001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
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 2 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 org.objectweb.speedo.naming.lib;
018:
019: import org.objectweb.asm.Type;
020: import org.objectweb.jorm.api.PException;
021: import org.objectweb.jorm.facility.naming.basidir.BasidBinder;
022: import org.objectweb.jorm.facility.naming.basidir.BasidName;
023: import org.objectweb.jorm.metainfo.api.Class;
024: import org.objectweb.jorm.metainfo.api.ClassMapping;
025: import org.objectweb.jorm.metainfo.api.ClassRef;
026: import org.objectweb.jorm.metainfo.api.GenClassMapping;
027: import org.objectweb.jorm.metainfo.api.GenClassRef;
028: import org.objectweb.jorm.metainfo.api.CommonClassMapping;
029: import org.objectweb.jorm.metainfo.api.Manager;
030: import org.objectweb.jorm.metainfo.api.MetaObject;
031: import org.objectweb.jorm.metainfo.api.NameDef;
032: import org.objectweb.jorm.metainfo.api.Reference;
033: import org.objectweb.jorm.metainfo.api.TypedElement;
034: import org.objectweb.jorm.naming.api.PBinder;
035: import org.objectweb.jorm.naming.api.PExceptionNaming;
036: import org.objectweb.jorm.naming.api.PName;
037: import org.objectweb.jorm.naming.api.PNameCoder;
038: import org.objectweb.jorm.naming.lib.CTHelper;
039: import org.objectweb.jorm.type.api.PType;
040: import org.objectweb.speedo.api.SpeedoException;
041: import org.objectweb.speedo.api.SpeedoProperties;
042: import org.objectweb.speedo.generation.enhancer.pc.POVariableNames;
043: import org.objectweb.speedo.generation.jorm.JormMIMappingBuilder;
044: import org.objectweb.speedo.generation.lib.NamingRules;
045: import org.objectweb.speedo.mapper.api.JormFactory;
046: import org.objectweb.speedo.metadata.SpeedoClass;
047: import org.objectweb.speedo.metadata.SpeedoExtension;
048: import org.objectweb.speedo.metadata.SpeedoField;
049: import org.objectweb.speedo.metadata.SpeedoIdentity;
050: import org.objectweb.speedo.naming.api.MIBuilderHelper;
051: import org.objectweb.speedo.naming.api.NamingManager;
052: import org.objectweb.util.monolog.api.BasicLevel;
053:
054: import java.util.ArrayList;
055: import java.util.Collection;
056: import java.util.Date;
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Map;
060: import java.util.Properties;
061:
062: /**
063: * Is a manager of identifier naming compised of a single visible field.
064: *
065: * @author S.Chassande-Barrioz
066: */
067: public class UserIdSingleNamingManager extends NamingManagerHelper
068: implements NamingManager {
069:
070: private final static String SINGLE_USER_ID = "suid";
071:
072: private int getCodingType(String fn, MetaObject mo) {
073: TypedElement te = null;
074: if (mo instanceof Class) {
075: te = ((Class) mo).getTypedElement(fn);
076: } else if (mo instanceof GenClassRef) {
077: te = ((GenClassRef) mo).getHiddenField(fn);
078: } else {
079: return -1;
080: }
081: return CTHelper.ptc2ct(te.getType().getTypeCode());
082: }
083:
084: protected String getName() {
085: return SINGLE_USER_ID;
086: }
087:
088: // IMPLEMENTATION OF THE METHOD FROM THE NamingManager INTERFACE //
089: //---------------------------------------------------------------//
090:
091: public Object encode(PName pn) throws PException {
092: if (pn instanceof BasidName) {
093: return pn.getPNameManager().getPType().getJormName() + SEP
094: + pn.encodeString();
095: }
096: return null;
097: }
098:
099: public PName decode(PNameCoder pnc, Object oid,
100: java.lang.Class clazz, JormFactory jf) throws PException {
101: if (oid instanceof String) {
102: String stroid = (String) oid;
103: int idx = stroid.indexOf(SEP);
104: if (pnc != null) {
105: if (pnc.codingSupported(PNameCoder.CTCOMPOSITE)) {
106: //The pnc is not a BasidBinder, then the oid cannot be managed
107: return null;
108: }
109: if (idx != -1) {
110: //The oid contains the class name
111: return pnc.decodeString(stroid.substring(idx
112: + SEP.length()));
113: } else {
114: //The oid must decoded directly
115: return pnc.decodeString(stroid);
116: }
117: }
118: //No pnc specified
119: if (idx == -1) {
120: //The oid cannot be managed
121: return null;
122: }
123: //The oid contains the class name
124: String fqcn = stroid.substring(0, idx);
125: ClassLoader cl = jf.getClass().getClassLoader();
126: if (cl == null) {
127: cl = ClassLoader.getSystemClassLoader();
128: }
129: try {
130: pnc = jf.getPNamingContext(fqcn, cl);
131: } catch (Exception e) {
132: return null;
133: }
134: if (pnc == null
135: || pnc.codingSupported(PNameCoder.CTCOMPOSITE)) {
136: return null;
137: }
138: return pnc.decodeString(stroid
139: .substring(idx + SEP.length()));
140: } else if (pnc instanceof BasidBinder) {
141: switch (((BasidBinder) pnc).getCodingType()) {
142: case PNameCoder.CTCHAR:
143: return pnc.decodeChar(((Character) oid).charValue());
144: case PNameCoder.CTBYTE:
145: return pnc.decodeByte(((Byte) oid).byteValue());
146: case PNameCoder.CTSHORT:
147: return pnc.decodeShort(((Short) oid).shortValue());
148: case PNameCoder.CTINT:
149: return pnc.decodeInt(((Integer) oid).intValue());
150: case PNameCoder.CTLONG:
151: return pnc.decodeLong(((Long) oid).longValue());
152: case PNameCoder.CTOCHAR:
153: return pnc.decodeOchar((Character) oid);
154: case PNameCoder.CTOBYTE:
155: return pnc.decodeObyte((Byte) oid);
156: case PNameCoder.CTOSHORT:
157: return pnc.decodeOshort((Short) oid);
158: case PNameCoder.CTOINT:
159: return pnc.decodeOint((Integer) oid);
160: case PNameCoder.CTOLONG:
161: return pnc.decodeOlong((Long) oid);
162: case PNameCoder.CTSTRING:
163: return pnc.decodeString((String) oid);
164: case PNameCoder.CTDATE:
165: return pnc.decodeDate((Date) oid);
166: case PNameCoder.CTCHARARRAY:
167: return pnc.decodeCharArray((char[]) oid);
168: case PNameCoder.CTBYTEARRAY:
169: return pnc.decode((byte[]) oid);
170: default:
171: throw new PExceptionNaming("Unmanaged coding type: "
172: + ((BasidBinder) pnc).getCodingType());
173: }
174: } else {
175: //oid
176: return null;
177: }
178: }
179:
180: public boolean canManage(SpeedoClass sc) {
181: if (sc.identity.strategy == SpeedoIdentity.USER_ID) {
182: String objectidClass = sc.identity.objectidClass;
183: if (sc.generateObjectId()) {
184: objectidClass = NamingRules.generatedObjectIdName(sc
185: .getFQName());
186: }
187: return objectidClass == null || objectidClass.length() == 0;
188: }
189: return false;
190: }
191:
192: public boolean canProvidePBinder(Object hints,
193: ClassLoader classLoader) {
194: if (!super .canProvidePBinder(hints, classLoader)) {
195: return false;
196: }
197: String ctStr = getBinderClassNameFromHints(hints,
198: SINGLE_USER_ID);
199: if (ctStr == null) {
200: return false;
201: }
202: try {
203: Short.parseShort(ctStr);
204: return true;
205: } catch (NumberFormatException e) {
206: return false;
207: }
208: }
209:
210: public boolean canProvidePNamingContext(Object hints,
211: ClassLoader classLoader) {
212: return getPNCClassNameFromHints(hints, SINGLE_USER_ID) != null;
213: }
214:
215: public PBinder getPBinder(String className, String hints,
216: ClassLoader cl, byte mappingStructureRule, Map cn2binder,
217: Map cn2pnc) {
218: String ctStr = getBinderClassNameFromHints(hints,
219: SINGLE_USER_ID);
220: return new BasidBinder(Short.parseShort(ctStr));
221: }
222:
223: /**
224: * sud,coding type, pnc class name, class name
225: */
226: public void getJormNamingConfig(NameDef nd,
227: SpeedoClass targetClass, MetaObject sourceMO, String key,
228: Properties result) throws SpeedoException {
229: StringBuffer sb = new StringBuffer();
230: sb.append(SINGLE_USER_ID);
231: sb.append(HINTS_SEP);
232: int ct = getCodingType(nd.getFieldName(), sourceMO);
233: sb.append(ct);
234: sb.append(HINTS_SEP);
235: String className = targetClass.getFQName();
236: SpeedoClass ancestor = targetClass.getAncestor();
237: if (sourceMO instanceof GenClassRef //For a Genclass ref or identifier
238: || (ancestor == null //No inheritance
239: && targetClass.jormclass.getSubClasses().isEmpty())) {
240: sb.append(ct);
241: } else {
242: if (ancestor == null) {
243: ancestor = targetClass;
244: }
245: try {
246: if (targetClass.jormclass.getSubClasses().isEmpty()) {
247: sb.append(ct);
248: } else if (targetClass.jormclass
249: .detectFilterElementNotInPK(
250: targetClass.jormclass
251: .getInheritanceFilter(nd), nd)) {
252: //if has child(ren)
253: //and one of the fields of the filter is not in the primary key,
254: //use a PolymorphicPNC
255: sb.append(POLYMORPHIC_PNC);
256: } else {
257: //use a kfpnc
258: sb.append(NamingRules.kfpncName(ancestor
259: .getFQName()));
260: }
261: } catch (Exception e) {
262: logger.log(BasicLevel.ERROR,
263: "Error while retrieving the inheritance filter of the namedef:"
264: + nd.toString());
265: throw new SpeedoException(
266: "Error while retrieving the inheritance filter of the namedef:"
267: + nd.toString(), e);
268: }
269: className = ancestor.getFQName();
270: }
271: sb.append(HINTS_SEP);
272: sb.append(className);
273: result.setProperty(key, sb.toString());
274: }
275:
276: public Object[] getPNameHints2(SpeedoClass sc, NameDef nd) {
277: String fn = nd.getFieldName();
278: return new Object[] { PNH_PFIELD, fn,
279: sc.jormclass.getTypedElement(fn).getType() };
280: }
281:
282: public String getPNameHints(SpeedoClass sc, NameDef nd) {
283: String fn = nd.getFieldName();
284: //provide the field value as Object format
285: int tc = sc.jormclass.getTypedElement(fn).getType()
286: .getTypeCode();
287: fn = POVariableNames.REFSTATE_FIELD_NAME + "." + fn;
288: switch (tc) {
289: case PType.TYPECODE_CHAR:
290: return "new Character(" + fn + ")";
291: case PType.TYPECODE_BYTE:
292: return "new Byte(" + fn + ")";
293: case PType.TYPECODE_SHORT:
294: return "new Short(" + fn + ")";
295: case PType.TYPECODE_INT:
296: return "new Integer(" + fn + ")";
297: case PType.TYPECODE_LONG:
298: return "new Long(" + fn + ")";
299: default:
300: return fn;
301: }
302: }
303:
304: public String getGCPNameHints(SpeedoClass sc, NameDef nd) {
305: return "speedoPO.getPName()";
306: }
307:
308: public void defineClassIdentifierNameDef(NameDef nd, Class jc,
309: SpeedoClass sc, ClassMapping cm, MIBuilderHelper mibh,
310: JormMIMappingBuilder mb, Collection createdMOs)
311: throws SpeedoException, PException {
312: SpeedoClass clazz = sc.getAncestor();
313: if (clazz == null) {
314: clazz = sc;
315: }
316: SpeedoField pkField = clazz.getUniquePKField();
317: nd.setFieldName(pkField.name);
318: }
319:
320: public boolean needInheritanceDiscriminator(SpeedoClass sc)
321: throws SpeedoException {
322: return true;
323: }
324:
325: /**
326: * This internal method defines a NameDef based on on the PK fields of the
327: * Referenced class. This method manages ClassRef owned by a class or by
328: * a generic class. But this method does not mapped the fields (ex:
329: * no rdb mapping)
330: * @param nd is the namedef to fill
331: * @param cr is the JORM meta object representing the reference. This
332: * ClassRef can be owned by a Class or a GenClassRef.
333: * @param sf is the Speedo MetaObject representing the persistent field
334: * linked to this ClassRef. If the owner of the ClassRef is a simple class
335: * then this parameter represents the classRef too. If the owner of the
336: * ClassRef is a generic class, then this parameter represents the reference
337: * to the generic class (Collection, Map, ...).
338: * @param mibh is a helper for the management of the JORM meta info
339: * @param prefix is a prefix for the name of the field composing the
340: * identifier
341: */
342: private void defineClassReferenceNamedDef(NameDef nd,
343: SpeedoField sf, ClassRef cr, MIBuilderHelper mibh,
344: String prefix) throws SpeedoException, PException {
345: SpeedoClass referencedClass = sf.moClass
346: .getSpeedoClassFromContext(cr.getMOClass().getFQName());
347: SpeedoField pkField = (SpeedoField) referencedClass
348: .getUniquePKField();
349:
350: String fn = prefix + pkField.name;
351: int size = PType.NOSIZE;
352: int scale = PType.NOSIZE;
353: if (pkField.columns != null && pkField.columns.length == 1) {
354: if (pkField.columns[0].length != -1) {
355: size = pkField.columns[0].length;
356: }
357: if (pkField.columns[0].scale != -1) {
358: scale = pkField.columns[0].scale;
359: }
360: }
361: PType type = mibh.getPrimitivePType(Type.getType(pkField.type));
362: mibh.createNameDefField(cr.getParent(), fn, type, size, scale);
363: nd.setFieldName(fn);
364: }
365:
366: public void defineClassReferenceNameDef(NameDef nd, ClassRef cr,
367: SpeedoField sf, SpeedoClass currentClass, ClassMapping cm,
368: MIBuilderHelper mibh, JormMIMappingBuilder mb)
369: throws SpeedoException, PException {
370: String prefix = mibh
371: .getNameDefFieldPrefix(cr, false, false, sf);
372: defineClassReferenceNamedDef(nd, sf, cr, mibh, prefix);
373: mb.createClassRefNameDefMapping(cm, nd, sf);
374: }
375:
376: public void defineClassReferenceNameDef(NameDef nd, ClassRef cr,
377: SpeedoField sf, SpeedoClass currentClass,
378: GenClassMapping gcm, MIBuilderHelper mibh,
379: JormMIMappingBuilder mb) throws SpeedoException, PException {
380: String prefix = mibh
381: .getNameDefFieldPrefix(cr, false, false, sf);
382: defineClassReferenceNamedDef(nd, sf, cr, mibh, prefix);
383: mb.createClassRefNameDefMapping(gcm, nd, sf);
384: }
385:
386: private void defineGenClassNameDef(NameDef nd, GenClassRef gcr,
387: SpeedoField sf, MIBuilderHelper mibh, boolean isGCId)
388: throws SpeedoException, PException {
389: SpeedoField pkField = sf.moClass.getUniquePKField();
390: String prefix = mibh.getNameDefFieldPrefix(gcr, isGCId, isGCId,
391: sf);
392: String fn = prefix + pkField.name;
393: if (isGCId) {
394: int size = PType.NOSIZE;
395: int scale = PType.NOSIZE;
396: if (pkField.columns != null && pkField.columns.length == 1) {
397: if (pkField.columns[0].length != -1) {
398: size = pkField.columns[0].length;
399: }
400: if (pkField.columns[0].scale != -1) {
401: scale = pkField.columns[0].scale;
402: }
403: }
404: PType type = mibh.getPrimitivePType(Type
405: .getType(pkField.type));
406: mibh.createNameDefField(gcr, fn, type, size, scale);
407: }
408: nd.setFieldName(fn);
409: }
410:
411: public void defineGenClassIdentifierNameDef(NameDef nd,
412: GenClassRef gcr, SpeedoField sf, SpeedoClass currentClass,
413: GenClassMapping gcm, MIBuilderHelper mibh,
414: JormMIMappingBuilder mb) throws SpeedoException, PException {
415: defineGenClassNameDef(nd, gcr, sf, mibh, true);
416: mb.createGenClassIdentifierNameDefMapping(gcm, nd, sf, mibh);
417: }
418:
419: public void defineGenClassReferenceNameDef(NameDef nd,
420: GenClassRef gcr, SpeedoField sf, SpeedoClass currentClass,
421: ClassMapping cm, MIBuilderHelper mibh,
422: JormMIMappingBuilder mb) throws SpeedoException, PException {
423: defineGenClassNameDef(nd, gcr, sf, mibh, false);
424: }
425: }
|