001: /*
002: * Copyright 2006 Davide Deidda
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: /*
018: * Metadata.java
019: *
020: * Created on 5 dicembre 2004, 9.38
021: */
022:
023: package it.biobytes.ammentos;
024:
025: import java.util.*;
026: import it.biobytes.ammentos.validation.*;
027: import java.lang.reflect.Method;
028:
029: /**
030: * Contains metadata information about an Entity
031: *
032: * @author Davide Deidda
033: */
034: public class Metadata {
035:
036: private Map<String, Field> m_fields; // Fields map
037: private List<String> m_fieldNames; // Field names list
038: private boolean m_editingSupported; // Edit support flag
039: private boolean m_deletingSupported; // Delete support flag
040: private boolean m_creatingSupported; // Create support flag
041: private Validator m_validator; // Related validator
042: private String m_sourceDomain; // Source domain
043: private String m_targetDomain; // Target domain
044: private String m_collectiveName;
045: private Field m_primaryKey;
046: private Field m_super Key; // Field containing super pKey
047: private Persistor m_persistor; // Persistor
048: private Class m_class; // Class represented from this metadata
049: private Class[] m_inheritancePath; // Inheritance path to Object
050: private List<CollectionField> m_collectionFields; // List fields
051: private boolean m_useDbSequences;
052: private Field[] m_compositeKey; // Composite key fields
053:
054: private List<Method> m_beforeSaveHandlers;
055: private List<Method> m_afterSaveHandlers;
056: private List<Method> m_beforeDeleteHandlers;
057: private List<Method> m_afterDeleteHandlers;
058: private List<Method> m_afterLoadHandlers;
059:
060: public Metadata(Class c) {
061: m_editingSupported = true;
062: m_deletingSupported = true;
063: m_fields = new HashMap<String, Field>();
064: m_fieldNames = new ArrayList<String>();
065: m_collectionFields = new ArrayList<CollectionField>();
066: m_class = c;
067: }
068:
069: public void addField(Field field) {
070: field.position = m_fields.size();
071: m_fields.put(field.getName().toUpperCase(), field);
072: m_fieldNames.add(field.getName());
073: if (field.isAutomatic()
074: && field.getAutomaticType() == AutomaticType.EXTERNAL) {
075: m_useDbSequences = true;
076: }
077: }
078:
079: public void addCollectionField(CollectionField listField) {
080: m_collectionFields.add(listField);
081: }
082:
083: /**
084: * Returns the list of insertable fields in the object, which are
085: * not external nor dynamic fields.
086: */
087: public Field[] getInsertableFields() {
088: List res = new ArrayList();
089: Iterator it = m_fields.values().iterator();
090: while (it.hasNext()) {
091: Field field = (Field) it.next();
092:
093: if ((!field.isExternal())
094: && (!field.isDynamic())
095: && (field.getAutomaticType() != AutomaticType.EXTERNAL)) {
096: res.add(field);
097: }
098: }
099: return (Field[]) res.toArray(new Field[0]);
100: }
101:
102: /**
103: * Returns the list of updatable fields in the object, which are
104: * not external nor dynamic nor automatic fields.
105: */
106: public Field[] getUpdatableFields() {
107: List res = new ArrayList();
108: Iterator it = m_fields.values().iterator();
109: while (it.hasNext()) {
110: Field field = (Field) it.next();
111: if ((!field.isExternal()) && (!field.isDynamic())
112: && (!field.isAutomatic())) {
113: res.add(field);
114: }
115: }
116: return (Field[]) res.toArray(new Field[0]);
117: }
118:
119: /**
120: * Returns the list of loadable fields, which are not dynamic fields.
121: * @return
122: */
123: public Field[] getLoadableFields() {
124: List res = new ArrayList();
125: Iterator it = m_fields.values().iterator();
126: while (it.hasNext()) {
127: Field field = (Field) it.next();
128: if (!field.isDynamic()) {
129: res.add(field);
130: }
131: }
132: return (Field[]) res.toArray(new Field[0]);
133: }
134:
135: /**
136: * Sets the visibility for the field "fieldName"
137: */
138: public void setFieldVisible(String fieldName, boolean visible) {
139: Field field = getField(fieldName);
140: if (field != null) {
141: field.setVisible(visible);
142: }
143: }
144:
145: public Field[] getFields() {
146: Field[] res = null;
147: res = (Field[]) m_fields.values().toArray(new Field[0]);
148: Arrays.sort(res);
149: return res;
150: }
151:
152: public List<CollectionField> getCollectionFields() {
153: return m_collectionFields;
154: }
155:
156: public Field[] getVisibleFields() {
157: List res = new ArrayList();
158:
159: for (String fieldName : m_fieldNames) {
160: Field field = (Field) getField(fieldName);
161: if (field.isVisible()) {
162: res.add(field);
163: }
164: }
165: return (Field[]) res.toArray(new Field[0]);
166: }
167:
168: public String[] getFieldNames() {
169: return (String[]) m_fieldNames.toArray(new String[0]);
170: }
171:
172: public Field getField(String fieldName) {
173: Field res = null;
174: if (fieldName != null) {
175: res = (Field) m_fields.get(fieldName.toUpperCase());
176: }
177: return res;
178: }
179:
180: public void setEditingSupported(boolean supported) {
181: m_editingSupported = supported;
182: }
183:
184: public void setDeletingSupported(boolean supported) {
185: m_deletingSupported = supported;
186: }
187:
188: public void setCreatingSupported(boolean supported) {
189: m_creatingSupported = supported;
190: }
191:
192: public boolean isEditingSupported() {
193: return m_editingSupported;
194: }
195:
196: public boolean isDeletingSupported() {
197: return m_deletingSupported;
198: }
199:
200: public boolean isCreatingSupported() {
201: return m_creatingSupported;
202: }
203:
204: protected Iterator fieldsIterator() {
205: return m_fields.values().iterator();
206: }
207:
208: protected Iterator<String> fieldNamesIterator() {
209: return m_fieldNames.iterator();
210: }
211:
212: /**
213: * Adds a validator
214: */
215: public void setValidator(Validator validator) {
216: m_validator = validator;
217: }
218:
219: public Validator getValidator() {
220: return m_validator;
221: }
222:
223: /**
224: * Returns the source table.The source table is the table where the items of
225: * this class are loaded. It can be different from the <i>target table</i>,
226: * which is instead the table where the items are saved. This difference is
227: * allowed to support composed items which are for example the result of
228: * a join of more tables. In this case the application must know where exactly
229: * to save items.
230: */
231: public String getSourceDomain() {
232: return m_sourceDomain;
233: }
234:
235: /**
236: * Sets the source table. The source table is the table where the items of
237: * this class are loaded. It can be different from the <i>target table</i>,
238: * which is instead the table where the items are saved. This difference is
239: * allowed to support composed items which are for example the result of
240: * a join of different tables. In this case the application must know where exactly
241: * save items.
242: */
243: public void setSourceDomain(String sourceDomain) {
244: m_sourceDomain = sourceDomain;
245: }
246:
247: /**
248: * Sets the target table. The target table is the table where the items are
249: * saved. Normally the target table and the source table are the same. They
250: * can be made different to support special cases (for example when an item
251: * is loaded from a join of several tables or from a view).
252: * WARNING: If the source table and the target table are different you must
253: * pay attention that all the updatable item fields are contained into the
254: * target table.
255: */
256: public void setTargetDomain(String targetDomain) {
257: m_targetDomain = targetDomain;
258: }
259:
260: /**
261: * Returns the target table.
262: */
263: public String getTargetDomain() {
264: String res = m_targetDomain;
265: if (res == null) {
266: res = m_sourceDomain;
267: }
268: return res;
269: }
270:
271: /**
272: * Sets the field "fieldName" as the primary key field. A primary key field
273: * is mandatory for update operations
274: *
275: * @param fieldName The name of the field to use as primary key
276: * @param isExternallyGenerated Indicates if the generation of the
277: * primary key value is externally managed
278: * ( f.e. from a database sequence )
279: */
280: public void setPrimaryKey(String fieldName,
281: boolean isExternallyGenerated) {
282: m_primaryKey = getField(fieldName);
283: m_primaryKey.setExternal(isExternallyGenerated);
284: }
285:
286: public void setPrimaryKeys(String... fieldNames) {
287: m_compositeKey = new Field[fieldNames.length];
288: for (int i = 0; i < fieldNames.length; i++) {
289: m_compositeKey[i] = getField(fieldNames[i]);
290: }
291: }
292:
293: /**
294: * Sets the field which contains the primary key of the superclass. By default
295: * this field is the same as the primary key, what means that the annotated
296: * class has the same primary key as the parent class
297: */
298: public void setSuperKey(String fieldName) {
299: m_super Key = getField(fieldName);
300: }
301:
302: /**
303: * Gets the primary key field for this persistent object, if it has one.
304: */
305: public Field getPrimaryKeyField() {
306: return m_primaryKey;
307: }
308:
309: /**
310: * Returns all the fields of the composite key.
311: */
312: public Field[] getPrimaryKeyFields() {
313: if (m_compositeKey == null) {
314: m_compositeKey = new Field[1];
315: m_compositeKey[0] = m_primaryKey;
316: }
317: return m_compositeKey;
318: }
319:
320: /**
321: * Returns the field containing the primary key of the super class. If not
322: * differently specified this field will be the same as the primary key field,
323: * what means that this class will have the same primary key as its superclass.
324: */
325: public Field getSuperKeyField() {
326: if (m_super Key == null) {
327: m_super Key = m_primaryKey;
328: }
329: return m_super Key;
330: }
331:
332: /**
333: * @param string
334: */
335: public void setCollectiveName(String string) {
336: m_collectiveName = string;
337: }
338:
339: /**
340: * @return
341: */
342: public String getCollectiveName() {
343: return m_collectiveName;
344: }
345:
346: public void setPersistenceMode(PersistenceMode mode) {
347: m_persistor = mode.getPersistor();
348: }
349:
350: public Persistor getPersistor() {
351: return m_persistor;
352: }
353:
354: /**
355: * Returns the inheritance path for the objects of the persistence class.
356: * The path starts from the class which owns this Metadata to Object,
357: * including only persistent casses (classes whith related metadata)
358: */
359: public Class[] inheritancePath() {
360: if (m_inheritancePath == null) {
361: List<Class> path = new ArrayList<Class>();
362: Class c = m_class;
363: while ((c != Object.class) && c != null) {
364: try {
365: Ammentos.getMetadata(c);
366: path.add(c);
367: } catch (Exception e) {
368: // Classes which are not persistent are not added to the path
369: }
370: c = c.getSuperclass();
371: }
372: m_inheritancePath = (Class[]) path.toArray(new Class[0]);
373: }
374: return m_inheritancePath;
375: }
376:
377: public boolean usesDbSequences() {
378: return m_useDbSequences;
379: }
380:
381: public List<Method> getBeforeSaveHandlers() {
382: return m_beforeSaveHandlers;
383: }
384:
385: public void addBeforeSaveHandler(Method handler) {
386: if (m_beforeSaveHandlers == null) {
387: m_beforeSaveHandlers = new ArrayList<Method>();
388: }
389: m_beforeSaveHandlers.add(handler);
390: }
391:
392: public List<Method> getAfterSaveHandlers() {
393: return m_afterSaveHandlers;
394: }
395:
396: public void addAfterSaveHandler(Method handler) {
397: if (m_afterSaveHandlers == null) {
398: m_afterSaveHandlers = new ArrayList<Method>();
399: }
400: m_afterSaveHandlers.add(handler);
401: }
402:
403: public List<Method> getBeforeDeleteHandlers() {
404: return m_beforeDeleteHandlers;
405: }
406:
407: public void addBeforeDeleteHandler(Method handler) {
408: if (m_beforeDeleteHandlers == null) {
409: m_beforeDeleteHandlers = new ArrayList<Method>();
410: }
411: m_beforeDeleteHandlers.add(handler);
412: }
413:
414: public List<Method> getAfterDeleteHandlers() {
415: return m_afterDeleteHandlers;
416: }
417:
418: public void addAfterDeleteHandler(Method handler) {
419: if (m_afterDeleteHandlers == null) {
420: m_afterDeleteHandlers = new ArrayList<Method>();
421: }
422: m_afterDeleteHandlers.add(handler);
423: }
424:
425: public List<Method> getAfterLoadHandlers() {
426: return m_afterLoadHandlers;
427: }
428:
429: public void addAfterLoadHandler(Method handler) {
430: if (m_afterLoadHandlers == null) {
431: m_afterLoadHandlers = new ArrayList<Method>();
432: }
433: m_afterLoadHandlers.add(handler);
434: }
435: }
|