001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S.Chassande-Barrioz.
025: *
026: */package org.objectweb.speedo.metadata;
027:
028: import java.util.Iterator;
029:
030: import org.objectweb.asm.Constants;
031: import org.objectweb.asm.Type;
032: import org.objectweb.speedo.api.SpeedoException;
033: import org.objectweb.speedo.api.SpeedoRuntimeException;
034: import org.objectweb.speedo.generation.enhancer.common.Util;
035:
036: /**
037: * This class corresponds to the description of persistent fields.
038: * @author S.Chassande-Barrioz
039: */
040: public class SpeedoField extends SpeedoCommonField {
041:
042: /*
043: * The following constants specify the propagation mode of diverse
044: * characteristics associated to refernce field persistence.
045: */
046: public final static byte PROPAG_NONE = 0;
047: public final static byte PROPAG_PERSIST = 1;
048: public final static byte PROPAG_MERGE = 2;
049: public final static byte PROPAG_REMOVE = 4;
050: public final static byte PROPAG_REFRESH = 8;
051: public final static byte PROPAG_ALL = PROPAG_PERSIST | PROPAG_MERGE
052: | PROPAG_REMOVE | PROPAG_REFRESH;
053:
054: public final static byte NO_BI_RELATION = 0;
055: public final static byte ONE_ONE_BI_RELATION = 1;
056: public final static byte ONE_MANY_BI_RELATION = 2;
057: public final static byte MANY_ONE_BI_RELATION = 3;
058: public final static byte MANY_MANY_BI_RELATION = 4;
059: public final static byte ONE_REFERENCE = 5;
060: public final static byte MANY_REFERENCE = 6;
061:
062: public final static byte UNKNOWN = 0;
063: public final static byte NONE = 1;
064: public final static byte PERSISTENT = 2;
065: public final static String[] PERSISTENCE_STATUS = { "UNKNOWN",
066: "NONE", "PERSISTENT" };
067:
068: /**
069: * @param s is a string representation of a persistence status
070: * @return the constant value corresponding to the persistence status.
071: */
072: public static byte parsePersistenceStatus(String s) {
073: for (byte i = 0; i < PERSISTENCE_STATUS.length; i++) {
074: if (PERSISTENCE_STATUS[i].equalsIgnoreCase(s)) {
075: return i;
076: }
077: }
078: return UNKNOWN;
079: }
080:
081: public static String parsePersistenceStatus(byte ps) {
082: return PERSISTENCE_STATUS[ps];
083: }
084:
085: /**
086: * visibility of the field (public | protected | private | static ...)
087: * @see Constants#ACC_PUBLIC
088: * @see Constants#ACC_PRIVATE
089: * @see Constants#ACC_PROTECTED
090: * @see Constants#ACC_STATIC
091: * @see Constants#ACC_FINAL
092: * @see Constants#ACC_TRANSIENT
093: */
094: public int visibility;
095:
096: /**
097: * Specify the kind of persistence characteristic should be propagated
098: * through this field (PERSIST | MERGE | REMOVE | REFRESH).
099: * @see #PROPAG_ALL
100: * @see #PROPAG_PERSIST
101: * @see #PROPAG_MERGE
102: * @see #PROPAG_REMOVE
103: * @see #PROPAG_REFRESH
104: * @see #PROPAG_NONE
105: */
106: public byte propagate;
107:
108: /**
109: * Type of the persistent field
110: * @see Type#getDescriptor()
111: */
112: public String type;
113:
114: /**
115: * is the index of the persistent field. This field is computed through a
116: * MI visitor.
117: */
118: public int number;
119:
120: /**
121: * Attribute persistence-modifier in the XML file.
122: */
123: public byte persistenceStatus;
124:
125: /**
126: * Boolean indicating if the field is a primary key.
127: */
128: public boolean primaryKey;
129:
130: /**
131: * Attribute null-value in the XML file.
132: */
133: public byte nullValue;
134:
135: /**
136: * This boolean indicates if the field is in the default fetch group.
137: * (not managed)
138: */
139: public boolean defaultFetchGroup;
140:
141: /**
142: * Recursive fetchgroups are controlled by the depth attribute. A depth of 0 (the default)
143: * will fetch the whole graph of instances reachable from this field.
144: */
145: public int depth;
146:
147: public String fetchGroup;
148:
149: /**
150: * Attribute embedded of the XML file. (not managed)
151: */
152: public boolean embedded;
153:
154: /**
155: * Attribute value-strategy
156: */
157: public String valueStrategy;
158:
159: /**
160: * Attribute sequence
161: */
162: public String sequence;
163:
164: /**
165: * Type of the relation containinig the persistent field
166: * @see #NO_BI_RELATION
167: * @see #ONE_ONE_BI_RELATION
168: * @see #ONE_MANY_BI_RELATION
169: * @see #MANY_ONE_BI_RELATION
170: * @see #MANY_MANY_BI_RELATION
171: */
172: public byte relationType;
173:
174: /**
175: * Is the name of the field which composes with the current field, a
176: * bidirectional relation ship.
177: */
178: public String reverseField;
179:
180: /**
181: * Indicates if the coherence of bidirectional relationship must be assumed
182: * by Speedo.
183: */
184: public boolean isCoherentReverseField = false;
185:
186: /**
187: * Indicates if the field has to be deleted when its referencer is deleted.
188: */
189: public boolean isCascadeDelete = false;
190:
191: /**
192: * In case of bi directional relationship the mapping of this field can be
193: * defined since the mapping of the reverse field. In this case the #columns
194: * field is null and this field is equals to 'true'.
195: * @see #columns
196: * @see #join
197: */
198: public boolean mappedByReversefield;
199:
200: public SpeedoField() {
201: SpeedoDefaults.setDefaults(this );
202: }
203:
204: /**
205: * Transforms a SpeedoField into a String.
206: * @return the String corresponding to the SpeedoField.
207: */
208: public String toString() {
209: StringBuffer sb = new StringBuffer();
210: sb.append("SpeedoField");
211: sb.append("name: ").append(modifier()).append(" ").append(name);
212: if (relationType != NO_BI_RELATION) {
213: if ((relationType == ONE_REFERENCE)
214: || (relationType == MANY_REFERENCE)) {
215: sb.append(", referenceType: ").append(relationType);
216: } else {
217: sb.append(", relationType: ").append(relationType);
218: sb.append(", reverseField: ").append(reverseField);
219: sb.append(", coherent: ")
220: .append(isCoherentReverseField);
221: }
222: }
223: if (persistenceStatus != SpeedoField.PERSISTENT) {
224: sb.append(", persistenceModifier: ").append(
225: persistenceStatus);
226: }
227: if (primaryKey) {
228: sb.append(", primaryKey");
229: }
230: if (nullValue != SpeedoNullValue.NONE) {
231: sb.append(", nullValue: ").append(nullValue);
232: }
233: if (fetchGroup != null) {
234: sb.append(", fetchGroup: ").append(fetchGroup);
235: }
236: if (depth != 0) {
237: sb.append(", depth: ").append(depth);
238: }
239: if (valueStrategy != null) {
240: sb.append(", valueStrategy: ").append(valueStrategy);
241: }
242: sb.append(", sequence: ").append(sequence);
243: if (jdoTuple != null)
244: sb.append(jdoTuple.toString());
245: if (columns != null) {
246: for (int i = 0; i < columns.length; i++) {
247: sb.append(", column[").append(i).append("]=(");
248: sb.append(columns[i]).append(")");
249: }
250: } else if (mappedByReversefield) {
251:
252: }
253: //sb.append(", defaultFetchGroup: ").append(defaultFetchGroup);
254: //sb.append(", embedded: ").append(embedded);
255: return sb.toString();
256: }
257:
258: /**
259: * Returns the field's signature with a public modifier.
260: * @return the String containing the field' signature with a public modifier.
261: */
262: public String publicSignature() {
263: int publicAccess = visibility;
264: publicAccess &= ~(Constants.ACC_PRIVATE | Constants.ACC_PROTECTED);
265: publicAccess |= Constants.ACC_PUBLIC;
266: return Util.modifier(publicAccess) + type() + " " + name;
267: }
268:
269: /**
270: * Returns the field's signature with a private modifier.
271: * @return the String containing the field' signature with a private modifier.
272: */
273: public String privateSignature() {
274: int privateAccess = visibility;
275: privateAccess &= ~(Constants.ACC_PUBLIC | Constants.ACC_PROTECTED);
276: privateAccess |= Constants.ACC_PRIVATE;
277: return Util.modifier(privateAccess) + type() + " " + name;
278: }
279:
280: /**
281: * Returns the field's modifier
282: * @return the String representing the modifier (<code>public</code>,
283: * <code>private</code>, <code>protected</code>)
284: */
285: public String modifier() {
286: return Util.modifier(visibility);
287: }
288:
289: /**
290: * Returns the type of the field.
291: * @return type of the field.
292: */
293: public String type() {
294: return Util.type(Type.getType(type));
295: }
296:
297: public SpeedoField getReverseField() throws SpeedoException {
298: return getFieldOfTheReferencedClass(reverseField);
299: }
300:
301: public SpeedoField getFieldOfTheReferencedClass(String fieldName)
302: throws SpeedoException {
303: String className = null;
304: if (jdoTuple != null) {
305: if (jdoTuple instanceof SpeedoCollection) {
306: className = ((SpeedoCollection) jdoTuple).elementType;
307: } else if (jdoTuple instanceof SpeedoMap) {
308: className = (String) ((SpeedoMap) jdoTuple).valueType;
309: } else if (jdoTuple instanceof SpeedoArray) {
310: className = Util.type(Type.getType(type));
311: }
312: } else {
313: className = Util.type(Type.getType(type));
314: }
315: SpeedoClass sc = moClass.getSpeedoClassFromContext(className);
316: if (sc == null) {
317: throw new SpeedoException("No persistent class '"
318: + className + "' found: " + getSourceDesc());
319: }
320: return (SpeedoField) sc.fields.get(fieldName);
321: }
322:
323: public String getSourceDesc() {
324: StringBuffer sb = new StringBuffer();
325: sb.append("field '").append(name);
326: sb.append("' in class '").append(moClass.getFQName());
327: sb.append("' in desc '");
328: sb.append(moClass.moPackage.xmlDescriptor.xmlFile).append("'");
329: return sb.toString();
330: }
331:
332: public void addColumn(SpeedoColumn col) {
333: columns = (SpeedoColumn[]) addInArray(col, columns,
334: SpeedoColumn[].class);
335: }
336:
337: public String getClassName() {
338: return Type.getType(type).getClassName();
339: }
340:
341: public SpeedoClass getReferencedClass() {
342: if (jdoTuple == null) {
343: return moClass.getSpeedoClassFromContext(getClassName());
344: } else if (jdoTuple instanceof SpeedoCollection) {
345: return moClass
346: .getSpeedoClassFromContext(((SpeedoCollection) jdoTuple).elementType);
347: } else if (jdoTuple instanceof SpeedoMap) {
348: return moClass
349: .getSpeedoClassFromContext(((SpeedoMap) jdoTuple).valueType);
350: } else {
351: return null;
352: }
353: }
354: }
|