001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.persistence.engines.jdbcengine.configservice;
051:
052: import org.apache.log4j.Logger;
053: import java.util.*;
054: import java.lang.reflect.*;
055: import org.jaffa.persistence.engines.jdbcengine.util.Introspection;
056: import org.jaffa.persistence.engines.jdbcengine.configservice.exceptions.ClassMetaDataValidationRuntimeException;
057: import java.net.URL;
058: import org.jaffa.metadata.FieldMetaData;
059:
060: /** This class holds all the meta deta pertaining to a particular persistent object */
061: public class ClassMetaData {
062: private static final Logger log = Logger
063: .getLogger(ClassMetaData.class);
064:
065: private URL m_xmlFileUrl;
066: private String m_className;
067: private String m_table;
068:
069: private Map m_keys;
070: private Map m_nonAutoKeys;
071: private Map m_attributes;
072: private Map m_sqlNames;
073: private Map m_sqlTypes;
074: private Map m_members;
075:
076: private Map m_accessors;
077: private Map m_mutators;
078:
079: /** Constructs a new ClassMetaData object with an empty class name. */
080: public ClassMetaData() {
081: this ("");
082: }
083:
084: /**
085: * Constructs a new ClassMetaData object with the specified class name.
086: * @param classname The fully-qualified classname of the class this meta object is to represent.
087: */
088: public ClassMetaData(String classname) {
089: m_className = classname;
090: m_keys = new HashMap();
091: m_nonAutoKeys = new HashMap();
092: m_attributes = new HashMap();
093: m_accessors = new HashMap();
094: m_mutators = new HashMap();
095: m_sqlNames = new HashMap();
096: m_sqlTypes = new HashMap();
097: m_members = new HashMap();
098: }
099:
100: /**
101: * Set the xmlFileUrl property of this meta data object.
102: * @param xmlFileUrl The File object used to describe this persistent object.
103: */
104: public void setXmlFileUrl(URL xmlFileUrl) {
105: m_xmlFileUrl = xmlFileUrl;
106: }
107:
108: /**
109: * Set the classname property of this meta data object.
110: * @param classname The fully qualified class name of the class this meta
111: * object represents.
112: */
113: public void setClassName(String classname) {
114: m_className = classname;
115: }
116:
117: /**
118: * Set the table property of this meta data object
119: *
120: * @param table The database table name used to store this object
121: */
122: public void setTable(String table) {
123: m_table = table;
124: }
125:
126: /**
127: * Add a primary key field attribute to this meta data object.
128: * @param attName The name of the primary key attribute to be added.
129: * @param type The Java type of the primary key attribute.
130: * @param autogen Indicates if the key will be auto-generated.
131: */
132: public void addKeyField(String attName, String type, boolean autogen) {
133: m_keys.put(attName, type);
134: if (!autogen)
135: m_nonAutoKeys.put(attName, type);
136: }
137:
138: /**
139: * Add an attribute to this meta data object.
140: * @param attName The attribute to be added.
141: * @param type The Java type of the attribute to be added.
142: */
143: public void addAttribute(String attName, String type) {
144: m_attributes.put(attName, type);
145: }
146:
147: /**
148: * Add a new sql name for an attribute to this meta object.
149: * @param attName The name of the attribute for which the sql name is to be added.
150: * @param sqlName The sql name of the attribute.
151: */
152: public void addSqlName(String attName, String sqlName) {
153: m_sqlNames.put(attName, sqlName);
154: }
155:
156: /**
157: * Add sql type data for a particular attribute in this meta data object.
158: * @param attName The name of the attribute for which sql type is to be added.
159: * @param type The sql type for the attribute.
160: */
161: public void addSqlType(String attName, String type) {
162: m_sqlTypes.put(attName, type);
163: }
164:
165: /**
166: * Add a member for an attribute to this meta object.
167: * @param attName The name of the attribute for which the member is to be added.
168: * @param memberName The name of the member variable.
169: */
170: public void addMember(String attName, String memberName) {
171: m_members.put(attName, memberName);
172: }
173:
174: /**
175: * Uses the Introspection service to ensure that the correct accessors and
176: * mutators exist for each attribtue specified in the mapping file. The runtime exception
177: * ClassMetaDataValidationRuntimeException is thrown in case any error occurs in the introspection,
178: * or if all accessors/mutators could not be located for all the attributes.
179: */
180: public void validate() {
181: try {
182: Class clazz = Class.forName(m_className);
183: m_accessors = Introspection.getAccessors(clazz,
184: m_attributes, m_members);
185: m_mutators = Introspection.getMutators(clazz, m_attributes,
186: m_members);
187: m_accessors.putAll(Introspection.getAccessors(clazz,
188: m_keys, m_members));
189: m_mutators.putAll(Introspection.getMutators(clazz, m_keys,
190: m_members));
191: if (m_accessors.size() < (m_attributes.size() + m_keys
192: .size())) {
193: String str = "All accessors could not be found for the attributes. Class='"
194: + m_className
195: + "', Mapping file='"
196: + (m_xmlFileUrl != null ? m_xmlFileUrl
197: .getFile() : null) + '\'';
198: log.error(str);
199: throw new ClassMetaDataValidationRuntimeException(str);
200: } else if (m_mutators.size() < (m_attributes.size() + m_keys
201: .size())) {
202: String str = "All mutators could not be found for the attributes. Class='"
203: + m_className
204: + "', Mapping file='"
205: + (m_xmlFileUrl != null ? m_xmlFileUrl
206: .getFile() : null) + '\'';
207: log.error(str);
208: throw new ClassMetaDataValidationRuntimeException(str);
209: }
210: } catch (ClassNotFoundException e) {
211: String str = "Class not found '"
212: + m_className
213: + "' for the mapping file '"
214: + (m_xmlFileUrl != null ? m_xmlFileUrl.getFile()
215: : null) + '\'';
216: log.error(str, e);
217: throw new ClassMetaDataValidationRuntimeException(str, e);
218: }
219: }
220:
221: /**
222: * Returns the URL object that was parsed to obtain the meta data for this
223: * object.
224: * @return The URL of the xml File that describes this object.
225: */
226: public URL getXmlFileUrl() {
227: return m_xmlFileUrl;
228: }
229:
230: /**
231: * Returns the fully-qualified class name of the class that this meta object
232: * represents.
233: * @return Fully qualified class name of the class that this meta object
234: * represents.
235: */
236: public String getClassName() {
237: return m_className;
238: }
239:
240: /**
241: * Return the database table name that the object represented by this meta
242: * object is to be stored in.
243: * @return Database table name that this object is stored in.
244: */
245: public String getTable() {
246: return m_table;
247: }
248:
249: /**
250: * Returns a Map where key is the name of a primary key attribute for
251: * the class and value is its corresponding Java type.
252: * <p>
253: * <b>Since 1.3</b> - This include both manual and auto genrated key fields, use
254: * getNonAutoKeyFieldNames() to get just the manual key fields.
255: *
256: * @return Map of the key attributes and their types.
257: */
258: public Map getAllKeyFieldNames() {
259: return m_keys;
260: }
261:
262: /**
263: * Returns a Map where key is the name of a primary key attribute for
264: * the class and value is its corresponding Java type. Only the keys that are
265: * not auto generated by the database are returned, these are the keys that are valid
266: * when inserting a row, as auto gnerated keys should not be provided.
267: * @since 1.3
268: * @return Map of the key attributes and their types.
269: */
270: public Map getNonAutoKeyFieldNames() {
271: return m_nonAutoKeys;
272: }
273:
274: /**
275: * Returns a Map of the non-primary-key attributes of the class where key
276: * is the name of the attribtue and value is its Java type.
277: * @return Map representing the non-primary-key attributes of the class.
278: */
279: public Map getAttributes() {
280: return m_attributes;
281: }
282:
283: /**
284: * Returns the Java type of the specified attribute.
285: * @param attName The name of the attribute to be checked.
286: * @return The Java type of the specified attribute.
287: */
288: public String getType(String attName) {
289: return (String) m_attributes.get(attName);
290: }
291:
292: /**
293: * Returns the name of the sql column in which the specified attribute
294: * is stored, as defined in the mapping file.
295: * @param attributeName Name of the attribute for which the sql name is required.
296: * @return The column name for the specified attribute.
297: */
298: public String getSqlName(String attributeName) {
299: return (String) m_sqlNames.get(attributeName);
300: }
301:
302: /**
303: * Returns the database sql type for the specified attribute, as defined in
304: * the mapping file.
305: * @param attributeName Name of the attribute for which sql type is required.
306: * @return The sql type for the specified attribtue.
307: */
308: public String getSqlType(String attributeName) {
309: return (String) m_sqlTypes.get(attributeName);
310: }
311:
312: /**
313: * Return a Map of the accessor Field/Method objects for the defined class where key is the
314: * name of the attribute and value is the accessor Field/Method object.
315: * @return A Map of the accessor Field/Method objects for the defined class.
316: */
317: public Map getAccessors() {
318: return m_accessors;
319: }
320:
321: /**
322: * Returns the accessor Field/Method for the specified attribute.
323: * @param attributeName Name of the attribute for which accessor is required.
324: * @return The accessor Field/Method for the attribute.
325: */
326: public AccessibleObject getAccessor(String attributeName) {
327: return (AccessibleObject) m_accessors.get(attributeName);
328: }
329:
330: /**
331: * Return a Map of the mutator Field/Method objects for the defined class where key is the
332: * name of the attribute and value is the mutator Field/Method object.
333: * @return A Map of the mutator Field/Method objects for the defined class.
334: */
335: public Map getMutators() {
336: return m_mutators;
337: }
338:
339: /**
340: * Returns the mutator Field/Method for the specified attribute.
341: * @param attributeName Name of the attribute for which mutator is required.
342: * @return The mutator Field/Method for the attribute.
343: */
344: public AccessibleObject getMutator(String attributeName) {
345: return (AccessibleObject) m_mutators.get(attributeName);
346: }
347: }
|