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.util.monolog.api.BasicLevel;
026:
027: /**
028: * Add the reverse extensions on the forgetten side. In addition the mapping
029: * is added too.
030: *
031: * @author S.Chassande-Barrioz
032: */
033: public class ReverseFieldAdder extends AbstractMetaInfoVisitor {
034:
035: public String getTitle() {
036: return "Reverse field definition completion...";
037: }
038:
039: public ReverseFieldAdder(Personality p) {
040: super (p);
041: }
042:
043: public ReverseFieldAdder(MetaInfoVisitor mim, Personality p) {
044: super (mim, p);
045: }
046:
047: protected String getLoggerName() {
048: return LOGGER_NAME + ".reverseField";
049: }
050:
051: public void visitField(SpeedoField sf) throws SpeedoException {
052: super .visitField(sf);
053: String rf = sf
054: .getExtensionValueByKey(SpeedoProperties.REVERSE_FIELD);
055: if (rf != null) {
056: sf.reverseField = rf;
057: sf.isCoherentReverseField = true;
058: }
059: if (sf.reverseField == null) {
060: return;
061: }
062: SpeedoField reverse = sf.getReverseField();
063: if (reverse == null) {
064: throw new SpeedoException("No reverse field '"
065: + sf.reverseField + "' found for the "
066: + sf.getSourceDesc());
067: }
068: if (reverse.reverseField == null) {
069: //fill the info about the current field on its reverse
070: reverse.reverseField = sf.name;
071: reverse.isCoherentReverseField = sf.isCoherentReverseField;
072: } else if (!reverse.reverseField.equals(sf.name)) {
073: throw new SpeedoException(
074: "Incoherent reverse field between the "
075: + sf.getSourceDesc() + " and the "
076: + reverse.getSourceDesc());
077: }
078:
079: // compute relationType
080: if (sf.jdoTuple != null) {
081: if (reverse.jdoTuple != null) {
082: sf.relationType = SpeedoField.MANY_MANY_BI_RELATION;
083: reverse.relationType = SpeedoField.MANY_MANY_BI_RELATION;
084: } else {
085: sf.relationType = SpeedoField.ONE_MANY_BI_RELATION;
086: reverse.relationType = SpeedoField.MANY_ONE_BI_RELATION;
087: }
088: } else {
089: if (reverse.jdoTuple != null) {
090: sf.relationType = SpeedoField.MANY_ONE_BI_RELATION;
091: reverse.relationType = SpeedoField.ONE_MANY_BI_RELATION;
092: } else {
093: sf.relationType = SpeedoField.ONE_ONE_BI_RELATION;
094: reverse.relationType = SpeedoField.ONE_ONE_BI_RELATION;
095: }
096: }
097: }
098:
099: /**
100: * Synchronize extension SpeedoProperties.REVERSE_FIELD to the fields
101: * SpeedoField.reverseField and SpeedoField.isCoherentReverseField
102: *
103: * @see SpeedoField#reverseField
104: * @see SpeedoField#isCoherentReverseField
105: * @see SpeedoProperties#REVERSE_FIELD
106: */
107: public void visitExtension(SpeedoExtension se)
108: throws SpeedoException {
109: debug = logger.isLoggable(BasicLevel.DEBUG);
110: if (!SpeedoProperties.VENDOR_NAME.equals(se.vendorName)
111: || !SpeedoProperties.REVERSE_FIELD.equals(se.key)) {
112: super .visitExtension(se);
113: return;
114: }
115:
116: //check that the extension REVERSE_FIELD is specified for a SpeedoField
117: if (!(se.owner instanceof SpeedoField)) {
118: SpeedoClass sc = getSpeedoClass(se.owner);
119: logger
120: .log(
121: BasicLevel.ERROR,
122: "You have specified the reverse field ('"
123: + se.value
124: + "') in other thing than a field tag ('"
125: + se.owner.toString()
126: + "')"
127: + (sc == null ? ""
128: : " in class '"
129: + sc.getFQName()
130: + "' of the descriptor '"
131: + sc.moPackage.xmlDescriptor.xmlFile));
132: super .visitExtension(se);
133: return;
134: }
135:
136: SpeedoField sf = (SpeedoField) se.owner;
137: sf.reverseField = se.value;
138: sf.isCoherentReverseField = true;
139: SpeedoField reverse = sf.getReverseField();
140: if (reverse == null) {
141: throw new SpeedoException("No reverse field '"
142: + sf.reverseField + "' found for the "
143: + sf.getSourceDesc());
144: }
145: checkExtension(sf, reverse, SpeedoProperties.TARGET_FK,
146: SpeedoProperties.SOURCE_FK);
147: checkExtension(sf, reverse, SpeedoProperties.SOURCE_FK,
148: SpeedoProperties.TARGET_FK);
149: checkExtension(reverse, sf, SpeedoProperties.TARGET_FK,
150: SpeedoProperties.SOURCE_FK);
151: checkExtension(reverse, sf, SpeedoProperties.SOURCE_FK,
152: SpeedoProperties.TARGET_FK);
153: checkExtension(sf, reverse, SpeedoProperties.JOIN_TABLE,
154: SpeedoProperties.JOIN_TABLE);
155: super .visitExtension(se);
156: }
157:
158: /**
159: * Check if a SpeedoField has a specified SpeedoExtension ('ext1'). If yes
160: * the extension 'ext2' is add on the reverse field with the same value.
161: * If the meta data is malformed then the visit continue to the next
162: * MetaDatavisitor.
163: * @param sf is the SpeedoField containing the SpeedoExtension 'ext1'
164: * @param reverse the SpeedoField which must contains at the end the options
165: * ext2 if the extension ext1 is defined on the field 'sf'
166: * @param ext1 a name of a SpeedoExtension (@see SpeedoProperties)
167: * @param ext2 a name of a SpeedoExtension (@see SpeedoProperties)
168: */
169: private void checkExtension(SpeedoField sf, SpeedoField reverse,
170: String ext1, String ext2) throws SpeedoException {
171: SpeedoExtension se1 = sf.getExtension(
172: SpeedoProperties.VENDOR_NAME, ext1);
173: if (se1 == null) {
174: return;
175: }
176: SpeedoExtension se2 = reverse.getExtension(
177: SpeedoProperties.VENDOR_NAME, ext2);
178: if (se2 == null) {
179: //define the extension on the reverse field with the same value
180: se2 = new SpeedoExtension(SpeedoProperties.VENDOR_NAME,
181: ext2, se1.value, reverse);
182: reverse.addExtension(se2);
183: logger.log(BasicLevel.DEBUG, "add the extension(" + ext2
184: + ", " + se1.value + ") on the "
185: + reverse.getSourceDesc());
186: } else if (!se2.value.equals(se1.value)) {
187: throw new SpeedoException(
188: "A bad mapping has been specified on the reverse "
189: + reverse.getSourceDesc()
190: + "' with regards to the "
191: + sf.getSourceDesc());
192: } else if (debug) {
193: SpeedoClass sc1 = sf.moClass;
194: SpeedoClass sc2 = reverse.moClass;
195: logger.log(BasicLevel.DEBUG,
196: "You could remove one of the following extensions:"
197: + "\n- .jdo: '"
198: + sc1.moPackage.xmlDescriptor.xmlFile
199: + "', class: '" + sc1.getFQName()
200: + "', field: '" + sf.name
201: + "', extension: '" + ext1 + "'"
202:
203: + "\n- .jdo: '"
204: + sc2.moPackage.xmlDescriptor.xmlFile
205: + "', class: '" + sc2.getFQName()
206: + "', field: '" + reverse.name
207: + "', extension: '" + ext2 + "'");
208: }
209: }
210: }
|