View Javadoc

1   package org.andromda.cartridges.webservice.metafacades;
2   
3   import java.text.Collator;
4   import java.text.MessageFormat;
5   import java.util.ArrayList;
6   import java.util.Collection;
7   import java.util.Collections;
8   import java.util.Comparator;
9   import java.util.HashSet;
10  import java.util.Iterator;
11  import java.util.LinkedHashSet;
12  import java.util.List;
13  import java.util.Set;
14  import java.util.TreeSet;
15  
16  import org.andromda.cartridges.webservice.WebServiceGlobals;
17  import org.andromda.cartridges.webservice.WebServiceUtils;
18  import org.andromda.core.common.ExceptionUtils;
19  import org.andromda.core.common.Introspector;
20  import org.andromda.core.metafacade.MetafacadeException;
21  import org.andromda.metafacades.uml.AssociationEndFacade;
22  import org.andromda.metafacades.uml.AttributeFacade;
23  import org.andromda.metafacades.uml.ClassifierFacade;
24  import org.andromda.metafacades.uml.ModelElementFacade;
25  import org.andromda.metafacades.uml.OperationFacade;
26  import org.andromda.metafacades.uml.ParameterFacade;
27  import org.andromda.metafacades.uml.ServiceOperation;
28  import org.andromda.metafacades.uml.TypeMappings;
29  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
30  import org.andromda.metafacades.uml.UMLProfile;
31  import org.apache.commons.collections.Closure;
32  import org.apache.commons.collections.CollectionUtils;
33  import org.apache.commons.collections.Predicate;
34  import org.apache.commons.lang.ObjectUtils;
35  import org.apache.commons.lang.StringUtils;
36  
37  
38  /**
39   * MetafacadeLogic implementation for org.andromda.cartridges.webservice.metafacades.WebService.
40   *
41   * @see org.andromda.cartridges.webservice.metafacades.WebService
42   */
43  public class WebServiceLogicImpl
44      extends WebServiceLogic
45  {
46      // ---------------- constructor -------------------------------
47      public WebServiceLogicImpl(
48          Object metaObject,
49          String context)
50      {
51          super(metaObject, context);
52      }
53  
54      /**
55       * @see org.andromda.cartridges.webservice.metafacades.WebService#getAllowedOperations()
56       */
57      protected java.util.Collection handleGetAllowedOperations()
58      {
59          List operations = new ArrayList(this.getOperations());
60          CollectionUtils.filter(
61              operations,
62              new Predicate()
63              {
64                  public boolean evaluate(Object object)
65                  {
66                      boolean valid = WebServiceOperation.class.isAssignableFrom(object.getClass());
67                      if (valid)
68                      {
69                          valid = ((WebServiceOperation)object).isExposed();
70                      }
71                      return valid;
72                  }
73              });
74          if (this.getWSDLOperationSortMode().equals(OPERATION_SORT_MODE_NAME))
75          {
76              Collections.sort(
77                  operations,
78                  new OperationNameComparator());
79          }
80          return operations;
81      }
82  
83      /**
84       * @see org.andromda.cartridges.webservice.metafacades.WebService#getAllowedMethods()
85       */
86      protected java.lang.String handleGetAllowedMethods()
87      {
88          Collection methodNames = new ArrayList();
89          Collection operations = this.getAllowedOperations();
90          if (operations != null && !operations.isEmpty())
91          {
92              Iterator operationIt = operations.iterator();
93              while (operationIt.hasNext())
94              {
95                  OperationFacade operation = (OperationFacade)operationIt.next();
96                  methodNames.add(StringUtils.trimToEmpty(operation.getName()));
97              }
98          }
99          return StringUtils.join(
100             methodNames.iterator(),
101             " ");
102     }
103 
104     /**
105      * @see org.andromda.cartridges.webservice.metafacades.WebService#getQName()
106      */
107     protected String handleGetQName()
108     {
109         return MessageFormat.format(
110             this.getQualifiedNameLocalPartPattern(),
111             new Object[] {StringUtils.trimToEmpty(this.getName())});
112     }
113 
114     /**
115      * @see org.andromda.cartridges.webservice.metafacades.WebService#getNamespace()
116      */
117     protected java.lang.String handleGetNamespace()
118     {
119         String packageName = this.getPackageName();
120         if (this.isReverseNamespace())
121         {
122             packageName = WebServiceUtils.reversePackage(packageName);
123         }
124         return MessageFormat.format(
125             this.getNamespacePattern(),
126             new Object[] {StringUtils.trimToEmpty(packageName)});
127     }
128 
129     /**
130      * The property defining the default style to give the web services.
131      */
132     private static final String PROPERTY_DEFAULT_STYLE = "defaultStyle";
133 
134     /**
135      * @see org.andromda.cartridges.webservice.metafacades.WebService#getStyle()
136      */
137     protected java.lang.String handleGetStyle()
138     {
139         String style = (String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_WEBSERVICE_STYLE);
140         if (StringUtils.isEmpty(style))
141         {
142             style = String.valueOf(this.getConfiguredProperty(PROPERTY_DEFAULT_STYLE));
143         }
144         return style;
145     }
146 
147     /**
148      * The property defining the default style to give the web services.
149      */
150     private static final String PROPERTY_DEFAULT_USE = "defaultUse";
151 
152     /**
153      * @see org.andromda.cartridges.webservice.metafacades.WebService#getUse()
154      */
155     protected java.lang.String handleGetUse()
156     {
157         String use = (String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_WEBSERVICE_USE);
158         if (StringUtils.isEmpty(use))
159         {
160             use = String.valueOf(this.getConfiguredProperty(PROPERTY_DEFAULT_USE));
161         }
162         return use;
163     }
164 
165     /**
166      * Keeps track of whether or not the type has been checked, keeps us from entering infinite loops when calling
167      * loadTypes.
168      */
169     private Collection checkedTypes = new ArrayList();
170 
171     /**
172      * @see org.andromda.cartridges.webservice.metafacades.WebService#getTypeMappingElements()
173      */
174     protected java.util.Collection handleGetTypeMappingElements()
175     {
176         final Collection parameterTypes = new LinkedHashSet();
177         for (final Iterator iterator = this.getAllowedOperations().iterator(); iterator.hasNext();)
178         {
179             parameterTypes.addAll(((OperationFacade)iterator.next()).getParameters());
180         }
181 
182         final Set types = new TreeSet(new TypeComparator());
183         final Collection nonArrayTypes = new TreeSet(new TypeComparator());
184 
185         // clear out the cache of checkedTypes, otherwise
186         // they'll be ignored the second time this method is
187         // called (if the instance is reused)
188         this.checkedTypes.clear();
189         for (final Iterator iterator = parameterTypes.iterator(); iterator.hasNext();)
190         {
191             this.loadTypes((ModelElementFacade)iterator.next(), types, nonArrayTypes);
192         }
193 
194         final Collection exceptions = new ArrayList();
195         for (final Iterator iterator = this.getAllowedOperations().iterator(); iterator.hasNext();)
196         {
197             exceptions.addAll(((OperationFacade)iterator.next()).getExceptions());
198         }
199 
200         types.addAll(exceptions);
201 
202         // now since we're at the end, and we know the
203         // non array types won't override any other types
204         // (such as association ends) we
205         // add the non array types to the types
206         types.addAll(nonArrayTypes);
207         return types;
208     }
209 
210     /**
211      * <p> Loads all <code>types</code> and <code>nonArrayTypes</code> for
212      * the specified <code>type</code>. For each array type we collect the
213      * <code>nonArrayType</code>. Non array types are loaded seperately so
214      * that they are added at the end at the type collecting process. Since the
215      * types collection is a set (by the fullyQualifiedName) we don't want any
216      * non array types to override things such as association ends in the
217      * <code>types</code> collection.
218      * </p>
219      *
220      * @param type the type
221      * @param types the collection to load.
222      * @param nonArrayTypes the collection of non array types.
223      */
224     private void loadTypes(ModelElementFacade modelElement, Set types, Collection nonArrayTypes)
225     {
226         ExceptionUtils.checkNull("types", types);
227         ExceptionUtils.checkNull("nonArrayTypes", nonArrayTypes);
228 
229         try
230         {
231             if (modelElement != null && !this.checkedTypes.contains(modelElement))
232             {
233                 final ClassifierFacade parameterType = this.getType(modelElement);
234 
235                 // only continue if the model element has a type
236                 if (parameterType != null)
237                 {
238                     final Set allTypes = new HashSet();
239                     allTypes.add(parameterType);
240 
241                     // add all generalizations and specializations of the type
242                     final Collection generalizations = parameterType.getAllGeneralizations();
243 
244                     if (generalizations != null)
245                     {
246                         allTypes.addAll(generalizations);
247                     }
248 
249                     final Collection specializations = parameterType.getAllSpecializations();
250 
251                     if (specializations != null)
252                     {
253                         allTypes.addAll(specializations);
254                     }
255 
256                     this.checkedTypes.add(modelElement);
257 
258                     for (final Iterator allTypesIterator = allTypes.iterator(); allTypesIterator.hasNext();)
259                     {
260                         ClassifierFacade type = (ClassifierFacade) allTypesIterator.next();
261 
262                         if (!this.containsManyType(types, modelElement))
263                         {
264                             ClassifierFacade nonArrayType = type;
265                             final boolean arrayType = type.isArrayType();
266 
267                             if (arrayType || this.isValidAssociationEnd(modelElement))
268                             {
269                                 types.add(modelElement);
270 
271                                 if (arrayType)
272                                 {
273                                     // convert to non-array type since we
274                                     // check if that one has the stereotype
275                                     nonArrayType = type.getNonArray();
276 
277                                     // set the type to the non array type since
278                                     // that will have the attributes
279                                     type = nonArrayType;
280                                 }
281                             }
282 
283                             if (nonArrayType != null)
284                             {
285                                 if (nonArrayType.hasStereotype(UMLProfile.STEREOTYPE_VALUE_OBJECT)
286                                         || nonArrayType.isEnumeration())
287                                 {
288                                     // we add the type when its a non array and
289                                     // has the correct stereotype (even if we have
290                                     // added the array type above) since we need to
291                                     // define both an array and non array in the WSDL
292                                     // if we are defining an array.
293                                     nonArrayTypes.add(nonArrayType);
294                                 }
295                             }
296                         }
297 
298                         if (type != null)
299                         {
300                             final Collection properties = type.getProperties();
301                             if (properties != null && !properties.isEmpty())
302                             {
303                                 for (final Iterator iterator = properties.iterator(); iterator.hasNext();)
304                                 {
305                                     final ModelElementFacade property = (ModelElementFacade) iterator.next();
306                                     this.loadTypes(property, types, nonArrayTypes);
307                                 }
308                             }
309                         }
310                     }
311                 }
312             }
313         }
314         catch (final Throwable throwable)
315         {
316             final String message = "Error performing loadTypes";
317             throwable.printStackTrace();
318             logger.error(throwable);
319             throw new MetafacadeException(message, throwable);
320         }
321     }
322 
323     /**
324      * <p> Checks to see if the <code>types</code> collection contains the
325      * <code>modelElement</code>. It does this by checking to see if the
326      * model element is either an association end or some type of model element
327      * that has a type that's an array. If it's either an array <strong>OR
328      * </strong> an association end, then we check to see if the type is stored
329      * within the <code>types</code> collection. If so, we return true,
330      * otherwise we return false.
331      * </p>
332      *
333      * @param types the previously collected types.
334      * @param modelElement the model element to check to see if it represents a
335      *        <code>many</code> type
336      * @return true/false depending on whether or not the model element is a
337      *         many type.
338      */
339     private boolean containsManyType(
340         final Collection types,
341         final Object modelElement)
342     {
343         final ClassifierFacade compareType = this.getClassifier(modelElement);
344         boolean containsManyType = false;
345         if (compareType != null)
346         {
347             containsManyType =
348                 CollectionUtils.find(
349                     types,
350                     new Predicate()
351                     {
352                         public boolean evaluate(Object object)
353                         {
354                             return compareType.equals(getClassifier(object));
355                         }
356                     }) != null;
357         }
358         return containsManyType;
359     }
360 
361     /**
362      * Attempts to get the classifier attached to the given <code>element</code>.
363      *
364      * @param element the element from which to retrieve the classifier.
365      * @return the classifier if found, null otherwise
366      */
367     private ClassifierFacade getClassifier(final Object element)
368     {
369         ClassifierFacade type = null;
370         if (element instanceof AssociationEndFacade)
371         {
372             AssociationEndFacade end = (AssociationEndFacade)element;
373             if (end.isMany())
374             {
375                 type = ((AssociationEndFacade)element).getType();
376             }
377         }
378         else if (element instanceof AttributeFacade)
379         {
380             type = ((AttributeFacade)element).getType();
381         }
382         else if (element instanceof ParameterFacade)
383         {
384             type = ((ParameterFacade)element).getType();
385         }
386         if (element instanceof ClassifierFacade)
387         {
388             type = (ClassifierFacade)element;
389         }
390         if (type != null)
391         {
392             if (type.isArrayType())
393             {
394                 type = type.getNonArray();
395             }
396         }
397         return type;
398     }
399 
400     /**
401      * Returns true/false depending on whether or not this class represents a valid association end (meaning it has a
402      * multiplicify of many)
403      *
404      * @param modelElement the model element to check.
405      * @return true/false
406      */
407     private boolean isValidAssociationEnd(Object modelElement)
408     {
409         return modelElement instanceof AssociationEndFacade && ((AssociationEndFacade)modelElement).isMany();
410     }
411 
412     /**
413      * @see org.andromda.cartridges.webservice.metafacades.WebService#getProvider()
414      */
415     protected java.lang.String handleGetProvider()
416     {
417         String provider = (String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_WEBSERVICE_PROVIDER);
418         if (StringUtils.isEmpty(provider))
419         {
420             provider = (String)this.getConfiguredProperty("defaultProvider");
421         }
422         return provider;
423     }
424 
425     /**
426      * @see org.andromda.cartridges.webservice.metafacades.WebService#getWsdlFile()
427      */
428     protected java.lang.String handleGetWsdlFile()
429     {
430         return StringUtils.replace(
431             this.getFullyQualifiedName(),
432             String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)),
433             "/") + ".wsdl";
434     }
435 
436     /**
437      * We use this comparator to actually elimate duplicates instead of sorting like a comparator is normally used.
438      */
439     final class TypeComparator
440         implements Comparator
441     {
442         private final Collator collator = Collator.getInstance();
443 
444         TypeComparator()
445         {
446             collator.setStrength(Collator.PRIMARY);
447         }
448 
449         public int compare(
450             Object objectA,
451             Object objectB)
452         {
453             final ModelElementFacade a = (ModelElementFacade)objectA;
454             ModelElementFacade aType = getType(a);
455             if (aType == null)
456             {
457                 aType = a;
458             }
459             final ModelElementFacade b = (ModelElementFacade)objectB;
460             ModelElementFacade bType = getType(b);
461             if (bType == null)
462             {
463                 bType = b;
464             }
465             return collator.compare(
466                 aType.getFullyQualifiedName(),
467                 bType.getFullyQualifiedName());
468         }
469     }
470 
471     /**
472      * Gets the <code>type</code> or <code>returnType</code> of the model element (if the model element has a type or
473      * returnType).
474      *
475      * @param modelElement the model element we'll retrieve the type of.
476      */
477     protected ClassifierFacade getType(Object modelElement)
478     {
479         try
480         {
481             final Introspector introspector = Introspector.instance();
482             ClassifierFacade type = null;
483             String typeProperty = "type";
484 
485             // only continue if the model element has a type
486             if (introspector.isReadable(modelElement, typeProperty))
487             {
488                 type = (ClassifierFacade)introspector.getProperty(modelElement, typeProperty);
489             }
490 
491             // try for return type if type wasn't found
492             typeProperty = "returnType";
493             if (type == null && introspector.isReadable(modelElement, typeProperty))
494             {
495                 type = (ClassifierFacade)introspector.getProperty(modelElement, typeProperty);
496             }
497             return type;
498         }
499         catch (final Throwable throwable)
500         {
501             String errMsg = "Error performing WebServiceLogicImpl.getType";
502             logger.error(errMsg, throwable);
503             throw new MetafacadeException(errMsg, throwable);
504         }
505     }
506 
507     static final String NAMESPACE_PREFIX = "namespacePrefix";
508 
509     /**
510      * @see org.andromda.cartridges.webservice.metafacades.WSDLType#getNamespacePrefix()
511      */
512     protected String handleGetNamespacePrefix()
513     {
514         return (String)this.getConfiguredProperty(NAMESPACE_PREFIX);
515     }
516 
517     static final String QNAME_LOCAL_PART_PATTERN = "qualifiedNameLocalPartPattern";
518 
519     /**
520      * Gets the <code>qualifiedNameLocalPartPattern</code> for this service.
521      */
522     protected String getQualifiedNameLocalPartPattern()
523     {
524         return (String)this.getConfiguredProperty(QNAME_LOCAL_PART_PATTERN);
525     }
526 
527     static final String NAMESPACE_PATTERN = "namespacePattern";
528 
529     /**
530      * Gets the <code>namespacePattern</code> for this service.
531      *
532      * @return String the namespace pattern to use.
533      */
534     protected String getNamespacePattern()
535     {
536         return (String)this.getConfiguredProperty(NAMESPACE_PATTERN);
537     }
538 
539     static final String REVERSE_NAMESPACE = "reverseNamespace";
540 
541     /**
542      * Gets whether or not <code>reverseNamespace</code> is true/false for this type.
543      *
544      * @return boolean true/false
545      */
546     protected boolean isReverseNamespace()
547     {
548         return Boolean.valueOf(String.valueOf(this.getConfiguredProperty(REVERSE_NAMESPACE))).booleanValue();
549     }
550 
551     /**
552      * @see org.andromda.cartridges.webservice.metafacades.WebService#getEjbJndiName()
553      */
554     protected java.lang.String handleGetEjbJndiName()
555     {
556         StringBuffer jndiName = new StringBuffer();
557         String jndiNamePrefix = StringUtils.trimToEmpty(this.getEjbJndiNamePrefix());
558         if (StringUtils.isNotEmpty(jndiNamePrefix))
559         {
560             jndiName.append(jndiNamePrefix);
561             jndiName.append("/");
562         }
563         jndiName.append("ejb/");
564         jndiName.append(this.getFullyQualifiedName());
565         return jndiName.toString();
566     }
567 
568     /**
569      * Gets the <code>ejbJndiNamePrefix</code> for an EJB provider.
570      *
571      * @return the EJB Jndi name prefix.
572      */
573     protected String getEjbJndiNamePrefix()
574     {
575         final String property = "ejbJndiNamePrefix";
576         return this.isConfiguredProperty(property) ? ObjectUtils.toString(this.getConfiguredProperty(property)) : null;
577     }
578 
579     /**
580      * @see org.andromda.cartridges.webservice.metafacades.WebService#getEjbHomeInterface()
581      */
582     protected java.lang.String handleGetEjbHomeInterface()
583     {
584         return MessageFormat.format(
585             this.getEjbHomeInterfacePattern(),
586             new Object[] {StringUtils.trimToEmpty(this.getPackageName()), StringUtils.trimToEmpty(this.getName())});
587     }
588 
589     /**
590      * Gets the <code>ejbHomeInterfacePattern</code> for an EJB provider.
591      *
592      * @return the EJB Home interface pattern
593      */
594     protected String getEjbHomeInterfacePattern()
595     {
596         return (String)this.getConfiguredProperty("ejbHomeInterfacePattern");
597     }
598 
599     /**
600      * @see org.andromda.cartridges.webservice.metafacades.WebService#getEjbInterface()
601      */
602     protected java.lang.String handleGetEjbInterface()
603     {
604         return MessageFormat.format(
605             this.getEjbInterfacePattern(),
606             new Object[] {StringUtils.trimToEmpty(this.getPackageName()), StringUtils.trimToEmpty(this.getName())});
607     }
608 
609     /**
610      * Gets the <code>ejbInterfacePattern</code> for an EJB provider.
611      *
612      * @return the EJB interface pattern
613      */
614     protected String getEjbInterfacePattern()
615     {
616         return (String)this.getConfiguredProperty("ejbInterfacePattern");
617     }
618 
619     private static final String RPC_CLASS_NAME_PATTERN = "rpcClassNamePattern";
620 
621     /**
622      * Gets the <code>rpcClassNamePattern</code> for this service.
623      */
624     protected String getRpcClassNamePattern()
625     {
626         return (String)this.getConfiguredProperty(RPC_CLASS_NAME_PATTERN);
627     }
628 
629     /**
630      * @see org.andromda.cartridges.webservice.metafacades.WebService#getRpcClassName()
631      */
632     protected String handleGetRpcClassName()
633     {
634         return MessageFormat.format(
635             this.getRpcClassNamePattern(),
636             new Object[] {StringUtils.trimToEmpty(this.getPackageName()), StringUtils.trimToEmpty(this.getName())});
637     }
638 
639     private static final String WSDL_OPERATION_SORT_MODE = "wsdlOperationSortMode";
640 
641     /**
642      * Used to sort operations by <code>name</code>.
643      */
644     final static class OperationNameComparator
645         implements Comparator
646     {
647         private final Collator collator = Collator.getInstance();
648 
649         OperationNameComparator()
650         {
651             collator.setStrength(Collator.PRIMARY);
652         }
653 
654         public int compare(
655             Object objectA,
656             Object objectB)
657         {
658             ModelElementFacade a = (ModelElementFacade)objectA;
659             ModelElementFacade b = (ModelElementFacade)objectB;
660 
661             return collator.compare(
662                 a.getName(),
663                 b.getName());
664         }
665     }
666 
667     /**
668      * The model specifying operations should be sorted by name.
669      */
670     private static final String OPERATION_SORT_MODE_NAME = "name";
671 
672     /**
673      * The model specifying operations should NOT be sorted.
674      */
675     private static final String OPERATION_SORT_MODE_NONE = "none";
676 
677     /**
678      * Gets the sort mode WSDL operations.
679      *
680      * @return String
681      */
682     private String getWSDLOperationSortMode()
683     {
684         Object property = this.getConfiguredProperty(WSDL_OPERATION_SORT_MODE);
685         return property != null || property.equals(OPERATION_SORT_MODE_NAME) ? (String)property : OPERATION_SORT_MODE_NONE;
686     }
687 
688     /**
689      * @see org.andromda.cartridges.webservice.metafacades.WebService#isSecured()
690      */
691     protected boolean handleIsSecured()
692     {
693         Collection roles = this.getAllRoles();
694         return roles != null && !roles.isEmpty();
695     }
696 
697     /**
698      * Overridden to only allow the exposed operations in the returned roles collection.
699      *
700      * @see org.andromda.metafacades.uml.Service#getAllRoles()
701      */
702     public Collection getAllRoles()
703     {
704         final Collection roles = new LinkedHashSet(this.getRoles());
705         CollectionUtils.forAllDo(
706             this.getAllowedOperations(),
707             new Closure()
708             {
709                 public void execute(Object object)
710                 {
711                     if (object != null && ServiceOperation.class.isAssignableFrom(object.getClass()))
712                     {
713                         roles.addAll(((ServiceOperation)object).getRoles());
714                     }
715                 }
716             });
717         return roles;
718     }
719 
720     /**
721      * The pattern used to construct the test package name.
722      */
723     private static final String TEST_PACKAGE_NAME_PATTERN = "testPackageNamePattern";
724 
725     /**
726      * @see org.andromda.cartridges.webservice.metafacades.WebService#getTestPackageName()
727      */
728     protected String handleGetTestPackageName()
729     {
730         return String.valueOf(this.getConfiguredProperty(TEST_PACKAGE_NAME_PATTERN)).replaceAll(
731             "\\{0\\}",
732             this.getPackageName());
733     }
734 
735     /**
736      * @see org.andromda.cartridges.webservice.metafacades.WebService#getFullyQualifiedTestName()
737      */
738     protected String handleGetFullyQualifiedTestName()
739     {
740         return this.getTestPackageName() + '.' + this.getTestName();
741     }
742 
743     /**
744      * The pattern used to construct the test name.
745      */
746     private static final String TEST_NAME_PATTERN = "testNamePattern";
747 
748     /**
749      * @see org.andromda.cartridges.webservice.metafacades.WebService#getTestName()
750      */
751     protected String handleGetTestName()
752     {
753         return String.valueOf(this.getConfiguredProperty(TEST_NAME_PATTERN)).replaceAll(
754             "\\{0\\}",
755             this.getName());
756     }
757 
758     /**
759      * Represents a "wrapped" style.
760      */
761     private static final String STYLE_WRAPPED = "wrapped";
762 
763     /**
764      * @see org.andromda.cartridges.webservice.metafacades.WebService#isWrappedStyle()
765      */
766     protected boolean handleIsWrappedStyle()
767     {
768         return this.getStyle().equalsIgnoreCase(STYLE_WRAPPED);
769     }
770 
771     /**
772      * Represents a "document" style.
773      */
774     private static final String STYLE_DOCUMENT = "document";
775 
776     /**
777      * @see org.andromda.cartridges.webservice.metafacades.WebService#isDocumentStyle()
778      */
779     protected boolean handleIsDocumentStyle()
780     {
781         return this.getStyle().equalsIgnoreCase(STYLE_DOCUMENT);
782     }
783 
784     /**
785      * Represents a "rpc" style.
786      */
787     private static final String STYLE_RPC = "rpc";
788 
789     /**
790      * @see org.andromda.cartridges.webservice.metafacades.WebService#isRpcStyle()
791      */
792     protected boolean handleIsRpcStyle()
793     {
794         return this.getStyle().equalsIgnoreCase(STYLE_RPC);
795     }
796 
797     /**
798      * Represents an "literal" use.
799      */
800     private static final String USE_LITERAL = "literal";
801 
802     /**
803      * @see org.andromda.cartridges.webservice.metafacades.WebService#isLiteralUse()
804      */
805     protected boolean handleIsLiteralUse()
806     {
807         return this.getStyle().equalsIgnoreCase(USE_LITERAL);
808     }
809 
810     /**
811      * Represents an "encoded" use.
812      */
813     private static final String USE_ENCODED = "encoded";
814 
815     /**
816      * @see org.andromda.cartridges.webservice.metafacades.WebService#isEncodedUse()
817      */
818     protected boolean handleIsEncodedUse()
819     {
820         return this.getStyle().equalsIgnoreCase(USE_ENCODED);
821     }
822 
823     /**
824      * The pattern used to construct the test implementation name.
825      */
826     private static final String TEST_IMPLEMENTATION_NAME_PATTERN = "testImplementationNamePattern";
827 
828     /**
829      * @see org.andromda.cartridges.webservice.metafacades.WebService#getTestImplementationName()
830      */
831     protected String handleGetTestImplementationName()
832     {
833         return String.valueOf(this.getConfiguredProperty(TEST_IMPLEMENTATION_NAME_PATTERN)).replaceAll(
834             "\\{0\\}",
835             this.getName());
836     }
837 
838     /**
839      * @see org.andromda.cartridges.webservice.metafacades.WebService#getFullyQualifiedTestImplementationName()
840      */
841     protected String handleGetFullyQualifiedTestImplementationName()
842     {
843         return this.getTestPackageName() + '.' + this.getTestImplementationName();
844     }
845 
846     /**
847 
848      * @see org.andromda.cartridges.webservice.metafacades.WebService#getSchemaMappings()
849      */
850     protected TypeMappings handleGetSchemaMappings()
851     {
852         final String propertyName = WebServiceGlobals.SCHEMA_TYPE_MAPPINGS_URI;
853         Object property = this.getConfiguredProperty(propertyName);
854         TypeMappings mappings = null;
855         String uri = null;
856         if (property instanceof String)
857         {
858             uri = (String)property;
859             try
860             {
861                 mappings = TypeMappings.getInstance(uri);
862                 mappings.setArraySuffix(this.getArraySuffix());
863                 this.setProperty(propertyName, mappings);
864             }
865             catch (Throwable th)
866             {
867                 String errMsg = "Error getting '" + propertyName + "' --> '" + uri + "'";
868                 logger.error(errMsg, th);
869                 // don't throw the exception
870             }
871         }
872         else
873         {
874             mappings = (TypeMappings)property;
875         }
876         return mappings;
877     }
878 
879     /**
880      * Gets the array suffix from the configured metafacade properties.
881      *
882      * @return the array suffix.
883      */
884     private String getArraySuffix()
885     {
886         return String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ARRAY_NAME_SUFFIX));
887     }
888 
889     protected Collection handleGetAllowedOperationExceptions()
890     {
891         final Collection exceptions = new HashSet();
892 
893         // collect the exceptions of all allowed operations into a single set
894         for (Iterator i = this.getAllowedOperations().iterator(); i.hasNext();)
895         {
896             final OperationFacade operation = (OperationFacade)i.next();
897             exceptions.addAll(operation.getExceptions());
898         }
899 
900         return exceptions;
901     }
902 }