001: package org.compass.core.mapping;
002:
003: import org.compass.core.converter.Converter;
004: import org.compass.core.converter.ResourcePropertyConverter;
005:
006: /**
007: * A simple lookup class, for a given path, will provide simple access to
008: * it's path and value converter. Also supports path escaping ('a.b' or will
009: * result in a.b and not alias a and resource property b).
010: */
011: public final class ResourcePropertyLookup {
012:
013: private AliasMapping aliasMapping;
014:
015: private ResourcePropertyMapping resourcePropertyMapping;
016:
017: private ResourcePropertyMapping[] resourcePropertyMappings;
018:
019: private String lookupName;
020:
021: private String path;
022:
023: private String dotPathAlias;
024:
025: private boolean convertOnlyWithDotPath = true;
026: private CompassMapping compassMapping;
027:
028: public ResourcePropertyLookup(CompassMapping compassMapping,
029: String name) {
030: this .compassMapping = compassMapping;
031: this .lookupName = name;
032: // the path is escaped, so don't try to look it up
033: if (name.charAt(0) == '\''
034: && name.charAt(name.length() - 1) == '\'') {
035: path = name.substring(1, name.length() - 1);
036: } else {
037: int dotIndex = name.indexOf('.');
038: if (dotIndex != -1) {
039: dotPathAlias = name.substring(0, dotIndex);
040: aliasMapping = compassMapping
041: .getAliasMapping(dotPathAlias);
042: }
043: this .resourcePropertyMapping = compassMapping
044: .getResourcePropertyMappingByPath(name);
045: if (resourcePropertyMapping == null) {
046: path = name;
047: } else {
048: path = resourcePropertyMapping.getPath().getPath();
049: }
050: resourcePropertyMappings = compassMapping
051: .getResourcePropertyMappingsByPath(path);
052: // did not find the resource mapping using "dot path", try and see if we can find a global one
053: if (resourcePropertyMappings != null
054: && resourcePropertyMapping == null) {
055: resourcePropertyMapping = resourcePropertyMappings[0];
056: }
057: }
058: }
059:
060: /**
061: * Perform specialized convert only when dot path is used. Defaults to <code>true</code>.
062: *
063: * <p>Sometimes, several meta-data names are used with different converteres. For example
064: * map to title both a pure String value and also a numeric value. If using dot path
065: * notation, Compass will narrow down to the specfic converter (for example a.title.title).
066: * When not using dot path notation, Compass now has two options for conversion. If this
067: * flag is set to true (and not using dot path notation), Compass will use a converter based
068: * on the object type. If this flag is set to false, the first mapping is used to convert.
069: */
070: public void setConvertOnlyWithDotPath(boolean convertOnlyWithDotPath) {
071: this .convertOnlyWithDotPath = convertOnlyWithDotPath;
072: }
073:
074: /**
075: * Returns the analyzer associated with the resource property. <code>null</code> if none
076: * is configured on the resource property or resource level.
077: */
078: public String getAnalyzer() {
079: if (resourcePropertyMapping != null) {
080: if (resourcePropertyMapping.getAnalyzer() != null) {
081: return resourcePropertyMapping.getAnalyzer();
082: }
083: }
084: return null;
085: }
086:
087: /**
088: * Returns the lookup name used in order to find the meta-data/property name.
089: */
090: public String getLookupName() {
091: return lookupName;
092: }
093:
094: /**
095: * Returns the alias used if using dot path notation. Returns <code>null</code> if dot path notation
096: * was not used.
097: */
098: public String getDotPathAlias() {
099: return dotPathAlias;
100: }
101:
102: /**
103: * Returns the alias mapping if using dot path notation. Returns <code>null</code> if dot path notation
104: * was not used.
105: */
106: public AliasMapping getAliasMapping() {
107: return aliasMapping;
108: }
109:
110: /**
111: * Returns the path matching the provided name. The path is the actual name used to store in
112: * the index.
113: */
114: public String getPath() {
115: return path;
116: }
117:
118: /**
119: * Returns the property mapping for the provided name. If not using dot path notation, will
120: * return the first one that match the "meta-data" name within all of Compass mappings.
121: */
122: public ResourcePropertyMapping getResourcePropertyMapping() {
123: return resourcePropertyMapping;
124: }
125:
126: /**
127: * Returns a list of property mappings for the provided name. When not using "dot path" which
128: * allows to narrows down to a specific property mapping, and a general meta-data name is used
129: * (such as title), will return all the property mappings for it within Compass mappings.
130: */
131: public ResourcePropertyMapping[] getResourcePropertyMappings() {
132: if (resourcePropertyMappings == null
133: && resourcePropertyMapping != null) {
134: resourcePropertyMappings = new ResourcePropertyMapping[] { resourcePropertyMapping };
135: }
136: return resourcePropertyMappings;
137: }
138:
139: /**
140: * Returns <code>true</code> if there is a specific converter that can be used to convert the
141: * value.
142: *
143: * <p>Note, when {@link #setConvertOnlyWithDotPath(boolean)} is set the <code>true</code>, and
144: * the name passed to the lookup does not contain "dot notation", <code>false</code> will be returned.
145: */
146: public boolean hasSpecificConverter() {
147: if (dotPathAlias == null && convertOnlyWithDotPath) {
148: return false;
149: }
150: return resourcePropertyMapping != null
151: && resourcePropertyMapping.getConverter() != null;
152: }
153:
154: /**
155: * Returns the String representation of the provided value Object. If {@link #hasSpecificConverter()}
156: * return <code>true</code>, will use the first mapping definition for the given name in order to
157: * convert it from Object to String. If it returns false, will use a Converter assigned to the given
158: * parameter class.
159: *
160: * @see org.compass.core.converter.ResourcePropertyConverter
161: */
162: public String getValue(Object value) {
163: if (value instanceof String) {
164: return normalizeString((String) value);
165: }
166: ResourcePropertyConverter converter = null;
167: if (hasSpecificConverter()) {
168: converter = (ResourcePropertyConverter) resourcePropertyMapping
169: .getConverter();
170: }
171: if (converter == null) {
172: converter = (ResourcePropertyConverter) compassMapping
173: .getConverterLookup().lookupConverter(
174: value.getClass());
175: }
176: return converter.toString(value, resourcePropertyMapping);
177: }
178:
179: /**
180: * Returns the Object converted from the String value. If the {@link #hasSpecificConverter()} returns
181: * <code>true</code>, will use the first mapping definition for the given name in order to conver it
182: * from String to Object. If it returns <code>false</code>, will use a Converter assigned to the
183: * given parameter class.
184: *
185: * @see org.compass.core.converter.ResourcePropertyConverter
186: */
187: public Object fromString(String value) {
188: ResourcePropertyConverter converter;
189: if (hasSpecificConverter()) {
190: converter = (ResourcePropertyConverter) resourcePropertyMapping
191: .getConverter();
192: } else {
193: converter = (ResourcePropertyConverter) compassMapping
194: .getConverterLookup().lookupConverter(
195: value.getClass());
196: }
197: return converter.fromString(value, resourcePropertyMapping);
198: }
199:
200: /**
201: * Normalizes a given String value to a (hopefully) String value that mathces the one stored in the
202: * index.
203: *
204: * <p>If {@link #hasSpecificConverter()} return <code>false</code> (note {@link #setConvertOnlyWithDotPath(boolean)})
205: * will simply return the given value.
206: *
207: * <p>If the {@link org.compass.core.converter.ResourcePropertyConverter} states that it should not be used
208: * for normalization ({@link org.compass.core.converter.ResourcePropertyConverter#canNormalize()} returns
209: * <code>false</code>), the provided value will be returned.
210: *
211: * <p>If none of the above happens, will conver it
212: * {@link org.compass.core.converter.ResourcePropertyConverter#fromString(String, org.compass.core.mapping.ResourcePropertyMapping)}
213: * and then {@link org.compass.core.converter.ResourcePropertyConverter#toString(Object, org.compass.core.mapping.ResourcePropertyMapping)}.
214: */
215: public String normalizeString(String value) {
216: if (!hasSpecificConverter()) {
217: return value;
218: }
219: Converter converter = resourcePropertyMapping.getConverter();
220: if (!(converter instanceof ResourcePropertyConverter)) {
221: return value;
222: }
223: ResourcePropertyConverter rpConverter = (ResourcePropertyConverter) converter;
224: if (!rpConverter.canNormalize()) {
225: return value;
226: }
227: return rpConverter.toString(rpConverter.fromString(value,
228: resourcePropertyMapping), resourcePropertyMapping);
229: }
230: }
|