001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.config.process;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Set;
024: import java.util.SortedSet;
025:
026: import org.compass.core.config.CompassSettings;
027: import org.compass.core.converter.Converter;
028: import org.compass.core.converter.ConverterLookup;
029: import org.compass.core.engine.naming.PropertyNamingStrategy;
030: import org.compass.core.mapping.AliasMapping;
031: import org.compass.core.mapping.CompassMapping;
032: import org.compass.core.mapping.Mapping;
033: import org.compass.core.mapping.MappingException;
034: import org.compass.core.mapping.OverrideByNameMapping;
035: import org.compass.core.mapping.osem.AbstractCollectionMapping;
036: import org.compass.core.mapping.osem.ArrayMapping;
037: import org.compass.core.mapping.osem.ClassMapping;
038: import org.compass.core.mapping.osem.CollectionMapping;
039: import org.compass.core.mapping.osem.ObjectMapping;
040:
041: /**
042: * Goes over all the OSEM {@link org.compass.core.mapping.osem.ClassMapping}s. For each
043: * class mappings, goes over all of its mappings and checks if they represent a collection/array.
044: * If they represent a collection/array, wraps them with either a {@link org.compass.core.mapping.osem.CollectionMapping}
045: * or an {@link org.compass.core.mapping.osem.ArrayMapping}. Copies over the mappings types and set it as the
046: * collection/array element mapping.
047: *
048: * <p>A note on element mapping: Compass simplifies mappings for collection. There is no need for different
049: * property/component/reference mappings when handling collections/arrays. So, the actual mappings (property/
050: * component/reference) actually refers to the element mapping, which is why the mapping constructed is copied
051: * over as the element mapping.
052: *
053: * @author kimchy
054: */
055: public class CollectionMappingProcessor implements MappingProcessor {
056:
057: private ConverterLookup converterLookup;
058:
059: public CompassMapping process(CompassMapping compassMapping,
060: PropertyNamingStrategy namingStrategy,
061: ConverterLookup converterLookup, CompassSettings settings)
062: throws MappingException {
063:
064: this .converterLookup = converterLookup;
065:
066: ArrayList colMappingsToAdd = new ArrayList();
067:
068: for (Iterator mappIt = compassMapping.mappingsIt(); mappIt
069: .hasNext();) {
070: AliasMapping aliasMapping = (AliasMapping) mappIt.next();
071: if (!(aliasMapping instanceof ClassMapping)) {
072: continue;
073: }
074: colMappingsToAdd.clear();
075:
076: ClassMapping classMapping = (ClassMapping) aliasMapping;
077: for (Iterator it = classMapping.mappingsIt(); it.hasNext();) {
078: Mapping mapping = (Mapping) it.next();
079: if ((mapping instanceof ObjectMapping)) {
080: ObjectMapping objectMapping = (ObjectMapping) mapping;
081: if (objectMapping.canBeCollectionWrapped()) {
082: Mapping maybeColMapping = checkCollection(objectMapping);
083: // check if we wrapped the mapping as a collection, if we did
084: // remove id and re-add it later
085: if (maybeColMapping instanceof AbstractCollectionMapping) {
086: colMappingsToAdd.add(maybeColMapping);
087: it.remove();
088: }
089: }
090: }
091: }
092:
093: for (Iterator it = colMappingsToAdd.iterator(); it
094: .hasNext();) {
095: Mapping mapping = (Mapping) it.next();
096: classMapping.addMapping(mapping);
097: }
098: }
099:
100: return compassMapping;
101: }
102:
103: /**
104: * An attibute/component/reference might be a collection/array. The method
105: * check if they represent a collection, and if they are, configures a
106: * collection mapping with them as the collection element mapping.
107: */
108: private Mapping checkCollection(ObjectMapping objectMapping)
109: throws MappingException {
110: AbstractCollectionMapping collectionMapping = null;
111: Class collectionClass = objectMapping.getGetter()
112: .getReturnType();
113: if (Collection.class.isAssignableFrom(collectionClass)) {
114: collectionMapping = new CollectionMapping();
115: if (List.class.isAssignableFrom(collectionClass)) {
116: collectionMapping
117: .setCollectionType(AbstractCollectionMapping.CollectionType.LIST);
118: } else if (SortedSet.class
119: .isAssignableFrom(collectionClass)) {
120: collectionMapping
121: .setCollectionType(AbstractCollectionMapping.CollectionType.SORTED_SET);
122: } else if (Set.class.isAssignableFrom(collectionClass)) {
123: collectionMapping
124: .setCollectionType(AbstractCollectionMapping.CollectionType.SET);
125: } else {
126: collectionMapping
127: .setCollectionType(AbstractCollectionMapping.CollectionType.UNKNOWN);
128: }
129: } else if (collectionClass.isArray()) {
130: Converter converter = converterLookup
131: .lookupConverter(objectMapping.getGetter()
132: .getReturnType());
133: if (converter == null) {
134: // there is no converter assigned to that array, use the array
135: // mapping to convert each element inside, otherwise the
136: // converter will be responsible to convert the whole array
137: collectionMapping = new ArrayMapping();
138: collectionMapping
139: .setCollectionType(AbstractCollectionMapping.CollectionType.NOT_REQUIRED);
140: }
141: }
142: if (collectionMapping != null) {
143: collectionMapping.setElementMapping(objectMapping);
144: // setting the collection (the same as the inner element mapping)
145: collectionMapping.setGetter(objectMapping.getGetter());
146: collectionMapping.setSetter(objectMapping.getSetter());
147: collectionMapping.setName(objectMapping.getName());
148: collectionMapping.setPath(objectMapping.getPath());
149: collectionMapping.setPropertyName(objectMapping
150: .getPropertyName());
151: if (objectMapping instanceof OverrideByNameMapping) {
152: collectionMapping
153: .setOverrideByName(((OverrideByNameMapping) objectMapping)
154: .isOverrideByName());
155: } else {
156: collectionMapping.setOverrideByName(true);
157: }
158: return collectionMapping;
159: } else {
160: return objectMapping;
161: }
162: }
163: }
|