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.converter.basic;
018:
019: import org.compass.core.Property;
020: import org.compass.core.Resource;
021: import org.compass.core.converter.ConversionException;
022: import org.compass.core.converter.ResourcePropertyConverter;
023: import org.compass.core.mapping.Mapping;
024: import org.compass.core.mapping.ResourcePropertyMapping;
025: import org.compass.core.marshall.MarshallingContext;
026:
027: /**
028: * An easy to use abstact class for Basic converters. Handles converters that usually deals with String
029: * as a result of the conversion.
030: *
031: * <p>Allows to override the actual marshalling and un-marshalling of object to strings. In order to override
032: * marshalling, override {@link #doToString(Object,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}
033: * and in order to override un-marshalling overrode
034: * {@link #doFromString(String,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}.
035: *
036: * @author kimchy
037: */
038: public abstract class AbstractBasicConverter implements
039: ResourcePropertyConverter {
040:
041: public boolean marshall(Resource resource, Object root,
042: Mapping mapping, MarshallingContext context)
043: throws ConversionException {
044:
045: ResourcePropertyMapping resourcePropertyMapping = (ResourcePropertyMapping) mapping;
046:
047: // don't save a null value if the context does not states so
048: if (root == null
049: && !handleNulls(resourcePropertyMapping, context)) {
050: return false;
051: }
052: String sValue = toString(root, resourcePropertyMapping, context);
053: Property p = createProperty(sValue, resourcePropertyMapping,
054: context);
055: doSetBoost(p, root, resourcePropertyMapping, context);
056: resource.addProperty(p);
057:
058: return resourcePropertyMapping.getStore() != Property.Store.NO;
059: }
060:
061: public Object unmarshall(Resource resource, Mapping mapping,
062: MarshallingContext context) throws ConversionException {
063: ResourcePropertyMapping resourcePropertyMapping = (ResourcePropertyMapping) mapping;
064:
065: if (resourcePropertyMapping.getStore() == Property.Store.NO) {
066: // it is not stored, so don't bother with converting it
067: return null;
068: }
069:
070: String propertyName = resourcePropertyMapping.getPath()
071: .getPath();
072: Property p = resource.getProperty(propertyName);
073:
074: // don't set anything if null
075: if (p == null) {
076: return null;
077: }
078:
079: return fromString(p.getStringValue(), resourcePropertyMapping,
080: context);
081: }
082:
083: /**
084: * Creates a new property to be added to the resource during the marshalling process. Allows
085: * sub classes to override ti in order to modify the created property.
086: *
087: * @param value The value of the property
088: * @param resourcePropertyMapping The resource mapping definition of the property
089: * @param context The context (allows to get the search engine from it)
090: * @return The property to be added to the Resource
091: */
092: protected Property createProperty(String value,
093: ResourcePropertyMapping resourcePropertyMapping,
094: MarshallingContext context) {
095: return context.getResourceFactory().createProperty(value,
096: resourcePropertyMapping);
097: }
098:
099: /**
100: * <p>Should the converter handle nulls? Handling nulls means should the
101: * converter process nulls or not. Usually the converter will not
102: * persist null values, but sometimes it might be needed
103: * ({@link org.compass.core.marshall.MarshallingContext#handleNulls()}).
104: *
105: * <p>If a specific null value is configured with the {@link org.compass.core.mapping.ResourcePropertyMapping}
106: * then the converter will always handle nulls and write it.
107: *
108: * @param context The marshalling context
109: * @return <code>true</code> if the converter should handle null values
110: */
111: protected boolean handleNulls(
112: ResourcePropertyMapping resourcePropertyMapping,
113: MarshallingContext context) {
114: return resourcePropertyMapping.hasNullValue()
115: || context.handleNulls();
116: }
117:
118: /**
119: * If the converter handle nulls, the value that will be stored in the
120: * search engine for <code>null</code> values (during the marshall process). Uses
121: * {@link org.compass.core.mapping.ResourcePropertyMapping#getNullValue()}.
122: *
123: * @param resourcePropertyMapping The resource proeprty mapping to get the null value from
124: * @param context The marshalling context
125: * @return Null value that will be inserted for <code>null</code>s.
126: */
127: protected String getNullValue(
128: ResourcePropertyMapping resourcePropertyMapping,
129: MarshallingContext context) {
130: return resourcePropertyMapping.getNullValue();
131: }
132:
133: /**
134: * Does this value represents a null value. If the {@link org.compass.core.mapping.ResourcePropertyMapping}
135: * is configured with a null value, then returns <code>true</code> if the null value equals the value read
136: * from the index. If the resource property mapping is not configured with a null value, checks if this
137: * it has the default value representing a null value.
138: */
139: protected boolean isNullValue(String value,
140: ResourcePropertyMapping resourcePropertyMapping,
141: MarshallingContext context) {
142: if (value == null) {
143: return true;
144: }
145: if (resourcePropertyMapping.hasNullValue()) {
146: return resourcePropertyMapping.getNullValue().equals(value);
147: }
148: // the default null value is an empty string
149: return value.length() == 0;
150: }
151:
152: /**
153: * <p>A simple extension point that allows to set the boost value for the created {@link Property}.
154: *
155: * <p>The default implemenation uses the statically defined boost value in the mapping definition
156: * ({@link org.compass.core.mapping.ResourcePropertyMapping#getBoost()}) to set the boost level
157: * using {@link Property#setBoost(float)}
158: *
159: * @param property The property to set the boost on
160: * @param root The object that is marshalled into a property
161: * @param resourcePropertyMapping The Resource Property Mapping definition
162: * @throws ConversionException
163: */
164: protected void doSetBoost(Property property, Object root,
165: ResourcePropertyMapping resourcePropertyMapping,
166: MarshallingContext context) throws ConversionException {
167: property.setBoost(resourcePropertyMapping.getBoost());
168: }
169:
170: /**
171: * Implementation calls {@link #toString(Object,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}
172: * with <code>null</code> value for the context parameter.
173: *
174: * <p>Note, please don't override this method, please override {@link #doToString(Object,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}
175: * to change the how the object gets marshalled into a String.
176: */
177: public String toString(Object o,
178: ResourcePropertyMapping resourcePropertyMapping) {
179: return toString(o, resourcePropertyMapping, null);
180: }
181:
182: /**
183: * Implementation handle nulls and if the object is not null, delegates to
184: * {@link #doToString(Object,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}.
185: *
186: * <p>Note, please don't override this method, please override {@link #doToString(Object,org.compass.core.mapping.ResourcePropertyMapping,org.compass.core.marshall.MarshallingContext)}
187: * to change the how the object gets marshalled into a String.
188: */
189: protected String toString(Object o,
190: ResourcePropertyMapping resourcePropertyMapping,
191: MarshallingContext context) {
192: String sValue;
193: if (o != null) {
194: sValue = doToString(o, resourcePropertyMapping, context);
195: } else {
196: sValue = getNullValue(resourcePropertyMapping, context);
197: }
198: return sValue;
199: }
200:
201: /**
202: * Allows to override to toString operation. Default implementation calls the object <code>toString</code>.
203: *
204: * <p>Note, the marshalling context might be null.
205: */
206: protected String doToString(Object o,
207: ResourcePropertyMapping resourcePropertyMapping,
208: MarshallingContext context) {
209: return o.toString();
210: }
211:
212: /**
213: * Calls {@link #fromString(String, org.compass.core.mapping.ResourcePropertyMapping, org.compass.core.marshall.MarshallingContext)}
214: * with a null value for the context.
215: */
216: public Object fromString(String str,
217: ResourcePropertyMapping resourcePropertyMapping)
218: throws ConversionException {
219: return fromString(str, resourcePropertyMapping, null);
220: }
221:
222: /**
223: * Performs null checks (by calling {@link #isNullValue(String, org.compass.core.mapping.ResourcePropertyMapping, org.compass.core.marshall.MarshallingContext)})
224: * and then calls {@link #doFromString(String, org.compass.core.mapping.ResourcePropertyMapping, org.compass.core.marshall.MarshallingContext)}
225: * if the value is not <code>null</code>.
226: */
227: protected Object fromString(String str,
228: ResourcePropertyMapping resourcePropertyMapping,
229: MarshallingContext context) throws ConversionException {
230: if (isNullValue(str, resourcePropertyMapping, context)) {
231: return null;
232: }
233: return doFromString(str, resourcePropertyMapping, context);
234: }
235:
236: /**
237: * Override the from String in order to un-marshall the String back into its object representation.
238: */
239: protected abstract Object doFromString(String str,
240: ResourcePropertyMapping resourcePropertyMapping,
241: MarshallingContext context) throws ConversionException;
242:
243: /**
244: * Return <code>false</code>. Specific parsers that can convert on query string should override this method
245: * and return <code>true</code>.
246: */
247: public boolean canNormalize() {
248: return false;
249: }
250: }
|