001package org.andromda.cartridges.spring.metafacades;
002
003import java.util.Arrays;
004import java.util.Collection;
005import java.util.Iterator;
006import org.andromda.cartridges.spring.SpringProfile;
007import org.andromda.cartridges.spring.SpringUtils;
008import org.andromda.metafacades.uml.AttributeFacade;
009import org.andromda.metafacades.uml.ClassifierFacade;
010import org.andromda.metafacades.uml.ModelElementFacade;
011import org.andromda.metafacades.uml.ParameterFacade;
012import org.andromda.metafacades.uml.UMLProfile;
013import org.apache.commons.lang.StringUtils;
014
015/**
016 * MetafacadeLogic implementation for org.andromda.cartridges.spring.metafacades.SpringQueryOperation.
017 *
018 * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperation
019 */
020public class SpringQueryOperationLogicImpl
021        extends SpringQueryOperationLogic
022{
023    private static final long serialVersionUID = 34L;
024    /**
025     * Public constructor for SpringQueryOperationLogicImpl
026     * @param metaObject
027     * @param context
028     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperation
029     */
030    public SpringQueryOperationLogicImpl(Object metaObject, String context)
031    {
032        super(metaObject, context);
033    }
034
035    /**
036     * @return getQuery((SpringEntity)null)
037     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperationLogic#getQuery()
038     */
039    protected String handleGetQuery()
040    {
041        return this.getQuery((SpringEntity)null);
042    }
043
044    /**
045     * Stores the translated query so that its only translated once.
046     */
047    private String translatedQuery = null;
048
049    /**
050     * Retrieves the translated query.
051     */
052    private String getTranslatedQuery()
053    {
054        if (this.translatedQuery == null)
055        {
056            this.translatedQuery = super.getQuery("query.Hibernate-QL");
057        }
058        return this.translatedQuery;
059    }
060
061    /**
062     * Stores whether or not named parameters should be used in hibernate queries.
063     */
064    private static final String USE_NAMED_PARAMETERS = "hibernateQueryUseNamedParameters";
065
066    /**
067     * @return SpringMetafacadeUtils.getUseNamedParameters(this, useNamedParameters)
068     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperationLogic#isUseNamedParameters()
069     */
070    protected boolean handleIsUseNamedParameters()
071    {
072        boolean useNamedParameters = Boolean.valueOf(String.valueOf(this.getConfiguredProperty(USE_NAMED_PARAMETERS)))
073                .booleanValue()
074                || StringUtils.isNotBlank(this.getTranslatedQuery());
075
076        return SpringMetafacadeUtils.getUseNamedParameters(this, useNamedParameters);
077    }
078
079    /**
080     * @return getCriteriaArgument() != null
081     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperation#isCriteriaFinder()
082     */
083    protected boolean handleIsCriteriaFinder()
084    {
085        return this.getCriteriaArgument() != null;
086    }
087
088    /**
089     * @return Parameter with UMLProfile.STEREOTYPE_CRITERIA
090     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperation#getCriteriaArgument()
091     */
092    protected ParameterFacade handleGetCriteriaArgument()
093    {
094        ParameterFacade foundParameter = null;
095        for (final ParameterFacade parameter : this.getParameters())
096        {
097            final ClassifierFacade type = parameter.getType();
098            if (type != null && type.hasStereotype(UMLProfile.STEREOTYPE_CRITERIA))
099            {
100                foundParameter = parameter;
101                break;
102            }
103        }
104        return foundParameter;
105    }
106
107    /**
108     * @param entity
109     * @return query
110     * @see org.andromda.cartridges.spring.metafacades.SpringQueryOperation#getQuery(org.andromda.cartridges.spring.metafacades.SpringEntity)
111     */
112    protected String handleGetQuery(SpringEntity entity)
113    {
114        // first see if we can retrieve the query from the super class as an OCL
115        // translation
116        String queryString = this.getTranslatedQuery();
117
118        // otherwise see if there is a query stored as a tagged value
119        if (StringUtils.isBlank(queryString))
120        {
121            Object value = this.findTaggedValue(SpringProfile.TAGGEDVALUE_HIBERNATE_QUERY);
122            queryString = (String)value;
123            if (queryString != null)
124            {
125                // remove any excess whitespace
126                queryString = queryString.replaceAll("[$\\s]+", " ");
127            }
128        }
129
130        // if there wasn't any stored query, create one by default.
131        if (StringUtils.isBlank(queryString))
132        {
133            ModelElementFacade owner = null;
134            String entityName = null;
135            if (entity == null)
136            {
137                owner = this.getOwner();
138                entityName = owner.getFullyQualifiedName();
139            }
140            else
141            {
142                owner = entity;
143                //retrieve the entity implementation for proper hibernate mapping resolving
144                entityName = entity.getFullyQualifiedEntityImplementationName();
145            }
146            String variableName = StringUtils.uncapitalize(owner.getName());
147            queryString = "from " + entityName + " as " + variableName;
148            if (!this.getArguments().isEmpty())
149            {
150                queryString += " where";
151                Collection<ParameterFacade> arguments = this.getArguments();
152                Iterator<ParameterFacade> iterator = arguments.iterator();
153                while(iterator.hasNext())
154                {
155                    final ParameterFacade argument = iterator.next();
156                    final ClassifierFacade type = argument.getType();
157                    if (type != null)
158                    {
159                        final String parameterName = argument.getName();
160                        if (type.isEmbeddedValue())
161                        {
162                            for (final Iterator<AttributeFacade> attributeIterator = type.getAttributes(true).iterator(); attributeIterator.hasNext();)
163                            {
164                                final AttributeFacade attribute = attributeIterator.next();
165                                String parameter = "?";
166                                if (this.isUseNamedParameters())
167                                {
168                                    parameter = ':' + SpringUtils.concatNamesCamelCase(Arrays.asList(parameterName, attribute.getName()));
169                                }
170                                queryString += ' ' + variableName + '.' + parameterName + '.' + attribute.getName() + " = " + parameter;
171                                if (attributeIterator.hasNext())
172                                {
173                                    queryString += " and";
174                                }
175                            }
176                        }
177                        else
178                        {
179                            String parameter = "?";
180                            if (this.isUseNamedParameters())
181                            {
182                                parameter = ':' + parameterName;
183                            }
184                            queryString += ' ' + variableName + '.' + parameterName + " = " + parameter;
185                            if (iterator.hasNext())
186                            {
187                                queryString += " and";
188                            }
189                        }
190                    }
191                }
192            }
193        }
194        return queryString;
195    }
196}