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.api.pattern;
36  
37  import java.text.MessageFormat;
38  
39  import javax.xml.namespace.QName;
40  
41  import org.apache.xmlbeans.XmlObject;
42  import org.ggf.schemas.jsdl.x2005.x11.jsdl.ApplicationType;
43  import org.ggf.schemas.jsdl.x2005.x11.jsdl.JobDefinitionDocument;
44  import org.ggf.schemas.jsdl.x2005.x11.jsdl.JobDefinitionType;
45  import org.ogf.graap.wsag.api.WsagConstants;
46  import org.ogf.schemas.graap.wsAgreement.ServiceDescriptionTermType;
47  import org.ogf.schemas.graap.wsAgreement.TermCompositorType;
48  
49  /**
50   * ChoosableComputeApplicationPattern
51   * 
52   * The term compositor contains a set of compute applications, where the client must choose on application out
53   * of the set.
54   * <p>
55   * 
56   * The protocol of this pattern is as follows. First one must select an application using
57   * {@link #selectApplication(ApplicationType)} or {@link #selectApplication(String, String)}. This service
58   * selection is instantly registered in the underlying term compositor.
59   * <p>
60   * 
61   * Subsequent modifications to the selected applications are possible by using functions such as
62   * {@link #getSelectedApplication()} or {@link #getSelectedJobDefinition()}. These modifications are not
63   * registered in the term compositor until {@link #updateSelectedApplication()} is executed. <br>
64   * 
65   * <pre>
66   * {@code
67   * <wsag:Template wsag:TemplateId="1"
68   *     xmlns:wsag="http://schemas.ggf.org/graap/2007/03/ws-agreement">
69   *     <wsag:Name>ComputeApplicationTemplate</wsag:Name>
70   *     <wsag:Context>
71   *         <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>
72   *         <wsag:TemplateId>1</wsag:TemplateId>
73   *         <wsag:TemplateName>ComputeApplicationTemplate</wsag:TemplateName>
74   *     </wsag:Context>
75   *     <wsag:Terms>
76   *         <wsag:All>
77   *             <wsag:ServiceDescriptionTerm wsag:Name="SDT_1"
78   *                 wsag:ServiceName="SERVICE_1">
79   *                 (Put your service description terms here ...)
80   *             </wsag:ServiceDescriptionTerm>
81   *             ...
82   *             <wsag:ExactlyOne>
83   *                 <wsag:ServiceDescriptionTerm wsag:Name="APPLICATION_SDT"
84   *                    wsag:ServiceName="CHANGE_ME">
85   *                     <jsdl:JobDefinition xmlns:jsdl="http://schemas.ggf.org/jsdl/2005/11/jsdl">
86   *                         <jsdl:JobDescription>
87   *                             <jsdl:Application>
88   *                                 <jsdl:ApplicationName>MyApp</jsdl:ApplicationName>
89   *                                 <jsdl:ApplicationVersion></jsdl:ApplicationVersion>
90   *                                 <jsdl:Description>Description</jsdl:Description>
91   *                             </jsdl:Application>
92   *                         </jsdl:JobDescription>
93   *                     </jsdl:JobDefinition>
94   *                 </wsag:ServiceDescriptionTerm>
95   *                 <wsag:ServiceDescriptionTerm wsag:Name="APPLICATION_SDT"
96   *                     wsag:ServiceName="CHANGE_ME">
97   *                     <jsdl:JobDefinition xmlns:jsdl="http://schemas.ggf.org/jsdl/2005/11/jsdl">
98   *                         <jsdl:JobDescription>
99   *                             <jsdl:Application>
100  *                                 <jsdl:ApplicationName></jsdl:ApplicationName>
101  *                                 <jsdl:ApplicationVersion></jsdl:ApplicationVersion>
102  *                                 <jsdl:Description>Description</jsdl:Description>
103  *                             </jsdl:Application>
104  *                         </jsdl:JobDescription>
105  *                     </jsdl:JobDefinition>
106  *                 </wsag:ServiceDescriptionTerm>
107  *             </wsag:ExactlyOne>
108  *         </wsag:All>
109  *     </wsag:Terms>
110  *     <wsag:CreationConstraints />
111  * </wsag:Template>
112  * }
113  * </pre>
114  * 
115  * @author Oliver Waeldrich
116  * @author Dominic Battre
117  * 
118  * 
119  */
120 public class ChoosableComputeApplicationPattern extends AbstractPattern
121 {
122 
123     private static final QName EXACTLY_ONE_QNAME = new QName( WsagConstants.NAMESPACE_URI, "ExactlyOne" );
124 
125     private ServiceDescriptionTermType selectedApplicationSDT;
126 
127     private ServiceDescriptionTermType[] applicationSDTs;
128 
129     private ApplicationType[] applicationDefinitions;
130 
131     private String appliationDescXPath =
132         "declare namespace wsag='http://schemas.ggf.org/graap/2007/03/ws-agreement';"
133             + "$this/wsag:ServiceDescriptionTerm[@wsag:Name = 'APPLICATION_SDT' ]";
134 
135     private String appliationXPath = "declare namespace jsdl='http://schemas.ggf.org/jsdl/2005/11/jsdl';"
136         + "$this/jsdl:JobDefinition/jsdl:JobDescription/jsdl:Application";
137 
138     /**
139      * Instantiates the pattern for the given term compositor.
140      * 
141      * @param termCompositor
142      *            the term compositor
143      */
144     public ChoosableComputeApplicationPattern( TermCompositorType termCompositor )
145     {
146         super( termCompositor );
147 
148         //
149         // check that the pattern is applied to an ExactlyOne term compositor
150         //
151         String localName = termCompositor.getDomNode().getLocalName();
152         String namespaceURI = termCompositor.getDomNode().getNamespaceURI();
153 
154         QName compositorName = new QName( namespaceURI, localName );
155 
156         if ( !EXACTLY_ONE_QNAME.equals( compositorName ) )
157         {
158             String msgError =
159                 "Tried to apply {0} to {1} term compositor. "
160                     + "This pattern can only be applied to wsag:ExactlyOne term compositor.";
161             String error =
162                 MessageFormat.format( msgError, new Object[] { getClass().getName(), compositorName } );
163             throw new IllegalStateException( error );
164         }
165 
166         if ( ( termCompositor.getAllArray().length > 0 ) || ( termCompositor.getExactlyOneArray().length > 0 )
167             || ( termCompositor.getOneOrMoreArray().length > 0 ) )
168         {
169 
170             String msgError =
171                 "A ChoosableComputeApplicationPattern must not contain any other term compositor.";
172             throw new IllegalStateException( msgError );
173         }
174 
175         if ( ( termCompositor.getGuaranteeTermArray().length > 0 )
176             || ( termCompositor.getServicePropertiesArray().length > 0 )
177             || ( termCompositor.getServiceReferenceArray().length > 0 ) )
178         {
179 
180             String msgError =
181                 "A ChoosableComputeApplicationPattern must not contain any Service Properties, "
182                     + "Service References, or Guarantee terms.";
183             throw new IllegalStateException( msgError );
184         }
185 
186         initialize();
187     }
188 
189     private void initialize()
190     {
191         //
192         // select the application SDTs and the applications
193         //
194         XmlObject[] applicationDescriptions = getTermCompositor().selectPath( getAppliationDescXPath() );
195 
196         applicationSDTs = new ServiceDescriptionTermType[applicationDescriptions.length];
197         applicationDefinitions = new ApplicationType[applicationDescriptions.length];
198 
199         for ( int i = 0; i < applicationDescriptions.length; i++ )
200         {
201             applicationSDTs[i] = (ServiceDescriptionTermType) applicationDescriptions[i].copy();
202 
203             XmlObject[] selectedApps = applicationDescriptions[i].selectPath( getAppliationXPath() );
204             if ( selectedApps.length != 1 )
205             {
206                 String msgError = "APPLICATION_SDT must contain exactly 1 JSDL application definition.";
207                 throw new IllegalStateException( msgError );
208             }
209 
210             applicationDefinitions[i] = (ApplicationType) selectedApps[0].copy();
211         }
212 
213         //
214         // select application and set the chosen application for this term compositor
215         //
216         setSelectedApplication( applicationSDTs[0] );
217     }
218 
219     /**
220      * 
221      * @return the job definition of the selected application SDT
222      */
223     public JobDefinitionType getSelectedJobDefinition()
224     {
225         final QName jobDefQName = JobDefinitionDocument.type.getDocumentElementName();
226         return (JobDefinitionType) selectedApplicationSDT.selectChildren( jobDefQName )[0];
227     }
228 
229     /**
230      * @return the selected application
231      */
232     public ApplicationType getSelectedApplication()
233     {
234         return (ApplicationType) selectedApplicationSDT.selectPath( getAppliationXPath() )[0];
235     }
236 
237     /**
238      * Selects the application in the term compositor.
239      * 
240      * @param application
241      *            the application to select
242      * @return true, if the application was selected, otherwise false.
243      */
244     public boolean selectApplication( ApplicationType application )
245     {
246         return selectApplication( application.getApplicationName(), application.getApplicationVersion() );
247     }
248 
249     /**
250      * Selects the application wit the given name and version in the term compositor.
251      * 
252      * @param name
253      *            the application name
254      * @param version
255      *            the application version
256      * @return true, if the application was selected, otherwise false.
257      */
258     public boolean selectApplication( String name, String version )
259     {
260         name = ( name == null ) ? "" : name;
261 
262         for ( int i = 0; i < applicationDefinitions.length; i++ )
263         {
264             if ( name.equals( applicationDefinitions[i].getApplicationName() ) )
265             {
266 
267                 boolean match = false;
268 
269                 if ( version != null )
270                 {
271                     match = version.equals( applicationDefinitions[i].getApplicationVersion() );
272                 }
273                 else
274                 {
275                     match = applicationDefinitions[i].getApplicationVersion() == null;
276                 }
277 
278                 if ( match )
279                 {
280                     setSelectedApplication( applicationSDTs[i] );
281                     return true;
282                 }
283             }
284         }
285 
286         return false;
287     }
288 
289     private void setSelectedApplication( ServiceDescriptionTermType selected )
290     {
291         selectedApplicationSDT = (ServiceDescriptionTermType) selected.copy();
292         updateSelectedApplication();
293     }
294 
295     /**
296      * Updates the selected application in the term compositor. This method actually updates the XML document
297      * referenced by the term compositor.
298      */
299     public void updateSelectedApplication()
300     {
301         ServiceDescriptionTermType[] appSDT = new ServiceDescriptionTermType[] { selectedApplicationSDT };
302         getTermCompositor().setServiceDescriptionTermArray( appSDT );
303     }
304 
305     /**
306      * Lists all applications in the term compositor.
307      * 
308      * @return the applications contained in the term compositor.
309      */
310     public ApplicationType[] listApplications()
311     {
312         return applicationDefinitions;
313     }
314 
315     /**
316      * @param appliationDescXPath
317      *            the appliationDescXPath to set
318      */
319     public void setAppliationDescXPath( String appliationDescXPath )
320     {
321         this.appliationDescXPath = appliationDescXPath;
322     }
323 
324     /**
325      * @return the appliationDescXPath
326      */
327     public String getAppliationDescXPath()
328     {
329         return appliationDescXPath;
330     }
331 
332     /**
333      * @param appliationXPath
334      *            the appliationXPath to set
335      */
336     public void setAppliationXPath( String appliationXPath )
337     {
338         this.appliationXPath = appliationXPath;
339     }
340 
341     /**
342      * @return the appliationXPath
343      */
344     public String getAppliationXPath()
345     {
346         return appliationXPath;
347     }
348 
349 }