001package org.andromda.cartridges.webservice;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Date;
007import java.util.HashSet;
008import java.util.LinkedHashSet;
009import java.util.List;
010import java.util.Map;
011import java.util.Set;
012import java.util.TreeMap;
013import java.util.TreeSet;
014import org.andromda.cartridges.webservice.metafacades.WSDLEnumerationType;
015import org.andromda.cartridges.webservice.metafacades.WSDLEnumerationTypeLogic;
016import org.andromda.cartridges.webservice.metafacades.WSDLType;
017import org.andromda.cartridges.webservice.metafacades.WSDLTypeAssociationEnd;
018import org.andromda.cartridges.webservice.metafacades.WSDLTypeAssociationEndLogic;
019import org.andromda.cartridges.webservice.metafacades.WSDLTypeAttributeLogic;
020import org.andromda.cartridges.webservice.metafacades.WSDLTypeLogic;
021import org.andromda.cartridges.webservice.metafacades.WebServiceLogicImpl;
022import org.andromda.cartridges.webservice.metafacades.WebServiceLogicImpl.OperationNameComparator;
023import org.andromda.cartridges.webservice.metafacades.WebServiceOperation;
024import org.andromda.cartridges.webservice.metafacades.WebServiceParameterLogic;
025import org.andromda.core.common.Introspector;
026import org.andromda.core.metafacade.MetafacadeBase;
027import org.andromda.core.metafacade.MetafacadeException;
028import org.andromda.metafacades.uml.AssociationEndFacade;
029import org.andromda.metafacades.uml.AttributeFacade;
030import org.andromda.metafacades.uml.ClassifierFacade;
031import org.andromda.metafacades.uml.DependencyFacade;
032import org.andromda.metafacades.uml.EnumerationFacade;
033import org.andromda.metafacades.uml.EnumerationLiteralFacade;
034import org.andromda.metafacades.uml.GeneralizableElementFacade;
035import org.andromda.metafacades.uml.ModelElementFacade;
036import org.andromda.metafacades.uml.OperationFacade;
037import org.andromda.metafacades.uml.PackageFacade;
038import org.andromda.metafacades.uml.ParameterFacade;
039import org.andromda.metafacades.uml.Role;
040import org.andromda.metafacades.uml.Service;
041import org.andromda.metafacades.uml.TypeMappings;
042import org.andromda.metafacades.uml.UMLProfile;
043import org.apache.commons.collections.Closure;
044import org.apache.commons.collections.CollectionUtils;
045import org.apache.commons.lang.StringUtils;
046import org.apache.commons.lang.time.FastDateFormat;
047import org.apache.log4j.Logger;
048
049/**
050 * Contains utilities used within the WebService cartridge.
051 *
052 * @author Chad Brandon
053 * @author Bob Fields
054 */
055public class WebServiceUtils
056{
057    /**
058     * The logger instance.
059     */
060    private static final Logger logger = Logger.getLogger(WebServiceUtils.class);
061
062    /**
063     * Retrieves all roles from the given <code>services</code> collection.
064     *
065     * @param services the collection services.
066     * @return all roles from the collection.
067     */
068    public Collection<Role> getAllRoles(Collection<Service> services)
069    {
070        final Collection<Role> allRoles = new LinkedHashSet<Role>();
071        CollectionUtils.forAllDo(services, new Closure()
072        {
073            public void execute(Object object)
074            {
075                if (object != null && Service.class.isAssignableFrom(object.getClass()))
076                {
077                    allRoles.addAll(((Service)object).getAllRoles());
078                }
079            }
080        });
081        return allRoles;
082    }
083
084    /**
085     * Cross reference between package name and namespace abbreviation, used to annotate foreign schema elements
086     */
087    private static Map<PackageFacade, String> packageAbbr = new TreeMap<PackageFacade, String>();
088
089    /**
090     * Creates a list of referenced packages for the service. Populates pkgAbbr static map.
091     * I tried this in the WebServiceLogicImpl metafacade but couldn't get repeatable results.
092     * Called from jaxws-included.xsd for CXF implementation
093     * @param service WebServiceLogicImpl The service for which to find referenced packages
094     * @param types Set<MetafacadeBase> of all serviceOperations, from $service.allowedOperations
095     * @param follow Follow Inheritance references $extensionInheritanceDisabled
096     * @return pkgRefs Collection<PackageFacade> - all referenced packages
097     */
098    public Collection<PackageFacade> getPackages(WebServiceLogicImpl service, Set<ModelElementFacade> types, boolean follow)
099    {
100        return setPkgAbbr(service, types, follow);
101    }
102
103    /** Adds the package namespace abbreviation for this package
104     * @param pkg Package for which to get the abbreviation. Uses a static Map so that
105     * all schemas globally for this model will use the same namespace abbreviations
106     * @param pkgAbbr Package Abbreviation to be added to namespace map
107     * @return PackageMap TreeMap of package <-> abbreviation cross references
108     */
109    public Map<PackageFacade, String> addPkgAbbr(PackageFacade pkg, String pkgAbbr)
110    {
111        if (packageAbbr==null)
112        {
113            packageAbbr = new TreeMap<PackageFacade, String>();
114        }
115        if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
116        {
117            if (packageAbbr.containsKey(pkg))
118            {
119                logger.debug(pkg + " abbreviation " + pkgAbbr + " already exists in Package namespace Map");
120            }
121            else
122            {
123                packageAbbr.put(pkg, pkgAbbr);
124            }
125        }
126        return packageAbbr;
127    }
128
129    /** Get the package namespace abbreviation for this package
130     * @param pkg Package for which to get the abbreviation. Uses a static Map so that
131     * all schemas globally for this model will use the same namespace abbreviations
132     * @return Package abbreviation nsX
133     */
134    public String getPkgAbbr(PackageFacade pkg)
135    {
136        return this.getPkgAbbr(pkg, null);
137    }
138
139    /** Get the package namespace abbreviation for this package
140     * @param pkg Package for which to get the abbreviation. Uses a static Map so that
141     * all schemas globally for this model will use the same namespace abbreviations
142     * @param currentPackage The package which is referencing the pkg. Return 'impl' if the same as pkg.
143     * @return Package abbreviation nsX
144     */
145    public String getPkgAbbr(PackageFacade pkg, PackageFacade currentPackage)
146    {
147        if (pkg==null)
148        {
149            logger.error("getPkgAbbr Null pkg " + packageAbbr.size() + ": " + packageAbbr);
150            return "impl";
151        }
152        if (currentPackage != null && pkg.getFullyQualifiedName().equals(currentPackage.getFullyQualifiedName()))
153        {
154            return "impl";
155        }
156        if (packageAbbr==null)
157        {
158            packageAbbr = new TreeMap<PackageFacade, String>();
159        }
160        String rtn = packageAbbr.get(pkg);
161        String pkgName = pkg.getFullyQualifiedName();
162        if (StringUtils.isEmpty(pkgName) || pkgName.startsWith("java.lang") || pkgName.startsWith("java.util")
163            || pkgName.endsWith("PrimitiveTypes") || pkgName.endsWith("datatype"))
164        {
165            // Assume simple types if no package
166            rtn="xs";
167        }
168        if (logger.isDebugEnabled())
169        {
170            logger.debug("getPkgAbbr " + pkg + ' ' + rtn + ' ' + packageAbbr.size() + ' ' + pkgName);
171        }
172        if (StringUtils.isEmpty(rtn))
173        {
174            rtn = (String)pkg.findTaggedValue(WebServiceGlobals.XML_XMLNS);
175            if (StringUtils.isEmpty(rtn))
176            {
177                // Package reference was never added originally - needs to be fixed in getPackageReferences()
178                int namespaceCount = packageAbbr.size()+1;
179                rtn = "ns" + namespaceCount;
180            }
181            packageAbbr.put(pkg, rtn);
182            if (logger.isDebugEnabled())
183            {
184                logger.debug("getPkgAbbr " + pkg + ' ' + rtn + ' ' + packageAbbr.size());
185            }
186            if (logger.isDebugEnabled())
187            {
188                logger.debug("Missing PkgAbbr for " + pkgName + ": added " + rtn);
189            }
190        }
191        return rtn;
192    }
193
194    /**
195     * Creates a list of sorted unique package names and namespace abbreviations for each one.
196     * Run this after running getTypeMappingElements(), to populate the namespace Map.
197     * Namespaces are in order ns1 through x
198     * @param types
199     * @return pkgAbbr
200     */
201    private Set<PackageFacade> setPkgAbbr(WebServiceLogicImpl service, Set<ModelElementFacade> types, boolean follow)
202    {
203        // Contains references to only packages needed from this service
204        Set<PackageFacade> pkgSet = new TreeSet<PackageFacade>();
205        if (logger.isDebugEnabled())
206        {
207            logger.debug(service.getName() + " setPkgAbbr");
208        }
209        int namespaceCount = packageAbbr.size() + 1;
210        PackageFacade pkg = (PackageFacade) service.getPackage();
211        String name = null;
212        if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
213        {
214            if (!pkgSet.contains(pkg))
215            {
216                pkgSet.add(pkg);
217            }
218            if (!packageAbbr.containsKey(pkg))
219            {
220                packageAbbr.put(pkg, "ns" + namespaceCount);
221                if (logger.isDebugEnabled())
222                {
223                    logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + service.getName() + " servicePackage");
224                }
225                namespaceCount++;
226            }
227        }
228        // Copy package names and abbreviations to package list
229        for (final WebServiceOperation op : service.getAllowedOperations())
230        {
231            for (final ModelElementFacade arg : (Collection<ModelElementFacade>)op.getExceptions())
232            {
233                pkg = (PackageFacade) arg.getPackage();
234                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
235                {
236                    if (!pkgSet.contains(pkg))
237                    {
238                        pkgSet.add(pkg);
239                    }
240                    if (!packageAbbr.containsKey(pkg))
241                    {
242                        packageAbbr.put(pkg, "ns" + namespaceCount);
243                        if (logger.isDebugEnabled())
244                        {
245                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + op.getName() + " getExceptions " + arg.getName());
246                        }
247                        namespaceCount++;
248                    }
249                }
250            }
251            for (final ParameterFacade arg : op.getParameters())
252            {
253                pkg = (PackageFacade) arg.getType().getPackage();
254                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
255                {
256                    if (!pkgSet.contains(pkg))
257                    {
258                        pkgSet.add(pkg);
259                    }
260                    if (!packageAbbr.containsKey(pkg))
261                    {
262                        packageAbbr.put(pkg, "ns" + namespaceCount);
263                        if (logger.isDebugEnabled())
264                        {
265                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + op.getName() + " getParameters " + arg.getName());
266                        }
267                        namespaceCount++;
268                    }
269                }
270            }
271            if (op.getReturnType()!=null)
272            {
273                pkg = (PackageFacade) op.getReturnType().getPackage();
274                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
275                {
276                    if (!pkgSet.contains(pkg))
277                    {
278                        pkgSet.add(pkg);
279                    }
280                    if (!packageAbbr.containsKey(pkg))
281                    {
282                        packageAbbr.put(pkg, "ns" + namespaceCount);
283                        if (logger.isDebugEnabled())
284                        {
285                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + op.getName() + " getReturnType " + op.getReturnType().getName());
286                        }
287                        namespaceCount++;
288                    }
289                }
290            }
291        }
292        for (final ModelElementFacade element : types)
293        {
294            ClassifierFacade facade = service.getType(element);
295            if (facade != null)
296            {
297                pkg = (PackageFacade) facade.getPackage();
298                if (logger.isDebugEnabled())
299                {
300                    name = facade.getName();
301                    logger.debug("setPkgAbbr facade " + pkg + '.' + name);
302                }
303                if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0)
304                {
305                    // This element is contained in this package, see what it references
306                    for (ModelElementFacade attr : (Collection<ModelElementFacade>)facade.getProperties(follow))
307                    {
308                        try
309                        {
310                            ClassifierFacade attrType = getType(attr);
311                            if (attrType != null)
312                            {
313                                pkg = (PackageFacade) attrType.getPackage();
314                                name = attrType.getName();
315                                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
316                                {
317                                    if (!pkgSet.contains(pkg))
318                                    {
319                                        pkgSet.add(pkg);
320                                    }
321                                    if (!packageAbbr.containsKey(pkg))
322                                    {
323                                        packageAbbr.put(pkg, "ns" + namespaceCount);
324                                        if (logger.isDebugEnabled())
325                                        {
326                                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + facade.getName());
327                                        }
328                                        namespaceCount++;
329                                    }
330                                }
331                            }
332                        }
333                        catch (RuntimeException e)
334                        {
335                            logger.debug("setPkgAbbr error in service " + service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + facade.getName());
336                        }
337                    }
338                    for (AssociationEndFacade otherEnd : (List<AssociationEndFacade>)facade.getNavigableConnectingEnds(follow))
339                    {
340                        try
341                        {
342                            ClassifierFacade endType = getType(otherEnd);
343                            if (endType != null)
344                            {
345                                pkg = (PackageFacade) endType.getPackage();
346                                name = endType.getName();
347                                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
348                                {
349                                    if (!pkgSet.contains(pkg))
350                                    {
351                                        pkgSet.add(pkg);
352                                    }
353                                    if (!packageAbbr.containsKey(pkg))
354                                    {
355                                        packageAbbr.put(pkg, "ns" + namespaceCount);
356                                        if (logger.isDebugEnabled())
357                                        {
358                                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + facade.getName());
359                                        }
360                                        namespaceCount++;
361                                    }
362                                }
363                            }
364                        }
365                        catch (RuntimeException e)
366                        {
367                            logger.debug("setPkgAbbr error in service " + service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + facade.getName());
368                        }
369                    }
370                }
371            }
372            // TODO remove 'else' and add ParameterFacade logic type
373            else if (element instanceof ClassifierFacade)
374            {
375                ClassifierFacade type = (ClassifierFacade)element;
376                if (getType(type) != null)
377                {
378                    type = getType(type);
379                }
380                pkg = (PackageFacade) type.getPackage();
381                if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0)
382                {
383                    //int cnt = type.getAttributes(follow).size();
384                    /*if (logger.isDebugEnabled())
385                    {
386                        logger.debug("WSDLTypeLogicImpl pkg=" + pkg + " name=" + type.getName() + " size=" + cnt + " propsize=" + type.getProperties(follow).size());
387                    }*/
388                    // Duplicates logic in jaxws-included.vsl so that referenced packages are the same.
389                    // Except that vsl uses getAttributes, not getProperties. getProperties returns all attributes, getAttributes does not.
390                    for (ModelElementFacade attr : (List<ModelElementFacade>)type.getProperties(follow))
391                    {
392                        try
393                        {
394                            ClassifierFacade attrType = getType(attr);
395                            if (getType(attrType) != null)
396                            {
397                                pkg = (PackageFacade) attrType.getPackage();
398                                name = attrType.getName();
399                                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
400                                {
401                                    if (!pkgSet.contains(pkg))
402                                    {
403                                        pkgSet.add(pkg);
404                                    }
405                                    if (!packageAbbr.containsKey(pkg))
406                                    {
407                                        packageAbbr.put(pkg, "ns" + namespaceCount);
408                                        if (logger.isDebugEnabled())
409                                        {
410                                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName() + '.' + name);
411                                        }
412                                        namespaceCount++;
413                                    }
414                                }
415                            }
416                        }
417                        catch (RuntimeException e)
418                        {
419                            logger.debug("setPkgAbbr error in service " + service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName() + ": " + e);
420                        }
421                    }
422                    for (AssociationEndFacade otherEnd : (List<AssociationEndFacade>)type.getNavigableConnectingEnds(follow))
423                    {
424                        try
425                        {
426                            ClassifierFacade endType = getType(otherEnd);
427                            if (endType != null)
428                            {
429                                pkg = (PackageFacade) endType.getPackage();
430                                name = endType.getName();
431                                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
432                                {
433                                    if (!pkgSet.contains(pkg))
434                                    {
435                                        pkgSet.add(pkg);
436                                    }
437                                    if (!packageAbbr.containsKey(pkg))
438                                    {
439                                        packageAbbr.put(pkg, "ns" + namespaceCount);
440                                        if (logger.isDebugEnabled())
441                                        {
442                                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName() + '.' + name);
443                                        }
444                                        namespaceCount++;
445                                    }
446                                }
447                            }
448                        }
449                        catch (RuntimeException e)
450                        {
451                            logger.debug("setPkgAbbr error in service " + service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName() + ": " + e);
452                        }
453                    }
454                }
455            }
456            else if (element instanceof AssociationEndFacade)
457            {
458                AssociationEndFacade type = (AssociationEndFacade)element;
459                facade = getType(type);
460                if (facade instanceof AssociationEndFacade)
461                {
462                    type = (AssociationEndFacade)facade;
463                }
464                pkg = (PackageFacade) type.getPackage();
465                if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0)
466                {
467                    if (facade != null && facade instanceof ClassifierFacade)
468                    {
469                        ClassifierFacade typeLogic = facade;
470                        pkg = (PackageFacade) typeLogic.getPackage();
471                        name = typeLogic.getName();
472                        if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
473                        {
474                            if (!pkgSet.contains(pkg))
475                            {
476                                pkgSet.add(pkg);
477                            }
478                            if (!packageAbbr.containsKey(pkg))
479                            {
480                                packageAbbr.put(pkg, "ns" + namespaceCount);
481                                if (logger.isDebugEnabled())
482                                {
483                                    logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName());
484                                }
485                                namespaceCount++;
486                            }
487                        }
488                    }
489                    else
490                    {
491                        if (logger.isDebugEnabled())
492                        {
493                            logger.debug("setPkgAbbr element association " + pkg + '.' + name);
494                        }
495                        name = type.getName();
496                        // Duplicates logic in wsdl.vsl so that referenced packages are the same.
497                        for (AssociationEndFacade otherEnd : (List<AssociationEndFacade>)type.getType().getNavigableConnectingEnds(follow))
498                        {
499                            try
500                            {
501                                ClassifierFacade endType = getType(otherEnd);
502                                if (endType != null)
503                                {
504                                    pkg = (PackageFacade) endType.getPackage();
505                                    name = endType.getName();
506                                    if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
507                                    {
508                                        if (!pkgSet.contains(pkg))
509                                        {
510                                            pkgSet.add(pkg);
511                                        }
512                                        if (!packageAbbr.containsKey(pkg))
513                                        {
514                                            packageAbbr.put(pkg, "ns" + namespaceCount);
515                                            if (logger.isDebugEnabled())
516                                            {
517                                                logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName());
518                                            }
519                                            namespaceCount++;
520                                        }
521                                    }
522                                }
523                            }
524                            catch (RuntimeException e)
525                            {
526                                logger.debug("setPkgAbbr error in service " + pkg + '.' + name + " ns" + namespaceCount);
527                            }
528                        }
529                    }
530                }
531            }
532            else if (element instanceof EnumerationFacade)
533            {
534                EnumerationFacade type = (EnumerationFacade)element;
535                if (getType(type) != null)
536                {
537                    type = (EnumerationFacade)getType(type);
538                }
539                pkg = (PackageFacade) type.getPackage();
540                if (pkg!=null && pkg.getFullyQualifiedName().indexOf('.') > 0)
541                {
542                    if (!pkgSet.contains(pkg))
543                    {
544                        pkgSet.add(pkg);
545                    }
546                    if (!packageAbbr.containsKey(pkg))
547                    {
548                        packageAbbr.put(pkg, "ns" + namespaceCount);
549                        if (logger.isDebugEnabled())
550                        {
551                            logger.debug(service.getName() + " ns" + namespaceCount + ' ' + pkg + ' ' + type.getName() + '.' + name);
552                        }
553                        namespaceCount++;
554                    }
555                }
556            }
557            else if (element.getName().endsWith("[]"))
558            {
559                // Ignore modeled array types - assume non-array type is already in the package
560            }
561            else
562            {
563                // Log the type so we can extend this logic later...
564                logger.error("setPkgAbbr Unexpected element in service " + pkg + '.' + name + " type: " + element);
565            }
566        }
567        return pkgSet;
568    }
569
570    /**
571     * Creates a list of referenced packages for each package.
572     * Run this after running getTypeMappingElements(), to populate the namespace Map and referenced imports from each namespace.
573     * @param service WebService containing WS operations with references.
574     * @param types Collection<String> of all schemaTypeMappings referenced in the WebService class operations
575     * @param packageName Package / namespace for which to find all related (referenced) packages
576     * @param follow Follow Inheritance references $extensionInheritanceDisabled
577     * @return pkgRefs
578     */
579    public Collection<PackageFacade> getPackageReferences(WebServiceLogicImpl service, Set<MetafacadeBase> types, String packageName, boolean follow)
580    {
581        Collection<PackageFacade> pkgRef = new TreeSet<PackageFacade>();
582        if (StringUtils.isNotBlank(packageName))
583        {
584            String name = null;
585            PackageFacade pkg = null;
586            String pkgRefs = "";
587            if (types!=null)
588            {
589                // Copy package names and collection of related packages to package references list
590                for (final MetafacadeBase element : types)
591                {
592                    ClassifierFacade facade = service.getType(element);
593                    if (facade != null)
594                    {
595                        pkg = (PackageFacade) facade.getPackage();
596                        if (logger.isDebugEnabled())
597                        {
598                            name = facade.getName();
599                            //logger.debug("getPackageReferences packageName=" + packageName + " facade " + pkg + "." + name);
600                        }
601                        if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0 && pkg.getFullyQualifiedName().equals(packageName))
602                        {
603                            // This element is contained in this package, see what it references
604                            // Add reference to immediate ancestor to import packages
605                            GeneralizableElementFacade generalization = facade.getGeneralization();
606                            if (generalization != null)
607                            {
608                                pkg = (PackageFacade) generalization.getPackage();
609                                if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg))
610                                {
611                                    pkgRef.add(pkg);
612                                    if (logger.isDebugEnabled())
613                                    {
614                                        pkgRefs += pkg + ",";
615                                        logger.debug("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name);
616                                    }
617                                }
618                            }
619                            for (ModelElementFacade attr : (List<ModelElementFacade>)facade.getProperties(follow))
620                            {
621                                try
622                                {
623                                    ClassifierFacade attrType = getType(attr);
624                                    if (attrType != null)
625                                    {
626                                        pkg = (PackageFacade) attrType.getPackage();
627                                        name = attrType.getName();
628                                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
629                                        {
630                                            pkgRef.add(pkg);
631                                            if (logger.isDebugEnabled())
632                                            {
633                                                pkgRefs += pkg + ",";
634                                                logger.debug("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name);
635                                            }
636                                        }
637                                    }
638                                }
639                                catch (RuntimeException e)
640                                {
641                                    logger.error("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name + ": " + e);
642                                }
643                            }
644                            for (final AssociationEndFacade endFacade : (List<AssociationEndFacade>)facade.getNavigableConnectingEnds(follow))
645                            {
646                                try
647                                {
648                                    if (getType(endFacade) != null)
649                                    {
650                                        ClassifierFacade otherEnd = getType(endFacade);
651                                        pkg = (PackageFacade) otherEnd.getPackage();
652                                        name = otherEnd.getName();
653                                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
654                                        {
655                                            pkgRef.add(pkg);
656                                            if (logger.isDebugEnabled())
657                                            {
658                                                pkgRefs += pkg + ",";
659                                                logger.debug("getPackageReferences packageName=" + packageName + " add facadeOtherEnd " + pkg + '.' + name);
660                                            }
661                                        }
662                                    }
663                                }
664                                catch (RuntimeException e)
665                                {
666                                    logger.error("getPackageReferences packageName=" + packageName + " add facadeOtherEnd " + pkg + '.' + name + ": " + e);
667                                }
668                            }
669                        }
670                    }
671                    // TODO remove 'else' and add ParameterFacade logic type
672                    else if (element instanceof ClassifierFacade)
673                    {
674                        ClassifierFacade type = (ClassifierFacade)element;
675                        if (getType(type) != null)
676                        {
677                            type = getType(type);
678                        }
679                        pkg = (PackageFacade) type.getPackage();
680                        if (logger.isDebugEnabled())
681                        {
682                            logger.debug("getPackageReferences packageName=" + packageName + " ClassifierFacade " + pkg + '.' + name);
683                        }
684                        if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0 && pkg.getFullyQualifiedName().equals(packageName))
685                        {
686                            // Duplicates logic in wsdl.vsl so that referenced packages are the same.
687                            for (ModelElementFacade attr : (List<ModelElementFacade>)type.getProperties(follow))
688                            {
689                                try
690                                {
691                                    ClassifierFacade attrType = getType(attr);
692                                    if (attrType != null)
693                                    {
694                                        pkg = (PackageFacade) attr.getPackage();
695                                        name = attr.getName();
696                                    }
697                                    if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
698                                    {
699                                        pkgRef.add(pkg);
700                                        if (logger.isDebugEnabled())
701                                        {
702                                            pkgRefs += pkg + ",";
703                                            logger.debug("getPackageReferences packageName=" + packageName + " add attribute " + pkg + '.' + name);
704                                        }
705                                    }
706                                }
707                                catch (RuntimeException e)
708                                {
709                                    logger.error("getPackageReferences packageName=" + packageName + " add attribute " + pkg + '.' + name + ": " + e);
710                                }
711                            }
712                            for (final Object object : type.getNavigableConnectingEnds(follow))
713                            {
714                                try
715                                {
716                                    ModelElementFacade endFacade = (ModelElementFacade)object;
717                                    if (getType(endFacade) != null)
718                                    {
719                                        ClassifierFacade otherEnd = getType(endFacade);
720                                        pkg = (PackageFacade) otherEnd.getPackage();
721                                        name = otherEnd.getName();
722                                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
723                                        {
724                                            pkgRef.add(pkg);
725                                            if (logger.isDebugEnabled())
726                                            {
727                                                pkgRefs += pkg + ",";
728                                                logger.debug("getPackageReferences packageName=" + packageName + " add otherEnd " + pkg + '.' + name);
729                                            }
730                                        }
731                                    }
732                                }
733                                catch (RuntimeException e)
734                                {
735                                    logger.error("getPackageReferences packageName=" + packageName + " add otherEnd " + pkg + '.' + name + ": " + e);
736                                }
737                            }
738                        }
739                    }
740                    else if (element instanceof AssociationEndFacade)
741                    {
742                        AssociationEndFacade type = (AssociationEndFacade)element;
743                        facade = getType(type);
744                        // TODO: When can ClassifierFacade ever be an instanceof AssociationEndFacade
745                        if (facade instanceof AssociationEndFacade)
746                        {
747                            type = (AssociationEndFacade)facade;
748                        }
749                        pkg = (PackageFacade) type.getPackage();
750                        if (logger.isDebugEnabled())
751                        {
752                            logger.debug("getPackageReferences packageName=" + packageName + " AssociationEndFacade " + pkg + '.' + name);
753                        }
754                        if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0 && pkg.getFullyQualifiedName().equals(packageName))
755                        {
756                            if (facade != null && facade instanceof ClassifierFacade)
757                            {
758                                ClassifierFacade typeLogic = facade;
759                                pkg = (PackageFacade) typeLogic.getPackage();
760                                if (logger.isDebugEnabled())
761                                {
762                                    name = typeLogic.getName();
763                                    logger.debug("getPackageReferences packageName=" + packageName + " element typeLogic " + pkg + '.' + name);
764                                }
765                                if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg))
766                                {
767                                    pkgRef.add(pkg);
768                                    if (logger.isDebugEnabled())
769                                    {
770                                        pkgRefs += pkg + ",";
771                                        logger.debug("getPackageReferences packageName=" + packageName + " add typeLogic " + pkg + '.' + name);
772                                    }
773                                }
774                            }
775                            else
776                            {
777                                if (logger.isDebugEnabled())
778                                {
779                                    logger.debug("getPackageReferences packageName=" + packageName + " element association " + pkg + '.' + name);
780                                }
781                                name = type.getName();
782                                // Duplicates logic in wsdl.vsl so that referenced packages are the same.
783                                for (final Object object : type.getType().getNavigableConnectingEnds(follow))
784                                {
785                                    try
786                                    {
787                                        ModelElementFacade endFacade = (ModelElementFacade)object;
788                                        if (getType(endFacade) != null)
789                                        {
790                                            ClassifierFacade otherEnd = getType(endFacade);
791                                            pkg = (PackageFacade) otherEnd.getPackage();
792                                            name = otherEnd.getName();
793                                            if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
794                                            {
795                                                pkgRef.add(pkg);
796                                                if (logger.isDebugEnabled())
797                                                {
798                                                    pkgRefs += pkg + ",";
799                                                    logger.debug("getPackageReferences packageName=" + packageName + " add otherEnd " + pkg + '.' + name);
800                                                }
801                                            }
802                                        }
803                                    }
804                                    catch (RuntimeException e)
805                                    {
806                                        logger.error("getPackageReferences packageName=" + packageName + " add otherEnd " + pkg + '.' + name + ": " + e);
807                                    }
808                                }
809                            }
810                        }
811                    }
812                    else if (element instanceof EnumerationFacade)
813                    {
814                        EnumerationFacade type = (EnumerationFacade)element;
815                        if (getType(type) != null)
816                        {
817                            type = (EnumerationFacade)getType(type);
818                        }
819                        pkg = (PackageFacade) type.getPackage();
820                        if (pkg != null && pkg.getFullyQualifiedName().indexOf('.') > 0 && pkg.getFullyQualifiedName().equals(packageName))
821                        {
822                            for (ModelElementFacade attr : (List<ModelElementFacade>)type.getAllProperties())
823                            {
824                                ClassifierFacade attrType = getType(attr);
825                                if (attrType != null)
826                                {
827                                    pkg = (PackageFacade) attr.getPackage();
828                                    name = attr.getName();
829                                }
830                                if (!pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
831                                {
832                                    pkgRef.add(pkg);
833                                    if (logger.isDebugEnabled())
834                                    {
835                                        pkgRefs += pkg + ",";
836                                        logger.debug("getPackageReferences packageName=" + packageName + " add enumeration attribute " + pkg + '.' + name);
837                                    }
838                                }
839                            }
840                        }
841                    }
842                    else if (element.getValidationName() != null && element.getValidationName().endsWith("[]"))
843                    {
844                        // Ignore modeled array types - assume non-array type is already in the package
845                    }
846                    else
847                    {
848                        // Log the type so we can extend this logic later...
849                        logger.error("getPackageReferences Unexpected element type in service " + packageName + '.' + name + " : " + element);
850                    }
851                }
852            }
853            if (packageName.equals(service.getPackageName()))
854            {
855                // Add references from the operations of the service package itself
856                for (WebServiceOperation op : service.getAllowedOperations())
857                {
858                    for (Object opit : op.getExceptions())
859                    {
860                        if (opit instanceof ModelElementFacade)
861                        {
862                            ModelElementFacade arg = (ModelElementFacade)opit;
863                            pkg = (PackageFacade) arg.getPackage();
864                            name = arg.getName();
865                        }
866                        else if (opit instanceof PackageFacade)
867                        {
868                            pkg = (PackageFacade) opit;
869                        }
870                        else if (opit instanceof WSDLType)
871                        {
872                            WSDLType type = (WSDLType) opit;
873                            if (!type.getAssociationEnds().isEmpty())
874                            {
875                                // Get the first Exception attribute (the FaultBean)
876                                ClassifierFacade fault = type.getAssociationEnds().get(0).getOtherEnd().getType();
877                                pkg = (PackageFacade) fault.getPackage();
878                                name = fault.getName();
879                            }
880                        }
881                        else
882                        {
883                            pkg = null;
884                        }
885                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(service.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
886                        {
887                            pkgRef.add(pkg);
888                            if (logger.isDebugEnabled())
889                            {
890                                pkgRefs += pkg + ",";
891                                logger.debug("getPackageReferences packageName=" + packageName + " add exception " + pkg + '.' + name);
892                            }
893                        }
894                    }
895                    for (final ParameterFacade arg : op.getParameters())
896                    {
897                        pkg = (PackageFacade) arg.getType().getPackage();
898                        name = arg.getType().getName();
899                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(service.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
900                        {
901                            pkgRef.add(pkg);
902                            if (logger.isDebugEnabled())
903                            {
904                                pkgRefs += pkg + ",";
905                                logger.debug("getPackageReferences packageName=" + packageName + " add parameter " + pkg + '.' + name);
906                            }
907                        }
908                    }
909                    if (op.getReturnType()!=null)
910                    {
911                        pkg = (PackageFacade) op.getReturnType().getPackage();
912                        name = op.getReturnType().getName();
913                        if (logger.isDebugEnabled())
914                        {
915                            logger.debug("getPackageReferences packageName=" + packageName + " return " + pkg + '.' + name);
916                        }
917                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(service.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
918                        {
919                            pkgRef.add(pkg);
920                            if (logger.isDebugEnabled())
921                            {
922                                pkgRefs += pkg + ",";
923                                logger.debug("getPackageReferences packageName=" + packageName + " add return " + pkg + '.' + name);
924                            }
925                        }
926                    }
927                }
928            }
929            if (logger.isDebugEnabled())
930            {
931                logger.debug("getPackageReferences packageName=" + packageName + ' ' + pkgRefs);
932            }
933        }
934        else
935        {
936            if (logger.isDebugEnabled())
937            {
938                logger.debug("getPackageReferences packageName=null");
939            }
940        }
941        return pkgRef;
942    }
943
944    /**
945     * Creates a list of referenced exception packages for each package.
946     * Populates schema reference list for import for the wsdl
947     * @param packageFacade Package / namespace for which to find all related (referenced) packages
948     * @return pkgRefs Collection<String> package names
949     */
950    public Collection<PackageFacade> getExceptionReferences(PackageFacade packageFacade)
951    {
952        Collection<PackageFacade> pkgRef = new TreeSet<PackageFacade>();
953        if (packageFacade != null)
954        {
955            String name = null;
956            PackageFacade pkg = null;
957            String packageName = packageFacade.getFullyQualifiedName();
958            @SuppressWarnings("unused")
959            String pkgRefs = "";
960            // Copy package names and collection of related packages to package references list
961            for (final ClassifierFacade classifier : packageFacade.getClasses())
962            {
963                //logger.debug("getPackageReferences packageName=" + packageName);
964                if (classifier != null)
965                {
966                    pkg = (PackageFacade) classifier.getPackage();
967                    if (classifier.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE))
968                    {
969                        // Add references from the operations of the service package itself
970                        for (final OperationFacade op : classifier.getOperations())
971                        {
972                            for (final ModelElementFacade arg : (Collection<ModelElementFacade>)op.getExceptions())
973                            {
974                                // TODO Why does MEF.getPackage return a ModelElementFacade instead of Package?
975                                pkg = (PackageFacade) arg.getPackage();
976                                if (pkg != null && !pkg.getFullyQualifiedName().equals(classifier.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
977                                {
978                                    pkgRef.add(pkg);
979                                    if (logger.isDebugEnabled())
980                                    {
981                                        pkgRefs += pkg + ",";
982                                        logger.debug("getPackageReferences packageName=" + packageName + " add parameter " + pkg + '.' + name);
983                                    }
984                                }
985                            }
986                        }
987                    }
988                }
989            }
990        }
991        return pkgRef;
992    }
993
994    /**
995     * Creates a list of referenced packages for each package.
996     * Populates schema reference list for import
997     * @param packageFacade Package / namespace for which to find all related (referenced) packages
998     * @param follow Follow Inheritance references $extensionInheritanceDisabled
999     * @return pkgRefs Collection<String> package names
1000     */
1001    public Collection<PackageFacade> getPackageReferences(PackageFacade packageFacade, boolean follow)
1002    {
1003        Collection<PackageFacade> pkgRef = new TreeSet<PackageFacade>();
1004        if (packageFacade != null)
1005        {
1006            String name = null;
1007            PackageFacade pkg = null;
1008            String packageName = packageFacade.getFullyQualifiedName();
1009            String pkgRefs = "";
1010            // Copy package names and collection of related packages to package references list
1011            for (final ClassifierFacade facade : packageFacade.getClasses())
1012            {
1013                //logger.debug("getPackageReferences packageName=" + packageName);
1014                if (facade != null)
1015                {
1016                    pkg = (PackageFacade) facade.getPackage();
1017                    if (logger.isDebugEnabled())
1018                    {
1019                        name = facade.getName();
1020                        logger.debug("getPackageReferences packageName=" + packageName + " facade " + pkg + '.' + name);
1021                    }
1022                    // Add reference to immediate ancestor to import packages
1023                    GeneralizableElementFacade generalization = facade.getGeneralization();
1024                    if (generalization != null)
1025                    {
1026                        pkg = (PackageFacade) generalization.getPackage();
1027                        if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg))
1028                        {
1029                            pkgRef.add(pkg);
1030                            if (logger.isDebugEnabled())
1031                            {
1032                                pkgRefs += pkg + ",";
1033                                logger.debug("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name);
1034                            }
1035                        }
1036                    }
1037                    if (facade.hasStereotype("ValueObject") || facade.hasStereotype("Exception") || facade.hasStereotype("UnexpectedException") || facade.hasStereotype("ApplicationException"))
1038                    {
1039                        // This element is contained in this package, see what it references
1040                        for (ModelElementFacade attr : (List<ModelElementFacade>)facade.getProperties(follow))
1041                        {
1042                            try
1043                            {
1044                                ClassifierFacade attrType = getType(attr);
1045                                if (attrType != null)
1046                                {
1047                                    pkg = (PackageFacade) attrType.getPackage();
1048                                    name = attrType.getName();
1049                                    if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
1050                                    {
1051                                        pkgRef.add(pkg);
1052                                        if (logger.isDebugEnabled())
1053                                        {
1054                                            pkgRefs += pkg + ",";
1055                                            logger.debug("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name);
1056                                        }
1057                                    }
1058                                }
1059                            }
1060                            catch (RuntimeException e)
1061                            {
1062                                logger.error("getPackageReferences packageName=" + packageName + " add facadeAttribute " + pkg + '.' + name + ": " + e);
1063                            }
1064                        }
1065                        for (final AssociationEndFacade endFacade : (List<AssociationEndFacade>)facade.getNavigableConnectingEnds(follow))
1066                        {
1067                            try
1068                            {
1069                                if (getType(endFacade) != null)
1070                                {
1071                                    ClassifierFacade otherEnd = getType(endFacade);
1072                                    pkg = (PackageFacade) otherEnd.getPackage();
1073                                    name = otherEnd.getName();
1074                                    if (pkg!=null && !pkg.getFullyQualifiedName().equals(packageName) && !pkgRef.contains(pkg) && pkg.getFullyQualifiedName().indexOf('.') > 0)
1075                                    {
1076                                        pkgRef.add(pkg);
1077                                        if (logger.isDebugEnabled())
1078                                        {
1079                                            pkgRefs += pkg + ",";
1080                                            logger.debug("getPackageReferences packageName=" + packageName + " add facadeOtherEnd " + pkg + '.' + name);
1081                                        }
1082                                    }
1083                                }
1084                            }
1085                            catch (RuntimeException e)
1086                            {
1087                                logger.error("getPackageReferences packageName=" + packageName + " add facadeOtherEnd " + pkg + '.' + name + ": " + e);
1088                            }
1089                        }
1090                    }
1091                    else if (facade.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE))
1092                    {
1093                        // Add references from the operations of the service package itself
1094                        for (final OperationFacade op : facade.getOperations())
1095                        {
1096                            for (final ModelElementFacade arg : (Collection<ModelElementFacade>)op.getExceptions())
1097                            {
1098                                // TODO Why does MEF.getPackage return a ModelElementFacade instead of Package?
1099                                pkg = (PackageFacade) arg.getPackage();
1100                                if (pkg != null && !pkg.getFullyQualifiedName().equals(facade.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
1101                                {
1102                                    pkgRef.add(pkg);
1103                                    if (logger.isDebugEnabled())
1104                                    {
1105                                        pkgRefs += pkg + ",";
1106                                        logger.debug("getPackageReferences packageName=" + packageName + " add parameter " + pkg + '.' + name);
1107                                    }
1108                                }
1109                            }
1110                            for (final ParameterFacade arg : op.getParameters())
1111                            {
1112                                pkg = (PackageFacade) arg.getType().getPackage();
1113                                name = arg.getType().getName();
1114                                if (pkg!=null && !pkg.getFullyQualifiedName().equals(facade.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
1115                                {
1116                                    pkgRef.add(pkg);
1117                                    if (logger.isDebugEnabled())
1118                                    {
1119                                        pkgRefs += pkg + ",";
1120                                        logger.debug("getPackageReferences packageName=" + packageName + " add parameter " + pkg + '.' + name);
1121                                    }
1122                                }
1123                            }
1124                            if (op.getReturnType()!=null)
1125                            {
1126                                pkg = (PackageFacade) op.getReturnType().getPackage();
1127                                name = op.getReturnType().getName();
1128                                if (pkg!=null && !pkg.getFullyQualifiedName().equals(facade.getPackageName()) && pkg.getFullyQualifiedName().indexOf('.') > 0 && !pkgRef.contains(pkg))
1129                                {
1130                                    pkgRef.add(pkg);
1131                                    if (logger.isDebugEnabled())
1132                                    {
1133                                        pkgRefs += pkg + ",";
1134                                        logger.debug("getPackageReferences packageName=" + packageName + " add return " + pkg + '.' + name);
1135                                    }
1136                                }
1137                            }
1138                        }
1139                    }
1140                    /*else if (facade.isEnumeration() || facade.hasStereotype("Enumeration"))
1141                    {
1142
1143                    }*/
1144                }
1145            }
1146            if (logger.isDebugEnabled())
1147            {
1148                logger.debug("getPackageReferences packageName=" + packageName + ' ' + pkgRefs);
1149            }
1150        }
1151        else
1152        {
1153            if (logger.isDebugEnabled())
1154            {
1155                logger.debug("getPackageReferences packageName=null");
1156            }
1157        }
1158        return pkgRef;
1159    }
1160
1161    /**
1162     * Get all operations under WebService or with WebServiceOperation in a package
1163     * @param packageFacade Package / namespace for which to find all service operations
1164     * @return operations
1165     */
1166    public List<WebServiceOperation> getAllowedOperations(PackageFacade packageFacade)
1167    {
1168        List<WebServiceOperation> operations = new ArrayList<WebServiceOperation>();
1169        for (final ModelElementFacade mefacade : packageFacade.getOwnedElements())
1170        {
1171            if (mefacade != null && mefacade instanceof ClassifierFacade)
1172            {
1173                ClassifierFacade facade = (ClassifierFacade)mefacade;
1174                boolean webService = facade.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE);
1175                for (final OperationFacade op : facade.getOperations())
1176                {
1177                    boolean visibility = op.getVisibility().equals("public") || op.getVisibility().equals("protected");
1178                    if (visibility && (webService || op.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE_OPERATION)))
1179                    {
1180                        operations.add((WebServiceOperation) op);
1181                    }
1182                }
1183            }
1184        }
1185        // Always sort by name so that operations can be easily found in a long list.
1186        Collections.sort(
1187                operations,
1188                new OperationNameComparator());
1189        return operations;
1190    }
1191
1192    /**
1193     * Get all operations under WebService or with WebServiceOperation in a package
1194     * @param packageFacade Package / namespace for which to find all service operations
1195     * @return operations
1196     */
1197    public Collection<ModelElementFacade> getAllowedOperationExceptions(PackageFacade packageFacade)
1198    {
1199        final Collection<ModelElementFacade> exceptions = new HashSet<ModelElementFacade>();
1200
1201        // collect the exceptions of all allowed operations into a single set
1202        for (final OperationFacade operation : this.getAllowedOperations(packageFacade))
1203        {
1204            exceptions.addAll(operation.getExceptions());
1205        }
1206
1207        return exceptions;
1208    }
1209
1210    /**
1211     * Filter schema types list and related object to only a single package. Called for each referenced package.
1212     * Run this after running getTypeMappingElements(), to populate the namespace Map and referenced imports from each namespace.
1213     * @param packageFacade Package / namespace for which to find all related (referenced) packages
1214     * @param follow Follow Inheritance references $extensionInheritanceDisabled
1215     * @return pkgRefs
1216     */
1217    public Collection<ModelElementFacade> getPackageTypes(PackageFacade packageFacade, boolean follow)
1218    {
1219        Collection<ModelElementFacade> pkgTypes = new HashSet<ModelElementFacade>();
1220        if (packageFacade != null)
1221        {
1222            String name = null;
1223            String pkg = null;
1224            String packageName = packageFacade.getFullyQualifiedName();
1225            String pkgRefs = "";
1226            // Copy package names and collection of related packages to package references list
1227            //ClassifierFacade facade = null;
1228            for (final ModelElementFacade mefacade : packageFacade.getOwnedElements())
1229            {
1230                if (logger.isDebugEnabled())
1231                {
1232                    logger.debug("getPackageTypes packageName=" + packageName + " element " + mefacade);
1233                }
1234                if (mefacade != null && mefacade instanceof ClassifierFacade)
1235                {
1236                    ClassifierFacade facade = (ClassifierFacade)mefacade;
1237                    if (logger.isDebugEnabled())
1238                    {
1239                        name = facade.getName();
1240                        logger.debug("getPackageTypes packageName=" + packageName + " facade " + name);
1241                    }
1242                    if (facade.hasStereotype("ValueObject"))
1243                    {
1244                        if (!pkgTypes.contains(facade))
1245                        {
1246                            pkgTypes.add(facade);
1247                            if (logger.isDebugEnabled())
1248                            {
1249                                name = facade.getName();
1250                                pkgRefs += name + ',';
1251                                logger.debug("getPackageTypes packageName=" + packageName + " add facadeValueObject " + name);
1252                            }
1253                        }
1254                    }
1255                    else if (facade.isEnumeration() || facade.hasStereotype("Enumeration"))
1256                    {
1257                        if (!pkgTypes.contains(facade))
1258                        {
1259                            pkgTypes.add(facade);
1260                            if (logger.isDebugEnabled())
1261                            {
1262                                name = facade.getName();
1263                                pkgRefs += name + ',';
1264                                logger.debug("getPackageTypes packageName=" + packageName + " add facadeEnumeration " + name);
1265                            }
1266                        }
1267                    }
1268                    else if (facade.hasStereotype("Exception") || facade.hasStereotype("ApplicationException")
1269                            || facade.hasStereotype("UnexpectedException") || facade.hasStereotype("WebFault"))
1270                    {
1271                        if (!pkgTypes.contains(facade))
1272                        {
1273                            pkgTypes.add(facade);
1274                            if (logger.isDebugEnabled())
1275                            {
1276                                name = facade.getName();
1277                                pkgRefs += name + ',';
1278                                logger.debug("getPackageTypes packageName=" + packageName + " add facadeEnumeration " + name);
1279                            }
1280                        }
1281                    }
1282                    else if (facade.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE))
1283                    {
1284                        // Add references from the operations of the service package itself
1285                        for (final OperationFacade op : facade.getOperations())
1286                        {
1287                            for (final ModelElementFacade arg : (Collection<ModelElementFacade>)op.getExceptions())
1288                            {
1289                                pkg = arg.getPackageName();
1290                                if (pkg!=null && pkg.equals(facade.getPackageName()) && pkg.indexOf('.') > 0 && !pkgTypes.contains(arg))
1291                                {
1292                                    pkgTypes.add(arg);
1293                                    if (logger.isDebugEnabled())
1294                                    {
1295                                        name = arg.getName();
1296                                        pkgRefs += name + ',';
1297                                        logger.debug("getPackageTypes packageName=" + packageName + " add exception " + pkg + '.' + name);
1298                                    }
1299                                }
1300                            }
1301                            for (final ParameterFacade arg : op.getParameters())
1302                            {
1303                                pkg = arg.getType().getPackageName();
1304                                name = arg.getType().getName();
1305                                //ClassifierFacade arg = ((ParameterFacade)opiterator.next()).getType();
1306                                //pkg = arg.getPackageName();
1307                                if (pkg!=null && pkg.equals(facade.getPackageName()) && pkg.indexOf('.') > 0 && !pkgTypes.contains(arg.getType()))
1308                                {
1309                                    pkgTypes.add(arg.getType());
1310                                    if (logger.isDebugEnabled())
1311                                    {
1312                                        name = arg.getName();
1313                                        pkgRefs += name + ',';
1314                                        logger.debug("getPackageTypes packageName=" + packageName + " add parameter " + pkg + '.' + name);
1315                                    }
1316                                }
1317                            }
1318                            if (op.getReturnType()!=null)
1319                            {
1320                                pkg = op.getReturnType().getPackageName();
1321                                if (logger.isDebugEnabled())
1322                                {
1323                                    name = op.getReturnType().getName();
1324                                    logger.debug("getPackageTypes packageName=" + packageName + " return " + pkg + '.' + name);
1325                                }
1326                                if (pkg!=null && pkg.equals(facade.getPackageName()) && pkg.indexOf('.') > 0 && !pkgTypes.contains(op.getReturnType()))
1327                                {
1328                                    pkgTypes.add(op.getReturnType());
1329                                    if (logger.isDebugEnabled())
1330                                    {
1331                                        pkgRefs += name + ',';
1332                                        logger.debug("getPackageTypes packageName=" + packageName + " add return " + pkg + '.' + name);
1333                                    }
1334                                }
1335                            }
1336                        }
1337                    }
1338                }
1339            }
1340            if (logger.isDebugEnabled())
1341            {
1342                logger.debug("getPackageTypes packageName=" + packageName + ' ' + pkgRefs);
1343            }
1344        }
1345        else
1346        {
1347            if (logger.isDebugEnabled())
1348            {
1349                logger.debug("getPackageTypes packageName=null");
1350            }
1351        }
1352        return pkgTypes;
1353    }
1354
1355    /**
1356     * Filter schema types list and related object to only a single package. Called for each referenced package.
1357     * Run this after running getTypeMappingElements(), to populate the namespace Map and referenced imports from each namespace.
1358     * @param service WebService containing WS operations with references.
1359     * @param types Collection<ModelElementFacade> of all schemaTypeMappings referenced in the WebService class operations
1360     * @param packageName Package / namespace for which to find all related (referenced) packages
1361     * @param follow Follow Inheritance references $extensionInheritanceDisabled
1362     * @return pkgRefs
1363     */
1364    public Collection<ModelElementFacade> getPackageTypes(WebServiceLogicImpl service, Set<MetafacadeBase> types, String packageName, boolean follow)
1365    {
1366        Collection<ModelElementFacade> pkgTypes = new TreeSet<ModelElementFacade>(service.new TypeComparator());
1367        if (StringUtils.isNotBlank(packageName))
1368        {
1369            String name = null;
1370            String pkg = null;
1371            String pkgRefs = "";
1372            // Copy package names and collection of related packages to package references list
1373            for (final MetafacadeBase element : types)
1374            {
1375                //TreeSet pkgRef = new TreeSet(new TypeComparator());
1376                ClassifierFacade facade = service.getType(element);
1377                if (facade != null)
1378                {
1379                    pkg = facade.getPackageName();
1380                    if (logger.isDebugEnabled())
1381                    {
1382                        name = facade.getName();
1383                        logger.debug("getPackageTypes packageName=" + packageName + " facade " + pkg + '.' + name);
1384                    }
1385                    if (pkg != null && pkg.indexOf('.') > 0 && pkg.equals(packageName) && !pkgTypes.contains(facade))
1386                    {
1387                        pkgTypes.add(facade);
1388                        if (logger.isDebugEnabled())
1389                        {
1390                            pkgRefs += facade.getName() + ',';
1391                            logger.debug("getPackageTypes packageName=" + packageName + " add facade " + facade.getPackageName() + '.' + facade.getName());
1392                        }
1393                    }
1394                    /*if (facade instanceof ClassifierFacade)
1395                    {
1396                        ClassifierFacade type = (ClassifierFacade)facade;
1397                        pkg = type.getPackageName();
1398                        name = type.getName();
1399                    }
1400                    else if (facade instanceof AssociationEndFacade)
1401                    {
1402                        AssociationEndFacade type = (AssociationEndFacade)facade;
1403                        pkg = type.getPackageName();
1404                        name = type.getName();
1405                    }*/
1406                }
1407                // TODO remove 'else' and add ParameterFacade logic type
1408                if (element instanceof ClassifierFacade)
1409                {
1410                    ClassifierFacade type = (ClassifierFacade)element;
1411                    facade = getType(type);
1412                    if (facade != null)
1413                    {
1414                        if (facade instanceof ClassifierFacade)
1415                        {
1416                            type = getType(type);
1417                        }
1418                    }
1419                    pkg = type.getPackageName();
1420                    if (logger.isDebugEnabled())
1421                    {
1422                        name = type.getName();
1423                        logger.debug("getPackageTypes packageName=" + packageName + " elementTypeLogic " + pkg + '.' + name);
1424                    }
1425                    if (pkg != null)
1426                    {
1427                        if (pkg.indexOf('.') > 0 && pkg.equals(packageName) && !pkgTypes.contains(type))
1428                        {
1429                            pkgTypes.add(type);
1430                            if (logger.isDebugEnabled())
1431                            {
1432                                pkgRefs += type.getName() + ',';
1433                                logger.debug("getPackageTypes packageName=" + packageName + " add typeLogic " + type.getPackageName() + '.' + type.getName());
1434                            }
1435                        }
1436                        if (logger.isDebugEnabled())
1437                        {
1438                            logger.debug("ClassifierFacade pkg=" + packageName + " refPkg=" + pkg + " name=" + type.getName());
1439                        }
1440                        // Duplicates logic in wsdl.vsl so that referenced packages are the same.
1441                        for (ModelElementFacade attr : (List<ModelElementFacade>)type.getProperties(follow))
1442                        {
1443                            try
1444                            {
1445                                ClassifierFacade attrType = getType(attr);
1446                                if (attrType != null)
1447                                {
1448                                    pkg = attrType.getPackageName();
1449                                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(attrType))
1450                                    {
1451                                        pkgTypes.add(attrType);
1452                                        if (logger.isDebugEnabled())
1453                                        {
1454                                            name = attrType.getName();
1455                                            pkgRefs += attrType.getName() + ',';
1456                                            logger.debug("getPackageTypes packageName=" + packageName + " add attr " + attrType.getPackageName() + '.' + attrType.getName());
1457                                        }
1458                                    }
1459                                }
1460                            }
1461                            catch (RuntimeException e)
1462                            {
1463                                logger.error("getPackageTypes packageName=" + packageName + " add attr " + pkg + '.' + name + ": " + e);
1464                            }
1465                        }
1466                    }
1467                }
1468                else if (element instanceof AssociationEndFacade)
1469                {
1470                    AssociationEndFacade type = (AssociationEndFacade)element;
1471                    facade = getType(type);
1472                    // TODO When can ClassifierFacade ever be an instanceof AssociationEndFacade
1473                    if (facade instanceof AssociationEndFacade)
1474                    {
1475                        type = (AssociationEndFacade)facade;
1476                    }
1477                    if (facade != null && facade instanceof ClassifierFacade)
1478                    {
1479                        ClassifierFacade typeLogic = facade;
1480                        pkg = typeLogic.getPackageName();
1481                        if (pkg != null && pkg.indexOf('.') > 0 && pkg.equals(packageName) && !pkgTypes.contains(typeLogic))
1482                        {
1483                            pkgTypes.add(typeLogic);
1484                            if (logger.isDebugEnabled())
1485                            {
1486                                name = typeLogic.getName();
1487                                pkgRefs += typeLogic.getName() + ',';
1488                                logger.debug("getPackageTypes packageName=" + packageName + " add typeLogic " + type.getPackageName() + '.' + type.getName());
1489                            }
1490                        }
1491                    }
1492                    else
1493                    {
1494                        pkg = type.getPackageName();
1495                        if (logger.isDebugEnabled())
1496                        {
1497                            name = type.getName();
1498                            logger.debug("getPackageTypes packageName=" + packageName + " associationEnd " + pkg + '.' + name);
1499                        }
1500                        if (pkg != null)
1501                        {
1502                            if (pkg.indexOf('.') > 0 && pkg.equals(packageName) && !pkgTypes.contains(type))
1503                            {
1504                                pkgTypes.add(type);
1505                                if (logger.isDebugEnabled())
1506                                {
1507                                    pkgRefs += type.getName() + ',';
1508                                    logger.debug("getPackageTypes packageName=" + packageName + " add typeAssoc " + type.getPackageName() + '.' + type.getName());
1509                                }
1510                            }
1511                            // Get the other end reference itself, then get the navigable connecting ends
1512                            try
1513                            {
1514                                AssociationEndFacade otherEnd = (type.getOtherEnd());
1515                                ClassifierFacade endType = getType(otherEnd);
1516                                if (endType != null)
1517                                {
1518                                    pkg = endType.getPackageName();
1519                                    if (logger.isDebugEnabled())
1520                                    {
1521                                        name = endType.getName();
1522                                        logger.debug("getPackageTypes packageName=" + packageName + " otherEnd " + pkg + '.' + name);
1523                                    }
1524                                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(endType))
1525                                    {
1526                                        pkgTypes.add(endType);
1527                                        if (logger.isDebugEnabled())
1528                                        {
1529                                            pkgRefs += endType.getName() + ',';
1530                                            logger.debug("getPackageTypes packageName=" + packageName + " add otherEnd " + endType.getPackageName() + '.' + otherEnd.getName());
1531                                        }
1532                                    }
1533                                }
1534                            }
1535                            catch (RuntimeException e)
1536                            {
1537                                logger.error("getPackageTypes packageName=" + packageName + " add otherEnd " + pkg + '.' + name + ": " + e);
1538                            }
1539                            // Duplicates logic in wsdl.vsl so that referenced packages are the same.
1540                            for (final Object object : type.getType().getNavigableConnectingEnds(follow))
1541                            {
1542                                ClassifierFacade otherEnd = null;
1543                                try
1544                                {
1545                                    AssociationEndFacade endFacade = (AssociationEndFacade)object;
1546                                    if (getType(endFacade) != null)
1547                                    {
1548                                        otherEnd = getType(endFacade);
1549                                        pkg = otherEnd.getPackageName();
1550                                        if (logger.isDebugEnabled())
1551                                        {
1552                                            name = otherEnd.getName();
1553                                            logger.debug("getPackageTypes packageName=" + packageName + " NavOtherEnd " + otherEnd.getPackageName() + '.' + otherEnd.getName());
1554                                        }
1555                                        if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(otherEnd))
1556                                        {
1557                                            pkgTypes.add(otherEnd);
1558                                            if (logger.isDebugEnabled())
1559                                            {
1560                                                pkgRefs += otherEnd.getName() + ',';
1561                                                logger.debug("getPackageTypes packageName=" + packageName + " add NavOtherEnd " + otherEnd.getPackageName() + '.' + otherEnd.getName());
1562                                            }
1563                                        }
1564                                    }
1565                                }
1566                                catch (RuntimeException e)
1567                                {
1568                                    if (otherEnd!=null)
1569                                    {
1570                                        logger.error("getPackageTypes packageName=" + packageName + " add NavOtherEnd " + otherEnd.getPackageName() + '.' + otherEnd.getName() + ": " + e);
1571                                    }
1572                                    else
1573                                    {
1574                                        logger.error("getPackageTypes packageName=" + packageName + " add NavOtherEnd " + type.getType().getPackageName() + '.' + type.getType().getName() + ": " + e);
1575                                    }
1576                                }
1577                            }
1578                        }
1579                    }
1580                }
1581                else if (element instanceof EnumerationFacade)
1582                {
1583                    EnumerationFacade type = (EnumerationFacade)element;
1584                    if (getType(type) != null)
1585                    {
1586                        type = (EnumerationFacade)getType(type);
1587                    }
1588                    pkg = type.getPackageName();
1589                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(type))
1590                    {
1591                        pkgTypes.add(type);
1592                        if (logger.isDebugEnabled())
1593                        {
1594                            pkgRefs += type.getName() + ',';
1595                            logger.debug("getPackageTypes packageName=" + packageName + " add NavOtherEnd " + type.getPackageName() + '.' + type.getName());
1596                        }
1597                    }
1598                }
1599                else if (facade != null && facade.getName().endsWith("[]"))
1600                {
1601                    // Ignore modeled array types - assume non-array type is already in the package
1602                }
1603                else
1604                {
1605                    // Log the type so we can extend this logic later...
1606                    logger.error("getPackageTypes Unexpected element in service " + pkg + '.' + element + " type: " + facade);
1607                }
1608            }
1609            // Add package types from the operations of the service package itself
1610            for (final WebServiceOperation op : service.getAllowedOperations())
1611            {
1612                for (final ModelElementFacade arg : (Collection<ModelElementFacade>)op.getExceptions())
1613                {
1614                    pkg = arg.getPackageName();
1615                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(arg))
1616                    {
1617                        pkgTypes.add(arg);
1618                        if (logger.isDebugEnabled())
1619                        {
1620                            name = arg.getName();
1621                            pkgRefs += arg.getName() + ',';
1622                            logger.debug("getPackageTypes packageName=" + packageName + " add service exception " + arg.getPackageName() + '.' + arg.getName());
1623                        }
1624                    }
1625                }
1626                for (final ParameterFacade arg : op.getParameters())
1627                {
1628                    pkg = arg.getType().getPackageName();
1629                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(arg.getType()))
1630                    {
1631                        pkgTypes.add(arg.getType());
1632                        if (logger.isDebugEnabled())
1633                        {
1634                            name = arg.getName();
1635                            pkgRefs += arg.getName() + ',';
1636                            logger.debug("getPackageTypes packageName=" + packageName + " add service parameter " + arg.getPackageName() + '.' + arg.getName());
1637                        }
1638                    }
1639                }
1640                if (op.getReturnType()!=null)
1641                {
1642                    pkg = op.getReturnType().getPackageName();
1643                    if (pkg!=null && pkg.equals(packageName) && pkg.indexOf('.') > 0 && !pkgTypes.contains(op.getReturnType()))
1644                    {
1645                        pkgTypes.add(op.getReturnType());
1646                        if (logger.isDebugEnabled())
1647                        {
1648                            name = op.getReturnType().getName();
1649                            pkgRefs += op.getReturnType().getName() + ',';
1650                            logger.debug("getPackageTypes packageName=" + packageName + " add service returnType " + op.getReturnType().getPackageName() + '.' + op.getReturnType().getName());
1651                        }
1652                    }
1653                }
1654            }
1655            if (logger.isDebugEnabled())
1656            {
1657                logger.debug("getPackageTypes packageName=" + packageName + ' ' + pkgRefs);
1658            }
1659        }
1660        else
1661        {
1662            if (logger.isDebugEnabled())
1663            {
1664                logger.debug("getPackageTypes packageName=null");
1665            }
1666        }
1667        return pkgTypes;
1668    }
1669
1670    /**
1671     * Gets the <code>type</code> or <code>returnType</code> of the model element (if the model element has a type or
1672     * returnType). Duplicate of method in WebServiceLogicImpl.
1673     *
1674     * @param modelElement the model element we'll retrieve the type of.
1675     * @return ClassifierFacade Type of modelElement Object
1676     */
1677    private ClassifierFacade getType(Object modelElement)
1678    {
1679        try
1680        {
1681            final Introspector introspector = Introspector.instance();
1682            ClassifierFacade type = null;
1683            String typeProperty = "type";
1684
1685            // only continue if the model element has a type
1686            if (introspector.isReadable(modelElement, typeProperty))
1687            {
1688                type = (ClassifierFacade)introspector.getProperty(modelElement, typeProperty);
1689            }
1690
1691            // try for return type if type wasn't found
1692            typeProperty = "returnType";
1693            if (type == null && introspector.isReadable(modelElement, typeProperty))
1694            {
1695                type = (ClassifierFacade)introspector.getProperty(modelElement, typeProperty);
1696            }
1697            return type;
1698        }
1699        catch (final Throwable throwable)
1700        {
1701            String errMsg = "Error performing WebServiceLogicImpl.getType";
1702            logger.error(errMsg, throwable);
1703            throw new MetafacadeException(errMsg, throwable);
1704        }
1705    }
1706
1707    /**
1708     * Determine if an object has schema complex types (associations, multiplicity > 1, or complex attributes).
1709     * Needed when useAttributes=true so wsdl/xsd outputs attributes instead of elements , no complex type element declarations.
1710     * If no complex types, only attribute declarations are needed in the object schema definition.
1711     * Sees if attribute packages are something other than java.lang, java,util, java.math.
1712     * @param facade Type to determine if it contains complex types
1713     * @param follow Follow inheritance hierarchy for type when determining complex types
1714     * @return pkgRefs
1715     */
1716    public boolean hasComplexTypes(ClassifierFacade facade, boolean follow)
1717    {
1718        boolean rtn = false;
1719        // Associations to other types are automatically complex, can only be elements
1720        if (!facade.getNavigableConnectingEnds(follow).isEmpty())
1721        {
1722            return true;
1723        }
1724        // Determine if attributes are multiple or anything other than simple types
1725        for (final Object obj : facade.getAttributes(follow))
1726        {
1727            AttributeFacade attr = (AttributeFacade)obj;
1728            if (attr.getUpper() > 1 || attr.getUpper() == -1)
1729            {
1730                return true;
1731            }
1732            // can't think of an easy way to determine simple type, just look at attribute package / type
1733            String pkg = attr.getType().getFullyQualifiedName(false);
1734            if (logger.isDebugEnabled())
1735            {
1736                String fqn = attr.getGetterSetterTypeName();
1737                String cpkg= attr.getType().getPackageName();
1738                logger.debug("attr=" + attr.getName() + " pkg=" + pkg + " fqn=" + fqn + " cpkg=" + cpkg);
1739            }
1740            if (StringUtils.isEmpty(pkg) || pkg.indexOf('.')<1)
1741            {
1742                //TODO: Make sure all types are mapped
1743                // Type mapping is missing? No FQN type, but xs:<type> is still output.
1744            }
1745            else if (pkg.length()<9)
1746            {
1747                // Assume complex type if package name is too short but still contains '.'
1748                return true;
1749            }
1750            else
1751            {
1752                pkg=pkg.substring(0, 9);
1753                if (!"java.lang".equals(pkg) && !"java.util".equals(pkg) && !"java.math".equals(pkg))
1754                {
1755                    return true;
1756                }
1757            }
1758        }
1759        return rtn;
1760    }
1761
1762    /**
1763     * Creates the package name from the element namespace, following the JAXB rules.
1764     * Reverse the hostname (separated by .)
1765     * Add the service context (separated by /)
1766     * Substitute underscore _ for dash - in name
1767     * Put _ in front of numeric values for package components.
1768     *
1769     * @param namespace the XML namespace.
1770     * @return the reversed package name.
1771     */
1772    public static String getPackageName(String namespace)
1773    {
1774        if (StringUtils.isBlank(namespace))
1775        {
1776            return "";
1777        }
1778        if (namespace.startsWith("http://"))
1779        {
1780            namespace = namespace.substring(7);
1781        }
1782        if (namespace.endsWith("/"))
1783        {
1784            namespace = namespace.substring(0, namespace.length()-1);
1785        }
1786        if (namespace.endsWith(".xsd"))
1787        {
1788            namespace = namespace.substring(0, namespace.length()-4);
1789        }
1790        String hostname = namespace;
1791        if (namespace.indexOf('/')>0)
1792        {
1793            hostname = namespace.substring(0, namespace.indexOf('/'));
1794            namespace = StringUtils.reverseDelimited(hostname, WebServiceGlobals.NAMESPACE_DELIMITER)
1795                + namespace.substring(namespace.indexOf('/'), namespace.length());
1796        }
1797        else
1798        {
1799            namespace = StringUtils.reverseDelimited(hostname, WebServiceGlobals.NAMESPACE_DELIMITER);
1800        }
1801        // TODO Change to tokenizer + pattern matcher
1802        /*StrTokenizer tok = new StrTokenizer(namespace, WebServiceGlobals.NAMESPACE_DELIMITER);
1803        for (String token : (List<String>)tok.getTokenList())
1804        {
1805            if (token.s)
1806        }*/
1807        namespace = StringUtils.replaceChars(namespace, '-', '_');
1808        namespace = StringUtils.replace(namespace, ".0", "_0");
1809        namespace = StringUtils.replace(namespace, ".1", "_1");
1810        namespace = StringUtils.replace(namespace, ".2", "_2");
1811        namespace = StringUtils.replace(namespace, ".3", "_3");
1812        namespace = StringUtils.replace(namespace, ".4", "_4");
1813        namespace = StringUtils.replace(namespace, ".5", "_5");
1814        namespace = StringUtils.replace(namespace, ".6", "_6");
1815        namespace = StringUtils.replace(namespace, ".7", "_7");
1816        namespace = StringUtils.replace(namespace, ".8", "_8");
1817        namespace = StringUtils.replace(namespace, ".9", "_9");
1818        namespace = StringUtils.replace(namespace, "$", "");
1819        namespace = StringUtils.replaceChars(namespace, '/', WebServiceGlobals.NAMESPACE_DELIMITER);
1820        namespace = StringUtils.replace(namespace, ".0", "._0");
1821        namespace = StringUtils.replace(namespace, ".1", "._1");
1822        namespace = StringUtils.replace(namespace, ".2", "._2");
1823        namespace = StringUtils.replace(namespace, ".3", "._3");
1824        namespace = StringUtils.replace(namespace, ".4", "._4");
1825        namespace = StringUtils.replace(namespace, ".5", "._5");
1826        namespace = StringUtils.replace(namespace, ".6", "._6");
1827        namespace = StringUtils.replace(namespace, ".7", "._7");
1828        namespace = StringUtils.replace(namespace, ".8", "._8");
1829        namespace = StringUtils.replace(namespace, ".9", "._9");
1830        return namespace;
1831    }
1832
1833    /**
1834     * Gets the fully qualified name of a class given the XML Element Name and namespace.
1835     * Assumes the namespace is the reversed package name.
1836     *
1837     * @param elementName the XML element name.
1838     * @param namespace the XML namespace for the element.
1839     * @return String the package + element name
1840     */
1841    public String getElementClassName(String elementName, String namespace)
1842    {
1843        if (StringUtils.isBlank(elementName) || StringUtils.isBlank(namespace))
1844        {
1845            return "";
1846        }
1847        return WebServiceUtils.reversePackage(namespace) + '.' + elementName;
1848    }
1849
1850    /**
1851     * Supplies a result for type = <new value>; initialization for all types
1852     * @param facade Type to create default object for
1853     * @return Constructor String with facade name
1854     */
1855    public String createConstructor(ModelElementFacade facade)
1856    {
1857        return createConstructor(facade, false);
1858    }
1859
1860    /**
1861     * Supplies a result for type = <new value>; initialization for all types
1862     * @param facade Type to create default object for
1863     * @param useMany Return constructor with multiplicity type instead of underlying type
1864     * @return Constructor String with facade name
1865     */
1866    public String createConstructor(ModelElementFacade facade, boolean useMany)
1867    {
1868        return createConstructor(facade, useMany, null);
1869    }
1870
1871    /**
1872     * Supplies a result for type = <new value>; initialization for all types
1873     * @param facade Type to create default object for
1874     * @param useMany Return constructor with multiplicity type instead of underlying type
1875     * @param parent Object containing this facade, which may have an attribute named dependency to a different type
1876     * @return Constructor String with facade name
1877     */
1878    @SuppressWarnings("null")
1879    public String createConstructor(ModelElementFacade facade, boolean useMany, ModelElementFacade parent)
1880    {
1881        if (facade==null)
1882        {
1883            return "facade was null";
1884        }
1885        String rtn = "";
1886        String toString = "";
1887        ClassifierFacade type = null;
1888        String typeName = facade.getFullyQualifiedName();
1889        String name = facade.getName();
1890        String defaultValue = "";
1891        // TODO: Default collection type from properties
1892        String collectionType = "java.util.ArrayList";
1893        Boolean isMany = null;
1894        boolean isEnumeration = false;
1895        /*if (parent != null)
1896        {
1897            // See if a named dependency exists with the same facadeName
1898            for (final DependencyFacade dependency : parent.getSourceDependencies())
1899            {
1900                if (dependency.getName().equals(facade.getName()) && dependency instanceof DependencyFacade)
1901                {
1902                    facade = ((DependencyFacade)dependency).getTargetElement();
1903                    toString = ".toString()";
1904                    break;
1905                }
1906            }
1907        }*/
1908        try {
1909            if (logger.isDebugEnabled())
1910            {
1911                logger.debug("facade=" + facade + " parent=" + parent + " useMany=" + useMany);
1912            }
1913            if (facade instanceof ClassifierFacade)
1914            {
1915                ClassifierFacade classifier = (ClassifierFacade) facade;
1916                type = classifier;
1917                typeName = classifier.getFullyQualifiedName();
1918            }
1919            if (facade instanceof AttributeFacade)
1920            {
1921                AttributeFacade attr = (AttributeFacade) facade;
1922                defaultValue = attr.getDefaultValue();
1923                type = attr.getType();
1924                if (useMany)
1925                {
1926                    typeName = attr.getGetterSetterTypeName();
1927                }
1928                else
1929                {
1930                    typeName = type.getFullyQualifiedName();
1931                }
1932                if (attr.getUpper()>1 || attr.getUpper()==-1)
1933                {
1934                    isMany = true;
1935                }
1936            }
1937            else if (facade instanceof WSDLTypeAttributeLogic)
1938            {
1939                WSDLTypeAttributeLogic attr = (WSDLTypeAttributeLogic) facade;
1940                defaultValue = attr.getDefaultValue();
1941                type = attr.getType();
1942                if (useMany)
1943                {
1944                    typeName = attr.getGetterSetterTypeName();
1945                }
1946                else
1947                {
1948                    typeName = type.getFullyQualifiedName();
1949                }
1950                if (attr.getUpper()>1 || attr.getUpper()==-1)
1951                {
1952                    isMany = true;
1953                }
1954            }
1955            else if (facade instanceof ParameterFacade)
1956            {
1957                ParameterFacade attr = (ParameterFacade) facade;
1958                defaultValue = attr.getDefaultValue();
1959                type = attr.getType();
1960                typeName = type.getFullyQualifiedName();
1961                if (type.isEnumeration())
1962                {
1963                    facade = type;
1964                }
1965                else if (useMany)
1966                {
1967                    typeName = collectionType + '<' + type.getFullyQualifiedName() + '>';
1968                }
1969                else
1970                {
1971                    typeName = type.getFullyQualifiedName();
1972                }
1973                if (attr.getUpper()>1 || attr.getUpper()==-1)
1974                {
1975                    isMany = true;
1976                }
1977            }
1978            if (facade instanceof AssociationEndFacade)
1979            {
1980                AssociationEndFacade attr = (AssociationEndFacade) facade;
1981                type = attr.getType();
1982                if (useMany)
1983                {
1984                    typeName = attr.getGetterSetterTypeName();
1985                }
1986                else
1987                {
1988                    typeName = type.getFullyQualifiedName();
1989                }
1990                if (attr.getUpper()>1 || attr.getUpper()==-1)
1991                {
1992                    isMany = true;
1993                }
1994                facade = attr.getType();
1995            }
1996            if (facade instanceof WSDLTypeAssociationEnd)
1997            {
1998                WSDLTypeAssociationEnd attr = (WSDLTypeAssociationEnd) facade;
1999                type = attr.getType();
2000                if (useMany)
2001                {
2002                    typeName = attr.getGetterSetterTypeName();
2003                }
2004                else
2005                {
2006                    typeName = type.getFullyQualifiedName();
2007                }
2008                if (attr.getUpper()>1 || attr.getUpper()==-1)
2009                {
2010                    isMany = true;
2011                }
2012                facade = attr.getType();
2013            }
2014            // TODO: Make this work for attribute types other than String.
2015            if (parent != null && StringUtils.isEmpty(defaultValue) && ("String".equals(typeName) || "java.lang.String".equals(typeName)))
2016            {
2017                // See if a named dependency exists with the same facadeName
2018                for (final DependencyFacade dependency : parent.getSourceDependencies())
2019                {
2020                    if (dependency.getName().equals(facade.getName()))
2021                    {
2022                        facade = dependency.getTargetElement();
2023                        // DependencyFacade type comes back empty for UML2::Integer
2024                        // Need to get metaObject Name property and verify it is not null.
2025                        if (facade instanceof WSDLTypeLogic)
2026                        {
2027                            WSDLTypeLogic wsdlType = (WSDLTypeLogic) facade;
2028                            if (logger.isDebugEnabled())
2029                            {
2030                                logger.debug(wsdlType + " fqn=" + wsdlType.getFullyQualifiedName() + " name="
2031                                    + wsdlType.getName() + " id=" + wsdlType.getId() + " properties="
2032                                    + wsdlType.getAllProperties() + " MetaObject=" + wsdlType.getMetaObject() + " properties="
2033                                    + wsdlType.getProperties());
2034                            }
2035                            if (StringUtils.isEmpty(wsdlType.getName()))
2036                            {
2037                                break;
2038                            }
2039                        }
2040                        if (facade instanceof ClassifierFacade)
2041                        {
2042                            type = (ClassifierFacade) facade;
2043                        }
2044                        typeName = facade.getFullyQualifiedName();
2045                        toString = ".toString()";
2046                        if (logger.isDebugEnabled())
2047                        {
2048                            logger.debug(parent + " " + facade + " = "
2049                                    + dependency + " type=" + type + " typeName="
2050                                    + typeName);
2051                        }
2052                        break;
2053                    }
2054                }
2055            }
2056            if (type instanceof WSDLEnumerationTypeLogic)
2057            {
2058                if (logger.isDebugEnabled())
2059                {
2060                    logger.debug("facade=" + facade + " type=" + type + " default=" + defaultValue);
2061                }
2062                WSDLEnumerationTypeLogic enumer = (WSDLEnumerationTypeLogic) type;
2063                //type = enumer.getLiteralType().getFullyQualifiedName();
2064                Collection<AttributeFacade> literals = enumer.getLiterals();
2065                if (StringUtils.isEmpty(defaultValue) && !literals.isEmpty())
2066                {
2067                    // Just get the first enumeration literal
2068                    Object literal = literals.iterator().next();
2069                    if (literal instanceof EnumerationLiteralFacade)
2070                    {
2071                        EnumerationLiteralFacade enumLiteral = (EnumerationLiteralFacade) literal;
2072                        // Use the literal name to retrieve the value with .valueOf(). XML version has only the value.
2073                        Boolean useEnumValueInXSD = Boolean.valueOf(String.valueOf(enumer.getConfiguredProperty("useEnumValueInXSD")));
2074                        if (useEnumValueInXSD)
2075                        {
2076                            defaultValue = enumLiteral.getValue();
2077                        }
2078                        else
2079                        {
2080                            defaultValue = enumLiteral.getName();
2081                        }
2082                    }
2083                    else if (literal instanceof AttributeFacade)
2084                    {
2085                        AttributeFacade attrib = (AttributeFacade) literal;
2086                        defaultValue = attrib.getEnumerationValue();
2087                        if (defaultValue==null)
2088                        {
2089                            defaultValue = attrib.getDefaultValue();
2090                        }
2091                    }
2092                    // Literal value is always a String. Remove quotes if part of default (i.e. class attribute).
2093                    // wsdl2java may add unexpected underscores such that name and literal value no longer match.
2094                    defaultValue = StringUtils.remove(defaultValue, "\"");
2095                    defaultValue = enumer.getFullyQualifiedName() + ".fromValue(\"" + defaultValue + "\")";
2096                }
2097                else
2098                {
2099                    defaultValue = enumer.getName() + '.' + defaultValue;
2100                }
2101                isEnumeration = true;
2102            }
2103            if (useMany && (isMany==null || isMany.booleanValue()))
2104            {
2105                if (!typeName.startsWith("java.util"))
2106                {
2107                    rtn = "new " + collectionType + '<' + typeName + ">()";
2108                }
2109                /*if (type.equals("java.util.Collection") || typeName.equals("java.util.List"))
2110                {
2111                    rtn = "new " + collectionType + "<" + typeName + ">()";
2112                }
2113                else if (typeName.equals("java.util.Set"))
2114                {
2115                    rtn = "new java.util.HashSet<" + typeName + ">";
2116                }
2117                else if (typeName.equals("java.util.Map"))
2118                {
2119                    rtn = "new java.util.HashMap<" + typeName + ">";
2120                }*/
2121                else
2122                {
2123                    // Assume array or type Collection<type>
2124                    rtn = "new " + typeName + "()";
2125                }
2126            }
2127            else if ("String".equals(typeName) || "java.lang.String".equals(typeName))
2128            {
2129                rtn = (StringUtils.isNotBlank(defaultValue) ? defaultValue : '\"' + name + '\"');
2130            }
2131            else if ("Boolean".equals(typeName) || "java.lang.Boolean".equals(typeName))
2132            {
2133                rtn = (StringUtils.isNotBlank(defaultValue) ? "Boolean." + defaultValue.toUpperCase() : "Boolean.TRUE");
2134            }
2135            else if ("boolean".equals(typeName))
2136            {
2137                rtn = (StringUtils.isNotBlank(defaultValue) ? defaultValue : "true");
2138            }
2139            else if ("int".equals(typeName) || "short".equals(typeName) || "long".equals(typeName)
2140                    || "byte".equals(typeName) || "float".equals(typeName) || "double".equals(typeName))
2141            {
2142                rtn = (StringUtils.isNotBlank(defaultValue) ? defaultValue : "1");
2143            }
2144            else if ("java.util.Date".equals(typeName))
2145            {
2146                rtn = "new " + typeName + "()";
2147            }
2148            else if ("java.sql.Timestamp".equals(typeName))
2149            {
2150                rtn = "new java.sql.Timestamp(System.currentTimeMillis())";
2151            }
2152            else if ("java.util.Calendar".equals(typeName))
2153            {
2154                rtn = "java.util.Calendar.getInstance()";
2155            }
2156            else if ("org.joda.time.LocalTime".equals(typeName))
2157            {
2158                rtn = "new org.joda.time.LocalTime(1, 1)";
2159            }
2160            else if ("char".equals(typeName))
2161            {
2162                rtn = "'" + (StringUtils.isNotEmpty(defaultValue) ? defaultValue : name.substring(0, 1)) + "'";
2163            }
2164            else if ("Character".equals(typeName))
2165            {
2166                rtn = "new Character('" + (StringUtils.isNotEmpty(defaultValue) ? "new Character(" + defaultValue : name.substring(0, 1)) + "')";
2167            }
2168            else if ("Byte".equals(typeName) || "java.lang.Byte".equals(typeName))
2169            {
2170                rtn = "new Byte(\"" + facade.getName() + "\")";
2171            }
2172            else if ("Short".equals(typeName) || "java.lang.Short".equals(typeName)
2173                    || "Integer".equals(typeName) || "java.lang.Integer".equals(typeName)
2174                    || "Long".equals(typeName) || "java.lang.Long".equals(typeName)
2175                    || "Float".equals(typeName) || "java.lang.Float".equals(typeName)
2176                    || "Double".equals(typeName) || "java.lang.Double".equals(typeName)
2177                    || "java.math.BigDecimal".equals(typeName))
2178            {
2179                rtn = (!StringUtils.isEmpty(defaultValue) ? typeName + ".valueOf(" + defaultValue + ")" : typeName + ".valueOf(1)");
2180            }
2181            else if ("java.math.BigInteger".equals(typeName))
2182            {
2183                rtn = (!StringUtils.isEmpty(defaultValue) ? "java.math.BigInteger.valueOf(" + defaultValue + ')' : "java.math.BigInteger.valueOf(1)");
2184            }
2185            else if ("byte[]".equals(typeName))
2186            {
2187                rtn = (StringUtils.isNotBlank(defaultValue) ? defaultValue : '\"' + name + '\"') + ".getBytes()";
2188            }
2189            else if ("char[]".equals(typeName))
2190            {
2191                String value = StringUtils.isNotBlank(defaultValue) ? defaultValue : name;
2192                if (!value.startsWith("\""))
2193                {
2194                    value = "\"" + value;
2195                }
2196                if (!value.endsWith("\""))
2197                {
2198                    value = value + "\"";
2199                }
2200                rtn = value + ".toCharArray()";
2201            }
2202            else if ("String[]".equals(typeName))
2203            {
2204                rtn = "new String[] { " + (StringUtils.isNotBlank(defaultValue) ? defaultValue : '\"' + name + '\"') + " }";
2205            }
2206            else if (isEnumeration)
2207            {
2208                if (useMany)
2209                {
2210                    rtn = collectionType + '<' + defaultValue + '>';
2211                }
2212                else
2213                {
2214                    rtn = defaultValue;
2215                }
2216            }
2217            else if (!StringUtils.isEmpty(defaultValue))
2218            {
2219                rtn = "new " + typeName + '(' + defaultValue + ')';
2220            }
2221            else if (type != null && type.hasStereotype("Entity"))
2222            {
2223                // Entity classes will always be abstract with Impl generated classes.
2224                rtn = '(' + typeName + ")new " + typeName + "Impl()";
2225            }
2226            else if (type instanceof GeneralizableElementFacade)
2227            {
2228                // If type has a descendant with name <typeName>Impl, assume typeNameImpl must be instantiated instead of typeName
2229                if (typeName.endsWith("[]"))
2230                {
2231                    rtn = "{ new " + typeName.substring(0, typeName.length()-2) + "() }";
2232                }
2233                else
2234                {
2235                    rtn = "new " + typeName + "()";
2236                }
2237                //if (facade instanceof ClassifierFacade)
2238                //{
2239                    //ClassifierFacade classifier = (ClassifierFacade)facade;
2240                    // If type is abstract, choose Impl descendant if exists, or the last descendant
2241                    if (type.isAbstract())
2242                    {
2243                        // Can't instantiate abstract class - pick some descendant
2244                        for (GeneralizableElementFacade spec : type.getSpecializations())
2245                        {
2246                            if (spec.getName().equals(type.getName() + "Impl"))
2247                            {
2248                                rtn = '(' + type.getName() + ")new " + typeName + "Impl()";
2249                                break;
2250                            }
2251                            rtn = '(' + type.getName() + ")new " + spec.getFullyQualifiedName() + "()";
2252                        }
2253                    }
2254                //}
2255                GeneralizableElementFacade generalization = (GeneralizableElementFacade)type;
2256                for (GeneralizableElementFacade spec : generalization.getSpecializations())
2257                {
2258                    if (spec.getName().equals(type.getName() + "Impl"))
2259                    {
2260                        rtn = '(' + type.getName() + ")new " + spec.getFullyQualifiedName() + "Impl()";
2261                    }
2262                }
2263            }
2264            else if (typeName.endsWith("[]"))
2265            {
2266                rtn = "{ new " + typeName.substring(0, typeName.length()-2) + "() }";
2267            }
2268            else
2269            {
2270                rtn = "new " + typeName + "()";
2271            }
2272            rtn = StringUtils.replace(rtn, "java.util.Collection", "java.util.ArrayList") + toString;
2273            rtn = StringUtils.replace(rtn, "java.util.Set", "java.util.HashSet") + toString;
2274            if (logger.isDebugEnabled())
2275            {
2276                logger.debug("facade=" + facade + " facadeName=" + facade.getName() + " type=" + type + " typeName=" + typeName + " name=" + name + " isMany=" + isMany + " defaultValue=" + defaultValue + " rtn=" + rtn);
2277            }
2278        } catch (RuntimeException e) {
2279            logger.error(e + " facade=" + facade + " facadeName=" + facade.getName() + " parent=" + parent + " type=" + type + " typeName=" + typeName + " name=" + name + " isMany=" + isMany + " defaultValue=" + defaultValue);
2280            e.printStackTrace();
2281        }
2282        return rtn;
2283    }
2284
2285    /**
2286     * Creates a list of referenced packages for all subclasses referenced by the element.
2287     * Used to add XmlSeeAlso references to the SEI Interface.
2288     * @param service WebService containing WS operations with references.
2289     * @param pkgRef Current List of package references to be modified
2290     * @return pkgRef Collection<ModelElementFacade> referenced types
2291     */
2292    private Collection<PackageFacade> getServiceDescendantPackages(ModelElementFacade element, Collection<PackageFacade> pkgRef, Collection<ModelElementFacade> added)
2293    {
2294        if (element==null) return pkgRef;
2295        ModelElementFacade pkg = element.getPackage();
2296        if (pkg==null || pkg.getFullyQualifiedName().indexOf('.') < 1
2297            || pkg.getFullyQualifiedName().startsWith("java.util.")) return pkgRef;
2298        //name = ex.getName();
2299        if (!pkgRef.contains(pkg) && pkg instanceof PackageFacade)
2300        {
2301            pkgRef.add((PackageFacade)pkg);
2302        }
2303        if (logger.isDebugEnabled() && pkg.getName().indexOf('.')>0)
2304        {
2305            logger.debug("getServiceDescendantPackages " + element.getFullyQualifiedName() + " package " + pkg.getName() + " size=" + pkgRef.size());
2306        }
2307        if (element instanceof ClassifierFacade)
2308        {
2309            ClassifierFacade classifier = (ClassifierFacade) element;
2310            // Use commented and change getAllProperties to getProperties, if only descendant references are needed
2311            /*for (final GeneralizableElementFacade descendant : classifier.getAllSpecializations())
2312            {
2313                pkgRef = getServiceDescendantPackages(descendant, pkgRef);
2314                // Get all associations and attributes, down the inheritance hierarchy
2315            }*/
2316            for (final ModelElementFacade property : (List<ModelElementFacade>)classifier.getAllProperties())
2317            {
2318                if (property instanceof AttributeFacade)
2319                {
2320                    AttributeFacade attrib = (AttributeFacade) property;
2321                    if (!attrib.getType().equals(classifier) && !added.contains(attrib.getType())
2322                        && attrib.getType().getPackageName().indexOf('.')>0)
2323                    {
2324                        if (logger.isDebugEnabled())
2325                        {
2326                            logger.debug("getServiceDescendantPackages " + attrib.getName() + ' ' + attrib.getType().getFullyQualifiedName() + " attribute in " + classifier.getFullyQualifiedName() + " size=" + pkgRef.size());
2327                        }
2328                        added.add(attrib.getType());
2329                        pkgRef = getServiceDescendantPackages(attrib.getType(), pkgRef, added);
2330                    }
2331                }
2332                else if (property instanceof AssociationEndFacade)
2333                {
2334                    AssociationEndFacade assoc = (AssociationEndFacade) property;
2335                    if (!assoc.getType().equals(classifier) && !added.contains(assoc.getType())
2336                        && assoc.getType().getPackageName().indexOf('.')>0)
2337                    {
2338                        if (logger.isDebugEnabled())
2339                        {
2340                            logger.debug("getServiceDescendantPackages " + assoc.getName() + ' ' + assoc.getType().getFullyQualifiedName() + " association in " + classifier.getFullyQualifiedName() + " size=" + pkgRef.size());
2341                        }
2342                        added.add(assoc.getType());
2343                        pkgRef = getServiceDescendantPackages(assoc.getType(), pkgRef, added);
2344                    }
2345                }
2346            }
2347        }
2348        return pkgRef;
2349    }
2350
2351    /**
2352     * Creates a list of referenced packages for all subclasses referenced by the service.
2353     * Used to add XmlSeeAlso references to the SEI Interface.
2354     * @param service WebService containing WS operations with references.
2355     * @param follow Follow Inheritance references $extensionInheritanceDisabled
2356     * @return typeRef Collection<ModelElementFacade> referenced types
2357     */
2358    public Collection<PackageFacade> getServiceDescendantPackages(WebServiceLogicImpl service, boolean follow)
2359    {
2360        // Note: The way XmlSeeAlso is supposed to work: any descendant classes from parameter or return or exception classes
2361        // not directly referenced by the XML types should have their package ObjectFactory added to the reference list.
2362        // The way CXF works: parameter types and type hierarchy referenced by the service are added.
2363        Collection<PackageFacade> pkgRef = new HashSet<PackageFacade>();
2364        // Keep track of elements already iterated, avoid stackOverflow.
2365        Collection<ModelElementFacade> added = new HashSet<ModelElementFacade>();
2366        // For each service parameter and return type and exception, find all descendants
2367        for (final WebServiceOperation op : service.getAllowedOperations())
2368        {
2369            if (logger.isDebugEnabled())
2370            {
2371                logger.debug("getServiceDescendantPackages " + service.getFullyQualifiedName() + '.' + op.getName() + " parms=" + op.getParameters().size() + " size=" + pkgRef.size());
2372            }
2373            /*for (final ModelElementFacade ex : op.getExceptions())
2374            {
2375                if (!added.contains(ex))
2376                {
2377                    if (logger.isDebugEnabled())
2378                    {
2379                        logger.debug("getServiceDescendantPackages " + service.getFullyQualifiedName() + '.' + op.getName() + " exception=" + ex.getFullyQualifiedName() + " size=" + pkgRef.size());
2380                    }
2381                    added.add(ex);
2382                    pkgRef = getServiceDescendantPackages(ex, pkgRef, added);
2383                }
2384            }*/
2385            for (final ParameterFacade arg : op.getParameters())
2386            {
2387                if (!added.contains(arg.getType()))
2388                {
2389                    if (logger.isDebugEnabled())
2390                    {
2391                        logger.debug("getServiceDescendantPackages " + service.getFullyQualifiedName() + '.' + op.getName() + " parameter=" + arg.getName() + " size=" + pkgRef.size());
2392                    }
2393                    added.add(arg.getType());
2394                    pkgRef = getServiceDescendantPackages(arg.getType(), pkgRef, added);
2395                }
2396            }
2397
2398        }
2399        // Don't put current package into package reference list
2400        pkgRef.remove(service.getPackage());
2401        return pkgRef;
2402    }
2403
2404    /**
2405     * Creates a list of referenced types for the service.
2406     * Used to add element references to the service namespace, for bare parameters.
2407     * @param service WebService containing WS operations with references.
2408     * @param follow Follow Inheritance references $extensionInheritanceDisabled
2409     * @return typeRef Collection<ModelElementFacade> referenced types
2410     */
2411    public Collection<ModelElementFacade> getServiceReferences(WebServiceLogicImpl service, boolean follow)
2412    {
2413        Collection<ModelElementFacade> typeRef = new HashSet<ModelElementFacade>();
2414        // Temporary holder until we determine that the service can be bare
2415        Collection<ModelElementFacade> opRef = new HashSet<ModelElementFacade>();
2416        //String name = null;
2417        String pkg = null;
2418        @SuppressWarnings("unused")
2419        String typeRefs = "";
2420        // Copy package names and collection of related packages to package references list
2421        // Add references from the operations of the service package itself
2422        for (final WebServiceOperation op : service.getAllowedOperations())
2423        {
2424            boolean isMany = false;
2425            /*for (final ModelElementFacade ex : op.getExceptions())
2426            {
2427                pkg = ex.getPackageName();
2428                //name = ex.getName();
2429                if (pkg!=null && pkg.indexOf('.') > 0 && !typeRef.contains(ex) && !opRef.contains(ex))
2430                {
2431                    opRef.add(ex);
2432                    if (logger.isDebugEnabled())
2433                    {
2434                        typeRefs += ex + ",";
2435                        logger.debug("getServiceReferences exception " + pkg + '.' + ex.getName());
2436                    }
2437                }
2438            }*/
2439            for (final ParameterFacade arg : op.getParameters())
2440            {
2441                pkg = arg.getType().getPackageName();
2442                //name = arg.getType().getName();
2443                if (arg.getUpper()>1 || arg.getUpper()==-1)
2444                {
2445                    // Can't handle return size > 1 for object - need wrapper
2446                    isMany = true;
2447                }
2448                if (pkg!=null && pkg.indexOf('.') > 0 && !typeRef.contains(arg.getType()) && !opRef.contains(arg.getType()))
2449                {
2450                    opRef.add(arg.getType());
2451                    if (logger.isDebugEnabled())
2452                    {
2453                        typeRefs += arg.getType() + ",";
2454                        logger.debug("getServiceReferences parameter " + pkg + '.' + arg.getType().getName());
2455                    }
2456                }
2457            }
2458/*            if (op.getReturnType()!=null)
2459            {
2460                ClassifierFacade rtnType = op.getReturnType();
2461                pkg = rtnType.getPackageName();
2462                //name = rtnType.getName();
2463                if (logger.isDebugEnabled())
2464                {
2465                    logger.debug("getServiceReferences packageName=" + packageName + " return " + pkg + "." + name);
2466                }
2467                if (pkg!=null && !pkg.equals(service.getPackageName()) && pkg.indexOf('.') > 0 && !typeRef.contains(rtnType))
2468                {
2469                    typeRef.add(rtnType);
2470                    //pkgRefs += pkg + ",";
2471                    if (logger.isDebugEnabled())
2472                    {
2473                        logger.debug("getServiceReferences packageName=" + packageName + " add return " + pkg + "." + name);
2474                    }
2475                }
2476            }*/
2477            if (!isMany)
2478            {
2479                typeRef.addAll(opRef);
2480            }
2481        }
2482        /*for (final ModelElementFacade type : typeRef)
2483        {
2484            if (logger.isDebugEnabled())
2485            {
2486                logger.debug("getServiceReferences packageName=" + type.getPackageName() + "." + type.getName());
2487            }
2488        }*/
2489        if (logger.isDebugEnabled())
2490        {
2491            logger.debug("getServiceReferences typeRef " + service.getPackageName() + '.' + service.getName() + ' ' + typeRef);
2492        }
2493        return typeRef;
2494    }
2495
2496    /**
2497     * Reverses the <code>packageName</code>.
2498     *
2499     * @param packageName the package name to reverse.
2500     * @return the reversed package name.
2501     */
2502    public static String reversePackage(String packageName)
2503    {
2504        if (StringUtils.isBlank(packageName))
2505        {
2506            return "";
2507        }
2508        if (packageName.startsWith("http://"))
2509        {
2510            packageName = packageName.substring(7);
2511        }
2512        return StringUtils.reverseDelimited(packageName, WebServiceGlobals.NAMESPACE_DELIMITER);
2513    }
2514
2515    private static FastDateFormat df = FastDateFormat.getInstance("MM/dd/yyyy HH:mm:ssZ");
2516
2517    /**
2518     * Returns the current Date in the specified format.
2519     *
2520     * @param format The format for the output date
2521     * @return the current date in the specified format.
2522     */
2523    public static String getDate(String format)
2524    {
2525        if (df == null || !format.equals(df.getPattern()))
2526        {
2527            df = FastDateFormat.getInstance(format);
2528        }
2529        return df.format(new Date());
2530    }
2531
2532    /**
2533     * Returns the current Date in the specified format.
2534     *
2535     * @return the current date with the default format .
2536     */
2537    public static String getDate()
2538    {
2539        return df.format(new Date());
2540    }
2541
2542    /**
2543     * Determine how a model type is mapped to a java implementation type.
2544     * Used to resolve conflicts between java and webservice type mappings.
2545     * i.e. webservice maps Integer as BigInteger and Date/Time/DateTime as Calendar, so
2546     * Value Object attributes will not match webservice attribute types.
2547     * Called from vsl $webServiceUtils.getTypeMapping($service.
2548     * @param mappings
2549     * @param from
2550     *
2551     * @return the String mapping type to.
2552     */
2553    public String getTypeMapping(TypeMappings mappings, String from)
2554    {
2555        // URI is the namespace value in andromda.xml configuration parameter for the type mapping
2556        //MetafacadeFactory.getInstance().getRegisteredProperty( metafacade, "languageMappingsUri");
2557        //Object property = metafacade.getConfiguredProperty("languageMappingsUri");
2558        //TypeMappings mappings = TypeMappings.getInstance(property);
2559        return mappings.getTo("datatype::"+from);
2560    }
2561
2562    /**
2563     * <p> Creates and returns the schema type for the given <code>type</code>.
2564     * It finds the mapped schema type from the passed in
2565     * <code>schemaTypeMappings</code>.
2566     * </p>
2567     *
2568     * @param type the ClassifierFacade instance
2569     * @param schemaTypeMappings contains the mappings from model datatypes to
2570     *        schema datatypes.
2571     * @param namespacePrefix the prefix given to the schema type if it's a
2572     *        custom type (non XSD type).
2573     * @param qName the qualified name
2574     * @param wrappedArrayTypePrefix a prefix to give to wrapped array types.
2575     * @param withPrefix a flag indicating whether or not the type should have
2576     *        the prefix defined
2577     * @param preserveArray true/false, if true then if the schema type is an
2578     *        array we'll preserve the fact that its an array and return an
2579     *        array schema type name. If false we will return back the non array
2580     *        type even if its an array.
2581     * @return the schema type name - String
2582     */
2583    public static String getSchemaType(
2584        ClassifierFacade type,
2585        TypeMappings schemaTypeMappings,
2586        String namespacePrefix,
2587        String qName,
2588        String wrappedArrayTypePrefix,
2589        boolean withPrefix,
2590        boolean preserveArray)
2591    {
2592        StringBuilder schemaType = new StringBuilder();
2593        String modelName = type.getFullyQualifiedName(true);
2594        if (schemaTypeMappings != null)
2595        {
2596            namespacePrefix += ':';
2597            String mappedValue = schemaTypeMappings.getTo(modelName);
2598            if (!mappedValue.equals(modelName) || StringUtils.isEmpty(type.getPackageName()))
2599            {
2600                schemaType.append(mappedValue);
2601            }
2602            else
2603            {
2604                if (withPrefix)
2605                {
2606                    schemaType.append(namespacePrefix);
2607                }
2608                if (type.isArrayType())
2609                {
2610                    ClassifierFacade nonArray = type.getNonArray();
2611                    if (nonArray != null)
2612                    {
2613                        if (nonArray instanceof WSDLType)
2614                        {
2615                            schemaType.append(((WSDLType)nonArray).getName());
2616                        }
2617                        else if (nonArray instanceof WSDLEnumerationType)
2618                        {
2619                            schemaType.append(((WSDLEnumerationType)nonArray).getName());
2620                        }
2621                    }
2622                }
2623                else
2624                {
2625                    schemaType.append(qName);
2626                }
2627            }
2628            // remove any array '[]' suffix
2629            schemaType = new StringBuilder(schemaType.toString().replaceAll("\\[\\]", ""));
2630            if (preserveArray && type.isArrayType())
2631            {
2632                int insertIndex = namespacePrefix.length();
2633                if (!schemaType.toString().startsWith(namespacePrefix))
2634                {
2635                    if (withPrefix)
2636                    {
2637                        // add the prefix for any normal XSD types
2638                        // that may not have been set above
2639                        schemaType.insert(0, namespacePrefix);
2640                    }
2641                    else
2642                    {
2643                        // since we aren't adding the prefix, set
2644                        // the correct insert index
2645                        insertIndex = 0;
2646                    }
2647                }
2648                schemaType.insert(insertIndex, wrappedArrayTypePrefix);
2649            }
2650            if (withPrefix && !schemaType.toString().startsWith(namespacePrefix))
2651            {
2652                schemaType.insert(0, WebServiceGlobals.XSD_NAMESPACE_PREFIX);
2653            }
2654        }
2655        return schemaType.toString();
2656    }
2657
2658    /**
2659     * <p> Returns true if java.lang.* or java.util.* datatype and not many*
2660     * </p>
2661     *
2662     * @param element the ClassifierFacade instance
2663     * @return if type is one of the PrimitiveTypes and not an array/list
2664     */
2665    public static boolean isSimpleType(ModelElementFacade element)
2666    {
2667        boolean simple = false;
2668        String typeName = null;
2669        ClassifierFacade type = null;
2670        boolean many = false;
2671        if (element instanceof AttributeFacade)
2672        {
2673            AttributeFacade attrib = (AttributeFacade)element;
2674            type = attrib.getType();
2675            many = attrib.isMany() && !type.isArrayType() && !type.isCollectionType();
2676        }
2677        else if (element instanceof AssociationEndFacade)
2678        {
2679            AssociationEndFacade association = (AssociationEndFacade)element;
2680            type = association.getType();
2681            many = association.isMany() && !type.isArrayType() && !type.isCollectionType();
2682        }
2683        else if (element instanceof ParameterFacade)
2684        {
2685            ParameterFacade param = (ParameterFacade)element;
2686            type = param.getType();
2687            many = param.isMany() && !type.isArrayType() && !type.isCollectionType();
2688        }
2689        else if (element instanceof WSDLTypeAttributeLogic)
2690        {
2691            WSDLTypeAttributeLogic attrib = (WSDLTypeAttributeLogic)element;
2692            type = attrib.getType();
2693            many = attrib.isMany() && !type.isArrayType() && !type.isCollectionType();
2694        }
2695        else if (element instanceof WSDLTypeAssociationEndLogic)
2696        {
2697            WSDLTypeAssociationEndLogic association = (WSDLTypeAssociationEndLogic)element;
2698            type = association.getType();
2699            many = association.isMany() && !type.isArrayType() && !type.isCollectionType();
2700        }
2701        else if (element instanceof WebServiceParameterLogic)
2702        {
2703            WebServiceParameterLogic param = (WebServiceParameterLogic)element;
2704            type = param.getType();
2705            many = param.isMany() && !type.isArrayType() && !type.isCollectionType();
2706        }
2707        else if (element instanceof ClassifierFacade)
2708        {
2709            ClassifierFacade classifier = (ClassifierFacade)element;
2710            type = classifier;
2711        }
2712        else
2713        {
2714            return simple;
2715        }
2716        typeName = type.getFullyQualifiedName();
2717        if (type.isPrimitive() || typeName.startsWith("java.lang.") || typeName.startsWith("java.util.")
2718            || !typeName.contains("."))
2719        {
2720            if (!many)
2721            {
2722                simple = true;
2723            }
2724        }
2725        return simple;
2726    }
2727}