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.generation.mivisitor;
018:
019: import org.objectweb.speedo.api.SpeedoException;
020: import org.objectweb.speedo.api.SpeedoProperties;
021: import org.objectweb.speedo.lib.Personality;
022: import org.objectweb.speedo.metadata.SpeedoClass;
023: import org.objectweb.speedo.metadata.SpeedoExtension;
024: import org.objectweb.speedo.metadata.SpeedoField;
025: import org.objectweb.speedo.metadata.SpeedoIdentity;
026: import org.objectweb.speedo.metadata.SpeedoPackage;
027: import org.objectweb.speedo.sequence.jdo.JDOSequence;
028: import org.objectweb.speedo.sequence.lib.SpeedoSequence;
029: import org.objectweb.util.monolog.api.BasicLevel;
030:
031: /**
032: * This SMI visitor manages the datastore identifier strategy. In particular, it
033: * converts old extensions (ID, SEQ*) in the right datastore strategy.
034: * A SpeedoSequence is also created each time the old extension about sequence
035: * are used. Finally the sequence are registered as meta object to serialized.
036: *
037: * @author S.Chassande-Barrioz
038: * @author Y.Bersihand
039: */
040: public final class DataStoreId extends AbstractMetaInfoVisitor
041: implements SpeedoProperties {
042:
043: public DataStoreId(Personality p) {
044: super (p);
045: }
046:
047: /**
048: * Register the sequence as serialized meta objects (.jmi file).
049: */
050: public final void visitSequence(final SpeedoSequence ss,
051: SpeedoPackage sp) throws SpeedoException {
052: sp.xmlDescriptor.mos.add(ss);
053: super .visitSequence(ss, sp);
054: }
055:
056: /**
057: * Treats the datastore identifier of the class
058: */
059: public final void visitClass(final SpeedoClass sc)
060: throws SpeedoException {
061: if (sc.identity.isDataStore()) {
062: translateIDExtension(sc);
063: treatDataStoreSequence(sc);
064: treatDataStoreLong(sc);
065: }
066: super .visitClass(sc);
067: }
068:
069: public void visitField(SpeedoField sf) throws SpeedoException {
070: super .visitField(sf);
071: //change identity.strategy to DATASTORE_SEQUENCE
072: //and assign the sequence to the class as an id
073: //only if field is pk
074: if (sf.primaryKey && sf.valueStrategy != null
075: && sf.valueStrategy.equals("sequence")
076: && sf.sequence != null) {
077: sf.moClass.identity.strategy = SpeedoIdentity.DATASTORE_SEQUENCE;
078: sf.moClass.identity.sequenceName = sf.sequence;
079: }
080: }
081:
082: protected String getLoggerName() {
083: return super .getLoggerName() + ".datastoreid";
084: }
085:
086: /**
087: * translates the ID extension in a identity strategy
088: */
089: private final void translateIDExtension(final SpeedoClass sc)
090: throws SpeedoException {
091: final String idExt = sc.getExtensionValueByKey(ID);
092: if (idExt != null) {
093: if (ID_LONG.equals(idExt)) {
094: sc.identity.strategy = SpeedoIdentity.DATASTORE_LONG;
095: } else if (ID_OLONG.equals(idExt)) {
096: sc.identity.strategy = SpeedoIdentity.DATASTORE_OLONG;
097: } else if (ID_SEQUENCE.equals(idExt)) {
098: sc.identity.strategy = SpeedoIdentity.DATASTORE_SEQUENCE;
099: } else if (ID_POLYMORPH_2L.equals(idExt)) {
100: sc.identity.strategy = SpeedoIdentity.DATASTORE_POLYMORPHID;
101: } else {
102: logger.log(BasicLevel.WARN, "Extension " + idExt
103: + " unknown => use the default (class="
104: + sc.getFQName() + ").");
105: }
106: logger.log(BasicLevel.DEBUG, "Set the strategy "
107: + sc.identity.getStrategyName()
108: + " to the identity of the class " + sc.getFQName()
109: + " from the extension " + ID + "/" + idExt);
110: }
111: }
112:
113: /**
114: * , and create
115: * SpeedoSequence for old extention.
116: * if sequence name specified, set the identity of the class
117: */
118: private final void treatDataStoreSequence(final SpeedoClass sc)
119: throws SpeedoException {
120: final String seqName = sc.getExtensionValueByKey(SQL_SEQ_NAME);
121: if (seqName != null) {
122: logger.log(BasicLevel.DEBUG, "Set the sequence name: "
123: + seqName + " to the identity of the class '"
124: + sc.getFQName() + "'.");
125: sc.identity.setDatastoreIdSequenceName(seqName);
126: }
127: if (sc.identity.strategy == SpeedoIdentity.DATASTORE_SEQUENCE) {
128: if (sc.identity.sequenceName == null
129: || sc.moPackage.sequences
130: .get(sc.identity.sequenceName) == null) {
131: // No sequence name is defined or no SpeedoSequence exists to
132: // the specified name
133: createSpeedoSequenceFromExtension(sc);
134: }
135: }
136: }
137:
138: /**
139: * Creates a new SpeedoSequence, register it into class's package and
140: * configures it from old extensions.
141: * @param sc a class requiring a sequence for the identifier.
142: */
143: private SpeedoSequence createSpeedoSequenceFromExtension(
144: final SpeedoClass sc) {
145: if (sc.identity.sequenceName == null) {
146: //compute the name of the sequence
147: SpeedoExtension se = sc.getExtensionByKey(SQL_SEQ_NAME);
148: if (se == null) { //no extension for the name of the sequence
149: if (sc.mainTable != null) {
150: if (debug) {
151: logger
152: .log(BasicLevel.DEBUG,
153: "Sequence name computed from the table name.");
154: }
155: //use the name of table
156: sc.identity.sequenceName = sc.mainTable.name
157: + "_SEQ";
158: } else {
159: if (debug) {
160: logger
161: .log(BasicLevel.DEBUG,
162: "Sequence name computed from the class name.");
163: }
164: //use the name of class (without package name)
165: sc.identity.sequenceName = sc.name.toUpperCase()
166: + "_SEQ";
167: }
168: } else {
169: if (debug) {
170: logger.log(BasicLevel.DEBUG,
171: "Sequence name specified by the extension "
172: + SQL_SEQ_NAME);
173: }
174: sc.identity.sequenceName = se.value;
175: }
176: }
177: //Create the sequence and register it
178: SpeedoSequence seq = new JDOSequence();
179: seq.name = sc.identity.sequenceName;
180: seq.packageName = sc.moPackage.name;
181: sc.moPackage.addSequence(seq);
182: seq.datastoreName = sc.identity.sequenceName;
183: seq.strategy = SpeedoSequence.NON_TRANSACTIONAL;
184: sc.moPackage.xmlDescriptor.mos.add(seq);
185: if (debug) {
186: logger.log(BasicLevel.DEBUG, "Create the sequence '"
187: + seq.name + "' into the package '"
188: + seq.packageName);
189: }
190:
191: //Configure the sequence from the extensions
192:
193: //increment
194: String v = sc.getExtensionValueByKey(SQL_SEQ_INC);
195: if (v != null) {
196: seq.increment = new Integer(v);
197: if (debug) {
198: logger.log(BasicLevel.DEBUG, "\t- Sequence increment: "
199: + seq.increment);
200: }
201: }
202: //start
203: v = sc.getExtensionValueByKey(SQL_SEQ_START);
204: if (v != null) {
205: seq.start = new Integer(v);
206: if (debug) {
207: logger.log(BasicLevel.DEBUG, "\t- Sequence start: "
208: + seq.start);
209: }
210: }
211: //cache
212: v = sc.getExtensionValueByKey(SQL_SEQ_CACHE);
213: if (v != null) {
214: seq.cache = new Integer(v);
215: if (debug) {
216: logger.log(BasicLevel.DEBUG, "\t- Sequence cache: "
217: + seq.cache);
218: }
219: }
220: //allocator
221: v = sc.getExtensionValueByKey(SQL_SEQ_ALLOCATOR);
222: if (v != null) {
223: seq.factoryClass = v;
224: if (debug) {
225: logger.log(BasicLevel.DEBUG, "\t- Sequence allocator: "
226: + seq.factoryClass);
227: }
228: }
229: return seq;
230: }
231:
232: /**
233: * If strategy is the default one (SpeedoIdentity.DATASTORE_NATIVE) then we
234: * have to check the type of field (if there is one). Maybe it is a
235: * java.lang.Long instead of a long. In this case the strategy is
236: * SpeedoIdentity.DATASTORE_OLONG.
237: */
238: private final void treatDataStoreLong(final SpeedoClass sc)
239: throws SpeedoException {
240: if (sc.identity.strategy == SpeedoIdentity.DATASTORE_NATIVE) {
241: SpeedoField sf = sc.getUniquePKField();
242: if (sf != null && "Ljava/lang/Long;".equals(sf.type)) {
243: sc.identity.strategy = SpeedoIdentity.DATASTORE_OLONG;
244: }
245: }
246: }
247: }
|