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.test.map;
018:
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import org.compass.core.CompassException;
024: import org.compass.core.Property;
025: import org.compass.core.Resource;
026: import org.compass.core.ResourceFactory;
027: import org.compass.core.config.CompassConfigurable;
028: import org.compass.core.config.CompassSettings;
029: import org.compass.core.converter.ConversionException;
030: import org.compass.core.converter.Converter;
031: import org.compass.core.engine.naming.PropertyNamingStrategy;
032: import org.compass.core.mapping.Mapping;
033: import org.compass.core.mapping.ResourcePropertyMapping;
034: import org.compass.core.marshall.MarshallingContext;
035: import org.compass.core.util.StringUtils;
036:
037: /**
038: * This is a sample converter that can handle {@link Map} and save dynamic properties into the index.
039: * <p/>
040: * Saves dynamic properties, with the map keys as the properties names and map values as the property
041: * values. Uses the Object toString to convert the key and values objects to strings.
042: * <p/>
043: * If the converter will support unmarshalling, than assumes that the key and the value are of type
044: * {@link String}. Saves the keys as comma delimited string under an internal property, and the
045: * values the same under a different property.
046: * <p/>
047: * Note, that using this converter might affect the Class mapping that uses the Map as a property.
048: * If another meta-data is mapped to a name that might be one of the dynamic property names, it must
049: * be set to have the intenal id always generated. It also applies to a class that has this class as
050: * component mapping.
051: * <p/>
052: * This Converter is provided as a baseline for different maps converters that might hold different
053: * object types than Strings.
054: *
055: * @author kimchy
056: */
057: public class MapConverter implements Converter, CompassConfigurable {
058:
059: private boolean supportUnmarshall = true;
060:
061: public void configure(CompassSettings settings)
062: throws CompassException {
063: supportUnmarshall = settings.getSettingAsBoolean(
064: "supportUnmarshall", true);
065: }
066:
067: public boolean marshall(Resource resource, Object root,
068: Mapping mapping, MarshallingContext context)
069: throws ConversionException {
070: if (root == null && !context.handleNulls()) {
071: return false;
072: }
073:
074: ResourcePropertyMapping resourcePropertyMapping = (ResourcePropertyMapping) mapping;
075: ResourceFactory resourceFactory = context.getResourceFactory();
076:
077: Map map = (Map) root;
078: for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
079: Map.Entry entry = (Map.Entry) it.next();
080: Property p = resourceFactory.createProperty(entry.getKey()
081: .toString(), entry.getValue().toString(),
082: resourcePropertyMapping.getStore(),
083: resourcePropertyMapping.getIndex(),
084: resourcePropertyMapping.getTermVector());
085: p.setBoost(resourcePropertyMapping.getBoost());
086: resource.addProperty(p);
087: }
088:
089: if (supportUnmarshall) {
090: StringBuffer keys = new StringBuffer();
091: StringBuffer values = new StringBuffer();
092: for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
093: Map.Entry entry = (Map.Entry) it.next();
094: keys.append(entry.getKey().toString()).append(",");
095: values.append(entry.getValue().toString()).append(",");
096: }
097: PropertyNamingStrategy propertyNamingStrategy = context
098: .getSession().getCompass().getSearchEngineFactory()
099: .getPropertyNamingStrategy();
100: // save keys (under an internal name)
101: String keyPath = propertyNamingStrategy.buildPath(
102: resourcePropertyMapping.getPath(), "keys")
103: .getPath();
104: Property p = resourceFactory.createProperty(keyPath, keys
105: .toString(), Property.Store.YES,
106: Property.Index.UN_TOKENIZED);
107: resource.addProperty(p);
108: // save values (under an internal name)
109: String valuePath = propertyNamingStrategy.buildPath(
110: resourcePropertyMapping.getPath(), "values")
111: .getPath();
112: p = resourceFactory.createProperty(valuePath, values
113: .toString(), Property.Store.YES,
114: Property.Index.UN_TOKENIZED);
115: resource.addProperty(p);
116: }
117:
118: return true;
119: }
120:
121: public Object unmarshall(Resource resource, Mapping mapping,
122: MarshallingContext context) throws ConversionException {
123: if (!supportUnmarshall) {
124: return null;
125: }
126:
127: ResourcePropertyMapping resourcePropertyMapping = (ResourcePropertyMapping) mapping;
128:
129: PropertyNamingStrategy propertyNamingStrategy = context
130: .getSession().getCompass().getSearchEngineFactory()
131: .getPropertyNamingStrategy();
132: // save keys (under an internal name)
133: String keyPath = propertyNamingStrategy.buildPath(
134: resourcePropertyMapping.getPath(), "keys").getPath();
135: String strKeys = resource.getValue(keyPath);
136: if (strKeys == null) {
137: return null;
138: }
139: String valuePath = propertyNamingStrategy.buildPath(
140: resourcePropertyMapping.getPath(), "values").getPath();
141: String strValues = resource.getValue(valuePath);
142: String[] keys = StringUtils.tokenizeToStringArray(strKeys, ",");
143: String[] values = StringUtils.tokenizeToStringArray(strValues,
144: ",");
145: if (keys.length != values.length) {
146: throw new ConversionException("Keys with length ["
147: + keys.length + "] does not match values length ["
148: + values.length + "]");
149: }
150: Map map = new HashMap();
151: for (int i = 0; i < keys.length; i++) {
152: map.put(keys[i], values[i]);
153: }
154: return map;
155: }
156:
157: public boolean isSupportUnmarshall() {
158: return supportUnmarshall;
159: }
160:
161: public void setSupportUnmarshall(boolean supportUnmarshall) {
162: this.supportUnmarshall = supportUnmarshall;
163: }
164: }
|