001: /**
002: * Copyright (C) 2006 NetMind Consulting Bt.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 3 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package hu.netmind.persistence;
018:
019: import java.util.HashMap;
020: import java.util.Map;
021: import java.util.List;
022: import java.util.Vector;
023: import java.util.Iterator;
024: import java.lang.reflect.Field;
025: import java.lang.reflect.Modifier;
026: import org.apache.log4j.Logger;
027: import java.util.Date;
028:
029: /**
030: * Information and transformations on a given class.
031: * @author Brautigam Robert
032: * @version Revision: $Revision$
033: */
034: public class ClassInfo {
035: private static Logger logger = Logger.getLogger(ClassInfo.class);
036:
037: protected StoreContext context;
038: protected ClassEntry sourceEntry;
039: protected HashMap handlersByAttribute;
040: protected HashMap handlersByEntry;
041: protected Vector classEntries;
042:
043: public ClassInfo(StoreContext context, ClassEntry sourceEntry) {
044: this .sourceEntry = sourceEntry;
045: // Assemble the attribute list
046: handlersByAttribute = new HashMap();
047: handlersByEntry = new HashMap();
048: classEntries = new Vector();
049: // Assemble the attribute list
050: ClassEntry localEntry = sourceEntry;
051: while (localEntry != null) {
052: logger.debug("analyzing entry for class info: "
053: + localEntry);
054: // Add to all class entries, if it is storable
055: if (localEntry.isStorable())
056: classEntries.add(localEntry);
057: // Determine handler for strict class, there are
058: // four kinds of handlers:
059: // - Null handler: has no attributes ever
060: // - Static handler: attributes are determined from reflection
061: // - Dynamic handler: attributes are determined with call to dynamic object
062: // - Primitive handler: primitive types
063: StrictClassHandler handler;
064: if (localEntry.isEmpty())
065: handler = new StrictNullHandler(localEntry);
066: else if (localEntry.hasDynamicAttributes())
067: handler = new StrictDynamicHandler(context, localEntry);
068: else if (localEntry.isPrimitive())
069: handler = new StrictPrimitiveHandler(localEntry);
070: else
071: handler = new StrictStaticHandler(context, localEntry);
072: logger.debug("handler for entry will be: " + handler);
073: // Add this class' attribute to sets
074: Map strictAttributeTypes = handler.getAttributeTypes();
075: Iterator attributeTypeIterator = strictAttributeTypes
076: .keySet().iterator();
077: while (attributeTypeIterator.hasNext()) {
078: String attributeName = attributeTypeIterator.next()
079: .toString().toLowerCase();
080: handlersByAttribute.put(attributeName, handler);
081: }
082: handlersByEntry.put(localEntry, handler);
083: // Get super
084: localEntry = localEntry.getSuperEntry();
085: }
086: logger.debug("analized class: " + sourceEntry
087: + ", attributes: " + getAttributeNames());
088: }
089:
090: private StrictClassHandler getHandler(ClassEntry entry) {
091: return (StrictClassHandler) handlersByEntry.get(entry);
092: }
093:
094: private StrictClassHandler getHandler(String attributeName) {
095: return (StrictClassHandler) handlersByAttribute
096: .get(attributeName.toLowerCase());
097: }
098:
099: /**
100: * Get the attribute types for a strict class.
101: */
102: public Map getStrictAttributeTypes(ClassEntry entry) {
103: return getHandler(entry).getAttributeTypes();
104: }
105:
106: /**
107: * Get all classes and superclasses of the source class.
108: */
109: public List getStrictClassEntries() {
110: return classEntries;
111: }
112:
113: /**
114: * Get the attributes declared in the class given.
115: */
116: public List getStrictAttributeNames(ClassEntry entry) {
117: return getHandler(entry).getAttributeNames();
118: }
119:
120: /**
121: * Instantiate an object of this info entity. If the object in question
122: * is a dynamic object, it's dynamic name will be set.
123: * @param marshalledValues The values for which this object will be created.
124: */
125: public Object newInstance(Map marshalledValues)
126: throws InstantiationException, IllegalAccessException {
127: // If primitive type, then construct with primitive value
128: if (getSourceEntry().isPrimitive())
129: return ((StrictPrimitiveHandler) getHandler(getSourceEntry()))
130: .newInstance(marshalledValues);
131: // It's a custom object, create it
132: Object result = sourceEntry.getSourceClass().newInstance();
133: // If it's a dynamic object, then set it's dynamic name
134: if (DynamicObject.class.isAssignableFrom(sourceEntry
135: .getSourceClass()))
136: ((DynamicObject) result)
137: .setPersistenceDynamicName(sourceEntry
138: .getDynamicName());
139: return result;
140: }
141:
142: /**
143: * Get the exact class a member attribute is declared in.
144: * @param attributeName The attribute to search for.
145: * @return The class the attribute is declared in, which is either the
146: * source class, or a superclass, or null if no such attribute is found.
147: */
148: public ClassEntry getAttributeClassEntry(String attributeName) {
149: return getHandler(attributeName).getSourceEntry();
150: }
151:
152: /**
153: * The table name for a class will be the fully qualified name, with
154: * the dots replaced with underscores. This algorithm is not guaranteed
155: * to stay this way during future versions.
156: */
157: public String getTableName(ClassEntry entry) {
158: StrictClassHandler handler = getHandler(entry);
159: if (handler == null)
160: return null;
161: return handler.getSourceEntry().getFullName().replace('.', '_')
162: .toLowerCase();
163: }
164:
165: /**
166: * Subtable names will be generated for attributes. This method does
167: * not check whether attribute need a subtable name, just generates
168: * one.
169: * @param attributeName The attribute to get subtable name for.
170: */
171: public String getSubTableName(String attributeName) {
172: return (getTableName(getAttributeClassEntry(attributeName))
173: + "_" + attributeName + "_").toLowerCase();
174: }
175:
176: /**
177: * Get the attribute names in a list of this class.
178: */
179: public List getAttributeNames() {
180: return new Vector(handlersByAttribute.keySet());
181: }
182:
183: /**
184: * Get the type of the attribute given.
185: * @return The type marker as defined in ClassTracker.
186: */
187: public Class getAttributeType(String attributeName) {
188: StrictClassHandler handler = getHandler(attributeName);
189: if (handler == null)
190: return null;
191: return (Class) handler.getAttributeTypes().get(
192: attributeName.toLowerCase());
193: }
194:
195: /**
196: * Return whether the information changed in info class.
197: */
198: public boolean hasChanged() {
199: Iterator handlerIterator = handlersByEntry.values().iterator();
200: while (handlerIterator.hasNext()) {
201: StrictClassHandler handler = (StrictClassHandler) handlerIterator
202: .next();
203: if (handler.hasChanged())
204: return true;
205: }
206: return false;
207: }
208:
209: /**
210: * Get the attribute value from a given object of this class and
211: * from given attribute.
212: */
213: public Object getAttributeValue(Object obj, String attributeName) {
214: return getHandler(attributeName).getAttributeValue(obj,
215: attributeName);
216: }
217:
218: /**
219: * Set an object as value into object given.
220: */
221: public void setAttributeValue(Object obj, String attributeName,
222: Object value) {
223: getHandler(attributeName).setAttributeValue(obj, attributeName,
224: value);
225: }
226:
227: public ClassEntry getSourceEntry() {
228: return sourceEntry;
229: }
230:
231: public int hashCode() {
232: return sourceEntry.getFullName().hashCode();
233: }
234:
235: public boolean equals(Object obj) {
236: if (!(obj instanceof ClassInfo))
237: return false;
238: return ((ClassInfo) obj).sourceEntry.getFullName().equals(
239: sourceEntry.getFullName());
240: }
241:
242: public String toString() {
243: return "[ClassInfo: " + sourceEntry.getFullName() + "]";
244: }
245: }
|