View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.server.actions.impl;
36  
37  import java.text.MessageFormat;
38  import java.util.Map;
39  
40  import org.apache.log4j.Logger;
41  import org.apache.xmlbeans.XmlObject;
42  import org.ogf.graap.wsag.api.Agreement;
43  import org.ogf.graap.wsag.api.AgreementOffer;
44  import org.ogf.graap.wsag.api.exceptions.AgreementFactoryException;
45  import org.ogf.graap.wsag.api.exceptions.NegotiationException;
46  import org.ogf.graap.wsag.api.logging.LogMessage;
47  import org.ogf.graap.wsag.server.actions.ActionInitializationException;
48  import org.ogf.graap.wsag.server.actions.IAction;
49  import org.ogf.graap.wsag.server.actions.ICreateAgreementAction;
50  import org.ogf.graap.wsag.server.actions.IGetTemplateAction;
51  import org.ogf.graap.wsag.server.actions.INegotiationAction;
52  import org.ogf.graap.wsag.server.api.IAgreementFactoryContext;
53  import org.ogf.graap.wsag.server.api.WsagSession;
54  import org.ogf.graap.wsag.server.api.WsagSessionManager;
55  import org.ogf.graap.wsag.server.engine.WsagEngine;
56  import org.ogf.graap.wsag4j.types.configuration.ImplementationConfigurationType;
57  import org.ogf.graap.wsag4j.types.engine.WSAG4JSessionDocument;
58  import org.ogf.graap.wsag4j.types.engine.WSAG4JSessionType;
59  import org.ogf.schemas.graap.wsAgreement.AgreementContextType;
60  import org.ogf.schemas.graap.wsAgreement.AgreementRoleType;
61  import org.ogf.schemas.graap.wsAgreement.AgreementTemplateType;
62  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferType;
63  import org.w3c.dom.Node;
64  
65  /**
66   * This class implements a WSAG4J agreement factory action. A factory action contains a set of strategies to
67   * generate an agreement template, to negotiate offers based on this template and to create agreements based
68   * on the template. The strategies are configured in the WSAG4J engine configuration file.
69   * 
70   * @see IGetTemplateAction
71   * @see INegotiationAction
72   * @see ICreateAgreementAction
73   * 
74   * @author Oliver Waeldrich
75   * 
76   */
77  public class AgreementFactoryAction
78      implements IAction
79  {
80  
81      private static final Logger LOG = Logger.getLogger( AgreementFactoryAction.class );
82  
83      private ICreateAgreementAction createAgreementAction;
84  
85      private IGetTemplateAction getTemplateAction;
86  
87      private INegotiationAction negotiationAction;
88  
89      private boolean useSession = false;
90  
91      private boolean supportsNegotiation = false;
92  
93      private String name;
94  
95      /**
96       * Creates a new {@link AgreementFactoryAction}.
97       * 
98       * @param templateAction
99       *            The {@link IGetTemplateAction} that is called to generate the agreement template for this
100      *            {@link AgreementFactoryAction}.
101      * 
102      * @param createAgreementAction
103      *            The {@link ICreateAgreementAction} that is called when an agreement is created based on the
104      *            template generated by this {@link AgreementFactoryAction}.
105      * 
106      * @param negotiationAction
107      *            The negotiation action that is called when a negotiation offer based on the agreement
108      *            template provided by this action was received.
109      */
110     public AgreementFactoryAction( IGetTemplateAction templateAction,
111                                    ICreateAgreementAction createAgreementAction,
112                                    INegotiationAction negotiationAction )
113     {
114         super();
115 
116         setGetTemplateAction( templateAction );
117         setCreateAgreementAction( createAgreementAction );
118         setNegotiationAction( negotiationAction );
119     }
120 
121     /**
122      * Indicates whether this action supports agreement negotiation or not. Negotiation is supported if the
123      * associated negotiation action is not null and not an instance of {@link NegotiationUnsupportedAction}
124      * 
125      * @return true, if negotiation is supported, otherwise false
126      * 
127      * @see #setNegotiationAction(INegotiationAction)
128      */
129     public boolean isNegotiationSupported()
130     {
131         return supportsNegotiation;
132     }
133 
134     /**
135      * Sets the template creation strategy for this factory action.
136      * 
137      * @param templateAction
138      *            the template creation strategy to set
139      */
140     public void setGetTemplateAction( IGetTemplateAction templateAction )
141     {
142         getTemplateAction = templateAction;
143     }
144 
145     /**
146      * Sets the SLA creation strategy for this factory action.
147      * 
148      * @param createAgreement
149      *            the agreement creation strategy to set
150      */
151     public void setCreateAgreementAction( ICreateAgreementAction createAgreement )
152     {
153         createAgreementAction = createAgreement;
154     }
155 
156     /**
157      * Sets the negotiation strategy for this factory action.
158      * 
159      * @param negotiationAction
160      *            the negotiation action to set
161      */
162     public void setNegotiationAction( INegotiationAction negotiationAction )
163     {
164         this.negotiationAction = negotiationAction;
165         if ( ( negotiationAction == null ) || ( negotiationAction instanceof NegotiationUnsupportedAction ) )
166         {
167             supportsNegotiation = false;
168         }
169         else
170         {
171             supportsNegotiation = true;
172         }
173     }
174 
175     /**
176      * {@inheritDoc}
177      * 
178      * @see org.ogf.graap.wsag.server.actions.IAction#initialize()
179      */
180     public void initialize() throws ActionInitializationException
181     {
182         if ( ( getTemplateAction == null ) || ( createAgreementAction == null ) )
183         {
184             throw new ActionInitializationException(
185                 "getTemplateAction and createAgreementAction must not be null." );
186         }
187 
188         try
189         {
190             getTemplateAction.initialize();
191             createAgreementAction.initialize();
192             negotiationAction.initialize();
193         }
194         catch ( Exception e )
195         {
196             //
197             // create error message and throw initialization exception
198             //
199             String detailsText =
200                 "Configured actions: GetTemplateAction [{0}], NegotiationAction: {1}), CreateAgreementAction: {2})";
201 
202             String details =
203                 LogMessage.format( detailsText, getTemplateAction.getClass().getName(),
204                     negotiationAction.getClass().getName(), createAgreementAction.getClass().getName() );
205 
206             String msgText =
207                 "Error while initializing AgreementFactoryAction. \nReason: {0} \nDetails: {1}";
208             String message = LogMessage.format( msgText, e.getMessage(), details );
209 
210             throw new ActionInitializationException( message, e );
211         }
212     }
213 
214     /**
215      * Returns the agreement template associated with this factory action.
216      * 
217      * @return the associated agreement template
218      * 
219      * @see AgreementTemplateType
220      */
221     public AgreementTemplateType getTemplate()
222     {
223 
224         AgreementTemplateType template = getTemplateAction.getTemplate();
225         template = (AgreementTemplateType) template.copy();
226 
227         if ( useSession )
228         {
229 
230             AgreementContextType context = template.getContext();
231 
232             //
233             // we create a new session for each time a template is requested
234             //
235             WsagSession session = WsagSessionManager.createSession();
236 
237             //
238             // If no context is defined in the template, we create a default context
239             //
240             if ( context == null )
241             {
242                 context = template.addNewContext();
243                 context.setTemplateId( template.getTemplateId() );
244                 context.setTemplateName( template.getName() );
245                 context.setServiceProvider( AgreementRoleType.AGREEMENT_RESPONDER );
246             }
247 
248             //
249             // finally, we create the session document and append it to the context
250             //
251             WSAG4JSessionDocument sessionDoc = WSAG4JSessionDocument.Factory.newInstance();
252             sessionDoc.addNewWSAG4JSession().setSessionID( session.getSessionId() );
253             Node imported =
254                 context.getDomNode().getOwnerDocument()
255                        .importNode( sessionDoc.getWSAG4JSession().getDomNode(), true );
256             context.getDomNode().appendChild( imported );
257         }
258 
259         return template;
260     }
261 
262     /**
263      * Invokes the create agreement strategy implemented by the {@link ICreateAgreementAction} which is set
264      * for this action
265      * 
266      * @param offer
267      *            the offer for which an agreement should be created
268      * 
269      * @return the agreement instance created by the {@link ICreateAgreementAction}
270      * 
271      * @throws AgreementFactoryException
272      *             the exception thrown by the {@link ICreateAgreementAction}
273      * 
274      * @see #setCreateAgreementAction(ICreateAgreementAction)
275      */
276     public Agreement createAgreement( AgreementOffer offer ) throws AgreementFactoryException
277     {
278         XmlObject[] sessionDocuments =
279             offer.getContext().selectChildren( WSAG4JSessionDocument.type.getDocumentElementName() );
280         if ( sessionDocuments.length > 0 )
281         {
282             if ( sessionDocuments.length > 1 )
283             {
284                 String message =
285                     "Found multiple wsag4j session documents in agreement context. Using the first, ignoring the rest.";
286                 LOG.warn( message );
287             }
288 
289             WSAG4JSessionType sessionToken = (WSAG4JSessionType) sessionDocuments[0];
290 
291             WsagSession session = WsagSessionManager.getSession( sessionToken.getSessionID() );
292             if ( session != null )
293             {
294                 WsagEngine.getWsagMessageContext().setSession( session );
295             }
296             else
297             {
298                 Object[] filler = new Object[] { sessionToken.getSessionID() };
299                 String message = MessageFormat.format( "WSAG4J session with id [{0}] not found.", filler );
300                 LOG.error( message );
301             }
302         }
303 
304         return createAgreementAction.createAgreement( offer );
305     }
306 
307     /**
308      * Implements the negotiation strategy for offers that are based on the template associated with this
309      * action.
310      * 
311      * @param quote
312      *            the quote to negotiate
313      * 
314      * @param context
315      *            implementation specific context
316      * 
317      * @return the counter offers produced by the negotiation strategy
318      * 
319      * @throws NegotiationException
320      *             An exception thrown by the negotiation strategy. See
321      *             {@link #setNegotiationAction(INegotiationAction)}.
322      * 
323      * @see INegotiationAction
324      */
325     public NegotiationOfferType[] negotiate( NegotiationOfferType quote, Map<String, Object> context )
326         throws NegotiationException
327     {
328 
329         //
330         // An agreement factory does not need to support negotiation.
331         // If no negotiation action is set, we throw an unsupported
332         // operation exception.
333         //
334         if ( negotiationAction == null )
335         {
336             String message = "Negotiation is not supported by this agreement factory";
337             throw new UnsupportedOperationException( message );
338         }
339 
340         return negotiationAction.negotiate( quote, context );
341     }
342 
343     /**
344      * @return true - if this {@link AgreementFactoryAction} is session aware. false - otherwise
345      */
346     public boolean isUsingSession()
347     {
348         return useSession;
349     }
350 
351     /**
352      * @param useSession
353      *            Specifies whether an {@link AgreementFactoryAction} is session aware or not.
354      */
355     public void setUseSession( boolean useSession )
356     {
357         this.useSession = useSession;
358     }
359 
360     /**
361      * @return The name configured for this action.
362      */
363     public String getName()
364     {
365         if ( name == null )
366         {
367             return getClass().getName();
368         }
369 
370         return name;
371     }
372 
373     /**
374      * @param name
375      *            Sets the name for this {@link AgreementFactoryAction}.
376      */
377     public void setName( String name )
378     {
379         this.name = name;
380     }
381 
382     /**
383      * <!-- begin-UML-doc --> The configuration of this {@link AgreementFactoryAction}. <!-- end-UML-doc -->
384      * 
385      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
386      */
387     private ImplementationConfigurationType actionConfiguration;
388 
389     /**
390      * <!-- begin-UML-doc --> Returns the configuration of this particular {@link AgreementFactoryAction}
391      * instance. <!-- end-UML-doc -->
392      * 
393      * @return The configuration of this {@link AgreementFactoryAction} instance.
394      * 
395      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
396      */
397     public ImplementationConfigurationType getActionConfiguration()
398     {
399         // begin-user-code
400         return actionConfiguration;
401         // end-user-code
402     }
403 
404     /**
405      * <!-- begin-UML-doc --> Sets the configuration for this object. <!-- end-UML-doc -->
406      * 
407      * @param configuration
408      *            The {@link AgreementFactoryAction} configuration to set.
409      * 
410      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
411      */
412     public void setActionConfiguration( ImplementationConfigurationType configuration )
413     {
414         // begin-user-code
415         this.actionConfiguration = configuration;
416         // end-user-code
417     }
418 
419     /**
420      * <!-- begin-UML-doc --> The context of the agreement factory where this action is deployed in. <!--
421      * end-UML-doc -->
422      * 
423      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
424      */
425     private IAgreementFactoryContext factoryContext;
426 
427     /**
428      * <!-- begin-UML-doc --> Allows implementations to access the context of the agreement factory in which
429      * this action was deployed. <!-- end-UML-doc -->
430      * 
431      * @return The context of the factory in which this action is deployed.
432      * 
433      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
434      */
435     public IAgreementFactoryContext getFactoryContext()
436     {
437         // begin-user-code
438         return factoryContext;
439         // end-user-code
440     }
441 
442     /**
443      * <!-- begin-UML-doc --> <!-- end-UML-doc -->
444      * 
445      * @param factoryContext
446      *            the factoryContext to set
447      * @generated "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
448      */
449     public void setFactoryContext( IAgreementFactoryContext factoryContext )
450     {
451         // begin-user-code
452         this.factoryContext = factoryContext;
453         // end-user-code
454     }
455 
456     /**
457      * 
458      * @return the negotiation strategy for a particular template
459      */
460     public INegotiationAction getNegotiationAction()
461     {
462         return negotiationAction;
463     }
464 }