WebServicePackageLogicImpl.java

// license-header java merge-point
//
// Generated by: MetafacadeLogicImpl.vsl in andromda-meta-cartridge.
package org.andromda.cartridges.webservice.metafacades;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.andromda.cartridges.webservice.WebServiceGlobals;
import org.andromda.cartridges.webservice.WebServiceUtils;
import org.andromda.core.metafacade.MetafacadeBase;
import org.andromda.core.metafacade.ModelValidationMessage;
import org.andromda.metafacades.uml.PackageFacade;
import org.andromda.metafacades.uml.UMLProfile;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 *
 * MetafacadeLogic implementation for org.andromda.cartridges.webservice.metafacades.WebServicePackage.
 *
 * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage
 */
public class WebServicePackageLogicImpl
    extends WebServicePackageLogic
{
    private static final long serialVersionUID = 34L;
    private static final String DEFAULT = "default";

    /**
     * Public constructor for WebServicePackageLogicImpl
     * @param metaObject
     * @param context
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage
     */
    public WebServicePackageLogicImpl (Object metaObject, String context)
    {
        super(metaObject, context);
    }

    /**
     * The logger instance.
     */
    private static final Logger logger = Logger.getLogger(WebServicePackageLogicImpl.class);

    /**
     * The property defining the default style to give the web services.
     */
    private static final String DEFAULT_ATTRIBUTE_FORM = "UNQUALIFIED";

    /**
     *
     * @return findTaggedValue(WebServiceGlobals.ATTRIBUTE_FORM_DEFAULT) or DEFAULT_ATTRIBUTE_FORM
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getAttributeFormDefault()
     */
    protected String handleGetAttributeFormDefault()
    {
        String style = (String)this.findTaggedValue(WebServiceGlobals.ATTRIBUTE_FORM_DEFAULT);
        if (StringUtils.isEmpty(style) || style.equals(DEFAULT))
        {
            style = DEFAULT_ATTRIBUTE_FORM;
        }
        return style;
    }

    /**
     * The property defining the default style to give the web services.
     */
    private static final String DEFAULT_ELEMENT_FORM = "QUALIFIED";

    /**
     *
     * @return findTaggedValue(WebServiceGlobals.ELEMENT_FORM_DEFAULT) or DEFAULT_ELEMENT_FORM
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getElementFormDefault()
     */
    protected String handleGetElementFormDefault()
    {
        String style = (String)this.findTaggedValue(WebServiceGlobals.ELEMENT_FORM_DEFAULT);
        if (StringUtils.isEmpty(style) || style.equals(DEFAULT))
        {
            style = DEFAULT_ELEMENT_FORM;
        }
        return style;
    }

    /**
     * reverseNamespace
     */
    static final String REVERSE_NAMESPACE = "reverseNamespace";
    /**
     * Backslash char /
     */
    static final String BACKSLASH = "/";
    /**
     *
     * @return findTaggedValue(WebServiceGlobals.XML_NAMESPACE) or REVERSE_NAMESPACE
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getNamespace()
     */
    protected String handleGetNamespace()
    {
        String namespace = (String)this.findTaggedValue(WebServiceGlobals.XML_NAMESPACE);
        if (StringUtils.isEmpty(namespace))
        {
            if (Boolean.valueOf(String.valueOf(this.getConfiguredProperty(REVERSE_NAMESPACE))).booleanValue())
            {
                namespace = WebServiceUtils.reversePackage(this.getName());
            }
            String namespacePattern = (String)this.getConfiguredProperty(WebServiceLogicImpl.NAMESPACE_PATTERN);
            namespace = MessageFormat.format(
                namespacePattern,
                new Object[] {StringUtils.trimToEmpty(namespace)});
            Boolean addNamespaceBackslash = Boolean.valueOf((String)this.getConfiguredProperty(WebServiceGlobals.ADD_NAMESPACE_BACKSLASH));
            if (addNamespaceBackslash && !namespace.endsWith(BACKSLASH))
            {
                namespace += BACKSLASH;
            }
        }
        return namespace;
    }

    /**
     * @return findTaggedValue(WebServiceGlobals.XML_XMLNS) or WebServiceUtils.getPkgAbbr(this)
     * @see org.andromda.cartridges.webservice.WebServiceUtils#getPkgAbbr(PackageFacade)
     */
    protected String handleGetXmlns()
    {
        WebServiceUtils utils = new WebServiceUtils();
        String abbr = (String)this.findTaggedValue(WebServiceGlobals.XML_XMLNS);
        if (StringUtils.isEmpty(abbr))
        {
            abbr = utils.getPkgAbbr(this);
        }
        else
        {
            utils.addPkgAbbr(this, abbr);
        }
        return abbr;
    }

    /**
     * @return findTaggedValue(WebServiceGlobals.XML_XMLNS) or WebServiceUtils.getPkgAbbr(this)
     * @see org.andromda.cartridges.webservice.WebServiceUtils#getPkgAbbr(PackageFacade)
     */
    protected String handleGetSchemaLocation()
    {
        String packageNamespace = this.getNamespace().substring(7) + ".xsd";
        packageNamespace = StringUtils.replaceChars(packageNamespace, "/\\", ".");
        packageNamespace = "xsd/" + StringUtils.replace(packageNamespace, "..", ".");
        return packageNamespace;
    }

    /**
     *
     * @return new WebServiceUtils().getPackageReferences(this, true)
     * @see org.andromda.cartridges.webservice.WebServiceUtils#getPackageReferences(PackageFacade, boolean)
     */
    protected Collection<PackageFacade> handleGetPackages()
    {
        return new WebServiceUtils().getPackageReferences(this, true);
    }

    /**
     * <p>
     * Package Abbreviation
     * </p>
     * @return findTaggedValue(WebServiceGlobals.XML_XMLNS) or WebServiceUtils.getPkgAbbr(this)
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getPackageAbbr()
     */
    protected String handleGetPackageAbbr()
    {
        WebServiceUtils utils = new WebServiceUtils();
        String namespace = (String)this.findTaggedValue(WebServiceGlobals.XML_XMLNS);
        if (StringUtils.isEmpty(namespace))
        {
            namespace = utils.getPkgAbbr(this);
        }
        else
        {
            utils.addPkgAbbr(this, namespace);
        }
        return namespace;
    }

    /**
     * <p>
     * Packages referenced by this package
     * </p>
     * @return WebServiceUtils.getPackageReferences(this, true)
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getPackageReferences()
     * @see org.andromda.cartridges.webservice.WebServiceUtils#getPackageReferences(WebServiceLogicImpl, java.util.Set, String, boolean)
     */
    protected Collection<PackageFacade> handleGetPackageReferences()
    {
        WebServiceUtils utils = new WebServiceUtils();
        return utils.getPackageReferences(this, true);
    }

    /**
     *
     * @param follow
     * @return WebServiceUtils.getPackageReferences(this, follow)
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackage#getPackageReferences(boolean)
     */
    protected Collection<PackageFacade> handleGetPackageReferences(boolean follow)
    {
        WebServiceUtils utils = new WebServiceUtils();
        return utils.getPackageReferences(this, follow);
    }

    /**
     * Allow sorting and use in TreeSet
     * @see Comparable#compareTo(Object)
     */
    public int compareTo(Object object)
    {
        if (object==null || !(object instanceof WebServicePackageLogic))
        {
            return -1;
        }
        return ((WebServicePackageLogic)object).getFullyQualifiedName().compareTo(this.getFullyQualifiedName());
    }

    private static List<WebServiceOperation> warnedOperations = new ArrayList<WebServiceOperation>();
    /**
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackageLogic#handleGetAllowedOperations()
     */
    @Override
    protected Collection<WebServiceOperation> handleGetAllowedOperations()
    {
        Collection<WebServiceOperation> operations = new WebServiceUtils().getAllowedOperations(this);
        // Log the actual offending operation name, since validator only shows the package name
        String webserviceStack = String.valueOf(this.getConfiguredProperty("webserviceStack"));
        if (webserviceStack.equals("cxf") || webserviceStack.equals("jaxws"))
        {
            for (WebServiceOperation operation : operations)
            {
                int matchCount = 0;
                String operationName = operation.getName();
                for (WebServiceOperation operationToCheck : operations)
                {
                    if (operationName.equals(operationToCheck.getName()))
                    {
                        matchCount++;
                    }
                }
                if (matchCount > 1 && !warnedOperations.contains(operation))
                {
                    warnedOperations.add(operation);
                    logger.warn(operation.getFullyQualifiedName() + " Duplicate webservice operation in package " + this.getFullyQualifiedName());
                }
            }
        }
        return operations;
    }

    private static List<String> checkedPackages = new ArrayList<String>();
    /**
     * @see org.andromda.cartridges.webservice.metafacades.WebServicePackageLogic#handleGetAllowedOperations()
     */
    @Override
    protected boolean handleIsMissingXmlSchema()
    {
        boolean result = false;
        // If the cartridge is configured to use CXF or JAX-WS, and schemas are imported...
        String webserviceStack = String.valueOf(this.getConfiguredProperty("webserviceStack"));
        String importedSchema = String.valueOf(this.getConfiguredProperty("importedXSD"));
        if (importedSchema.equals("true") && (webserviceStack.equals("cxf") || webserviceStack.equals("jaxws")))
        {
            int serviceCount = this.getAllowedOperations().size();
            // Check this package is it contains services
            if (serviceCount > 0 && !this.hasStereotype(UMLProfile.STEREOTYPE_XMLSCHEMA))
            {
                // the packages containing the webservices must be labeled with XmlSchema
                result = true;
                if (!checkedPackages.contains(this.getFullyQualifiedName()))
                {
                    // Only display the error message once for each referenced package
                    checkedPackages.add(this.getFullyQualifiedName());
                }
            }
            // Check packages referenced by this package
            if (serviceCount > 0 || this.hasStereotype(UMLProfile.STEREOTYPE_XMLSCHEMA))
            {
                Collection<PackageFacade> references = new WebServiceUtils().getPackageReferences(this, true);
                for (PackageFacade pkg : references)
                {
                    if (!pkg.hasStereotype(UMLProfile.STEREOTYPE_XMLSCHEMA))
                    {
                        result = true;
                        if (!checkedPackages.contains(pkg.getFullyQualifiedName()))
                        {
                            // Only display the error message once for each referenced package
                            checkedPackages.add(pkg.getFullyQualifiedName());
                            logger.warn(pkg.getFullyQualifiedName() + " package is missing XmlSchema stereotype");
                        }
                    }
                }
            }
        }
        return result;
    }

    /**
     * <p><b>Constraint:</b> org::andromda::cartridges::webservice::metafacades::WebServicePackage::package must be lowercase</p>
     * <p><b>Error:</b>XmlSchema Package name must be lowercase.</p>
     * @param validationMessages Collection<ModelValidationMessage>
     * @see MetafacadeBase#validateInvariants(Collection validationMessages)
     */
    @Override
    public void validateInvariants(Collection<ModelValidationMessage> validationMessages)
    {
        super.validateInvariants(validationMessages);
        try
        {
            final Object contextElement = this.THIS();
            final String name = this.getName();
            boolean constraintValid = name != null && name.toLowerCase().equals(name);
            // Exclude common package names from validation
            //boolean common = name.equals("PrimitiveTypes") || name.equals("datatype") || name.startsWith("UML");
            if (!constraintValid && this.hasStereotype(UMLProfile.STEREOTYPE_XMLSCHEMA))
            {
                validationMessages.add(
                    new ModelValidationMessage(
                        (MetafacadeBase)contextElement ,
                        "org::andromda::cartridges::webservice::metafacades::WebServicePackage::package must be lowercase",
                        "Package name must be lowercase."));
            }
        }
        catch (Throwable th)
        {
            Throwable cause = th.getCause();
            int depth = 0; // Some throwables have infinite recursion
            while (cause != null && depth < 7)
            {
                th = cause;
                depth++;
            }
            logger.error("Error validating constraint 'org::andromda::cartridges::webservice::metafacades::WebServicePackage::package must be lowercase' ON "
                + this.THIS().toString() + ": " + th.getMessage(), th);
        }
    }
}