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.accessor;
018:
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025: import org.compass.core.CompassException;
026: import org.compass.core.config.CompassConfigurable;
027: import org.compass.core.config.CompassEnvironment;
028: import org.compass.core.config.CompassSettings;
029: import org.compass.core.config.ConfigurationException;
030: import org.compass.core.mapping.MappingException;
031: import org.compass.core.util.ClassUtils;
032:
033: /**
034: * A factory that creates a {@link PropertyAccessor}.
035: * <p/>
036: * Acts as a registry for property accessors, with two default implementations,
037: * {@link BasicPropertyAccessor} registered under "property", and {@link DirectPropertyAccessor}
038: * registered under "field".
039: * <p/>
040: * Allows for configuration of new property accessors, and register them under new/same names.
041: * Configuration is using the {@link org.compass.core.config.CompassEnvironment.PropertyAccessor}.
042: *
043: * @author kimchy
044: */
045: public class PropertyAccessorFactory implements CompassConfigurable {
046:
047: private static final Log log = LogFactory
048: .getLog(PropertyAccessorFactory.class);
049:
050: private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
051:
052: private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor();
053:
054: private Map propertyAccessorsRegistry = new HashMap();
055:
056: /**
057: * Configures the property accessor registry, using the two default ones (field and property),
058: * and any external registered ones.
059: */
060: public void configure(CompassSettings settings)
061: throws CompassException {
062: propertyAccessorsRegistry.put("property",
063: BASIC_PROPERTY_ACCESSOR);
064: propertyAccessorsRegistry
065: .put("field", DIRECT_PROPERTY_ACCESSOR);
066:
067: Map paGroups = settings
068: .getSettingGroups(CompassEnvironment.PropertyAccessor.PREFIX);
069: for (Iterator it = paGroups.keySet().iterator(); it.hasNext();) {
070: String paName = (String) it.next();
071: if (log.isDebugEnabled()) {
072: log.debug("Property Accessor [" + paName
073: + "] building...");
074: }
075: CompassSettings paSettings = (CompassSettings) paGroups
076: .get(paName);
077: String paType = paSettings
078: .getSetting(CompassEnvironment.PropertyAccessor.TYPE);
079: if (paType == null) {
080: throw new ConfigurationException(
081: "Must define type for property accessor ["
082: + paName + "]");
083: }
084: PropertyAccessor propertyAccessor;
085: try {
086: propertyAccessor = (PropertyAccessor) ClassUtils
087: .forName(paType, settings.getClassLoader())
088: .newInstance();
089: } catch (Exception e) {
090: throw new ConfigurationException(
091: "Failed to create property accessor [" + paName
092: + "] type", e);
093: }
094: if (propertyAccessor instanceof CompassConfigurable) {
095: ((CompassConfigurable) propertyAccessor)
096: .configure(paSettings);
097: }
098: propertyAccessorsRegistry.put(paName, propertyAccessor);
099: }
100: }
101:
102: /**
103: * Returns a new property accessor that match the given type. If the type is <code>null</code>
104: * will return the {@link BasicPropertyAccessor}. If the type can be found in the pre
105: * configured registry of property accessors, will return it. If nothing is found in
106: * the registry will try to instanciate it using the type as the class name.
107: */
108: public PropertyAccessor getPropertyAccessor(String type,
109: CompassSettings settings) throws MappingException {
110:
111: if (type == null) {
112: PropertyAccessor propertyAccessor = (PropertyAccessor) propertyAccessorsRegistry
113: .get(CompassEnvironment.PropertyAccessor.DEFAULT_GROUP);
114: if (propertyAccessor != null) {
115: return propertyAccessor;
116: }
117: return BASIC_PROPERTY_ACCESSOR;
118: }
119:
120: PropertyAccessor propertyAccessor = (PropertyAccessor) propertyAccessorsRegistry
121: .get(type);
122: if (propertyAccessor != null) {
123: return propertyAccessor;
124: }
125:
126: Class accessorClass;
127: try {
128: accessorClass = ClassUtils.forName(type, settings
129: .getClassLoader());
130: } catch (ClassNotFoundException cnfe) {
131: throw new MappingException(
132: "Could not find PropertyAccessor class [" + type
133: + "]", cnfe);
134: }
135: try {
136: return (PropertyAccessor) accessorClass.newInstance();
137: } catch (Exception e) {
138: throw new MappingException(
139: "Could not instantiate PropertyAccessor class ["
140: + type + "]", e);
141: }
142:
143: }
144: }
|