001package org.andromda.metafacades.uml14;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Iterator;
007import org.andromda.core.common.ExceptionUtils;
008import org.andromda.core.configuration.Filters;
009import org.andromda.core.metafacade.MetafacadeBase;
010import org.andromda.core.metafacade.MetafacadeConstants;
011import org.andromda.core.metafacade.MetafacadeFactory;
012import org.andromda.core.metafacade.ModelAccessFacade;
013import org.andromda.metafacades.uml.EntityMetafacadeUtils;
014import org.andromda.metafacades.uml.ModelElementFacade;
015import org.andromda.metafacades.uml.PackageFacade;
016import org.apache.commons.collections.CollectionUtils;
017import org.apache.commons.collections.Predicate;
018import org.apache.commons.lang.StringUtils;
019import org.apache.log4j.Logger;
020import org.omg.uml.UmlPackage;
021import org.omg.uml.foundation.core.ModelElement;
022
023/**
024 * Contains a UML model, follows the {@link ModelAccessFacade} interface and can therefore be processed by AndroMDA.
025 *
026 * @author <a href="http://www.mbohlen.de">Matthias Bohlen </a>
027 * @author Chad Brandon
028 * @author Bob Fields
029 */
030public class UMLModelAccessFacade
031    implements ModelAccessFacade
032{
033    private static final Logger logger = Logger.getLogger(UMLModelAccessFacade.class);
034    private UmlPackage model;
035
036    /**
037     * @see org.andromda.core.metafacade.ModelAccessFacade#setModel(Object)
038     */
039    public void setModel(final Object model)
040    {
041        ExceptionUtils.checkNull("model", model);
042        ExceptionUtils.checkAssignable(
043            UmlPackage.class,
044            "modelElement",
045            model.getClass());
046        this.model = (UmlPackage)model;
047        // TODO: - clears out the foreign key cache (probably not
048        //         the cleanest way, but the easiest at this point).
049        EntityMetafacadeUtils.clearForeignKeyConstraintNameCache();
050    }
051
052    /**
053     * @see org.andromda.core.metafacade.ModelAccessFacade#getModel()
054     */
055    public UmlPackage getModel()
056    {
057        return model;
058    }
059
060    /**
061     * @see org.andromda.core.metafacade.ModelAccessFacade#getName(Object)
062     */
063    public String getName(final Object modelElement)
064    {
065        ExceptionUtils.checkNull("modelElement", modelElement);
066        ExceptionUtils.checkAssignable(
067            ModelElementFacade.class,
068            "modelElement",
069            modelElement.getClass());
070        return ((ModelElementFacade)modelElement).getName();
071    }
072
073    /**
074     * @see org.andromda.core.metafacade.ModelAccessFacade#getPackageName(Object)
075     */
076    public String getPackageName(final Object modelElement)
077    {
078        ExceptionUtils.checkNull("modelElement", modelElement);
079        ExceptionUtils.checkAssignable(
080            ModelElementFacade.class,
081            "modelElement",
082            modelElement.getClass());
083        final ModelElementFacade modelElementFacade = (ModelElementFacade)modelElement;
084        final StringBuilder packageName = new StringBuilder(modelElementFacade.getPackageName(true));
085
086        // - if the model element is a package then the package name will be the name
087        //   of the package with its package name
088        if (modelElement instanceof PackageFacade)
089        {
090            final String name = modelElementFacade.getName();
091            if (StringUtils.isNotBlank(name))
092            {
093                packageName.append(MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR);
094                packageName.append(name);
095            }
096        }
097        return packageName.toString();
098    }
099
100    /**
101     * @see org.andromda.core.metafacade.ModelAccessFacade#getStereotypeNames(Object)
102     */
103    public Collection<String> getStereotypeNames(final Object modelElement)
104    {
105        Collection<String> stereotypeNames = new ArrayList();
106        if (modelElement instanceof ModelElement)
107        {
108            ModelElement element = (ModelElement)modelElement;
109            Collection<ModelElement> stereotypes = element.getStereotype();
110            for (final Iterator<ModelElement> iterator = stereotypes.iterator(); iterator.hasNext();)
111            {
112                ModelElement stereotype = iterator.next();
113                stereotypeNames.add(stereotype.getName());
114            }
115        }
116        else if (modelElement instanceof ModelElementFacade)
117        {
118            stereotypeNames = ((ModelElementFacade)modelElement).getStereotypeNames();
119        }
120        return stereotypeNames;
121    }
122
123    /**
124     * @see org.andromda.core.metafacade.ModelAccessFacade#findByStereotype(String)
125     */
126    public Collection<MetafacadeBase> findByStereotype(String stereotype)
127    {
128        final String methodName = "UMLModelAccessFacade.findByStereotype";
129        final Collection<MetafacadeBase> metafacades = new ArrayList<MetafacadeBase>();
130        stereotype = StringUtils.trimToEmpty(stereotype);
131        if (StringUtils.isNotBlank(stereotype))
132        {
133            if (this.model != null)
134            {
135                final Collection<ModelElement> underlyingElements = model.getCore().getModelElement().refAllOfType();
136                if (underlyingElements != null && !underlyingElements.isEmpty())
137                {
138                    for (final ModelElement element : underlyingElements)
139                    {
140                        Collection<String> stereotypeNames = this.getStereotypeNames(element);
141                        if (stereotypeNames != null && stereotypeNames.contains(stereotype))
142                        {
143                            metafacades.add(MetafacadeFactory.getInstance().createMetafacade(element));
144                        }
145                    }
146                }
147                if (logger.isDebugEnabled())
148                {
149                    logger.debug("completed " + methodName + " with " + metafacades.size() + " modelElements");
150                }
151            }
152            this.filterMetafacades(metafacades);
153        }
154        return metafacades;
155    }
156
157    /**
158     * @see org.andromda.core.metafacade.ModelAccessFacade#getModelElements()
159     */
160    public Collection<MetafacadeBase> getModelElements()
161    {
162        Collection<MetafacadeBase> metafacades = Collections.emptyList();
163        if (this.model != null)
164        {
165            metafacades =
166                MetafacadeFactory.getInstance().createMetafacades(
167                    this.model.getCore().getModelElement().refAllOfType());
168            this.filterMetafacades(metafacades);
169        }
170        return metafacades;
171    }
172
173    /**
174     * Stores the package filter information.  Protected
175     * visibility for better inner class access performance.
176     */
177    protected Filters modelPackages;
178
179    /**
180     * @see org.andromda.core.metafacade.ModelAccessFacade#setPackageFilter(org.andromda.core.configuration.Filters)
181     */
182    public void setPackageFilter(final Filters modelPackages)
183    {
184        this.modelPackages = modelPackages;
185    }
186
187    /**
188     * Filters out those metafacades which <strong>should </strong> be processed.
189     *
190     * @param metafacades the Collection of modelElements.
191     */
192    private void filterMetafacades(final Collection metafacades)
193    {
194        if (this.modelPackages != null && !this.modelPackages.isEmpty())
195        {
196            CollectionUtils.filter(
197                metafacades,
198                new Predicate()
199                {
200                    public boolean evaluate(final Object metafacade)
201                    {
202                        boolean valid = false;
203                        if (metafacade instanceof MetafacadeBase)
204                        {
205                            final ModelElementFacade modelElementFacade = (ModelElementFacade)metafacade;
206                            final StringBuilder packageName = new StringBuilder(modelElementFacade.getPackageName(true));
207
208                            // - if the model element is a package then the package name will be the name
209                            //   of the package with its package name
210                            if (metafacade instanceof PackageFacade)
211                            {
212                                final String name = modelElementFacade.getName();
213                                if (StringUtils.isNotBlank(name))
214                                {
215                                    packageName.append(MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR);
216                                    packageName.append(name);
217                                }
218                            }
219                            valid = modelPackages.isApply(packageName.toString());
220                        }
221                        return valid;
222                    }
223                });
224        }
225    }
226}