/**
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.objectweb.speedo.generation.mivisitor;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoProperties;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoExtension;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.util.monolog.api.BasicLevel;
/**
* Add the reverse extensions on the forgetten side. In addition the mapping
* is added too.
*
* @author S.Chassande-Barrioz
*/
public class ReverseFieldAdder extends AbstractMetaInfoVisitor {
public String getTitle() {
return "Reverse field definition completion...";
}
public ReverseFieldAdder(Personality p) {
super(p);
}
public ReverseFieldAdder(MetaInfoVisitor mim, Personality p) {
super(mim, p);
}
protected String getLoggerName() {
return LOGGER_NAME + ".reverseField";
}
public void visitField(SpeedoField sf) throws SpeedoException {
super.visitField(sf);
String rf = sf.getExtensionValueByKey(SpeedoProperties.REVERSE_FIELD);
if (rf != null) {
sf.reverseField = rf;
sf.isCoherentReverseField = true;
}
if (sf.reverseField == null) {
return;
}
SpeedoField reverse = sf.getReverseField();
if (reverse == null) {
throw new SpeedoException("No reverse field '" + sf.reverseField
+ "' found for the " + sf.getSourceDesc());
}
if (reverse.reverseField == null) {
//fill the info about the current field on its reverse
reverse.reverseField = sf.name;
reverse.isCoherentReverseField = sf.isCoherentReverseField;
} else if (!reverse.reverseField.equals(sf.name)) {
throw new SpeedoException("Incoherent reverse field between the "
+ sf.getSourceDesc() + " and the "
+ reverse.getSourceDesc());
}
// compute relationType
if (sf.jdoTuple != null) {
if (reverse.jdoTuple != null) {
sf.relationType = SpeedoField.MANY_MANY_BI_RELATION;
reverse.relationType = SpeedoField.MANY_MANY_BI_RELATION;
} else {
sf.relationType = SpeedoField.ONE_MANY_BI_RELATION;
reverse.relationType = SpeedoField.MANY_ONE_BI_RELATION;
}
} else {
if (reverse.jdoTuple != null) {
sf.relationType = SpeedoField.MANY_ONE_BI_RELATION;
reverse.relationType = SpeedoField.ONE_MANY_BI_RELATION;
} else {
sf.relationType = SpeedoField.ONE_ONE_BI_RELATION;
reverse.relationType = SpeedoField.ONE_ONE_BI_RELATION;
}
}
}
/**
* Synchronize extension SpeedoProperties.REVERSE_FIELD to the fields
* SpeedoField.reverseField and SpeedoField.isCoherentReverseField
*
* @see SpeedoField#reverseField
* @see SpeedoField#isCoherentReverseField
* @see SpeedoProperties#REVERSE_FIELD
*/
public void visitExtension(SpeedoExtension se) throws SpeedoException {
debug = logger.isLoggable(BasicLevel.DEBUG);
if (!SpeedoProperties.VENDOR_NAME.equals(se.vendorName)
|| !SpeedoProperties.REVERSE_FIELD.equals(se.key)) {
super.visitExtension(se);
return;
}
//check that the extension REVERSE_FIELD is specified for a SpeedoField
if (!(se.owner instanceof SpeedoField)) {
SpeedoClass sc = getSpeedoClass(se.owner);
logger.log(BasicLevel.ERROR, "You have specified the reverse field ('"
+ se.value + "') in other thing than a field tag ('"
+ se.owner.toString() + "')" +
(sc == null
? ""
: " in class '" + sc.getFQName() + "' of the descriptor '"
+ sc.moPackage.xmlDescriptor.xmlFile));
super.visitExtension(se);
return;
}
SpeedoField sf = (SpeedoField) se.owner;
sf.reverseField = se.value;
sf.isCoherentReverseField = true;
SpeedoField reverse = sf.getReverseField();
if (reverse == null) {
throw new SpeedoException("No reverse field '" + sf.reverseField
+ "' found for the " + sf.getSourceDesc());
}
checkExtension(sf, reverse,
SpeedoProperties.TARGET_FK, SpeedoProperties.SOURCE_FK);
checkExtension(sf, reverse,
SpeedoProperties.SOURCE_FK, SpeedoProperties.TARGET_FK);
checkExtension(reverse, sf,
SpeedoProperties.TARGET_FK, SpeedoProperties.SOURCE_FK);
checkExtension(reverse, sf,
SpeedoProperties.SOURCE_FK, SpeedoProperties.TARGET_FK);
checkExtension(sf, reverse,
SpeedoProperties.JOIN_TABLE, SpeedoProperties.JOIN_TABLE);
super.visitExtension(se);
}
/**
* Check if a SpeedoField has a specified SpeedoExtension ('ext1'). If yes
* the extension 'ext2' is add on the reverse field with the same value.
* If the meta data is malformed then the visit continue to the next
* MetaDatavisitor.
* @param sf is the SpeedoField containing the SpeedoExtension 'ext1'
* @param reverse the SpeedoField which must contains at the end the options
* ext2 if the extension ext1 is defined on the field 'sf'
* @param ext1 a name of a SpeedoExtension (@see SpeedoProperties)
* @param ext2 a name of a SpeedoExtension (@see SpeedoProperties)
*/
private void checkExtension(SpeedoField sf,
SpeedoField reverse,
String ext1,
String ext2) throws SpeedoException {
SpeedoExtension se1 = sf.getExtension(SpeedoProperties.VENDOR_NAME, ext1);
if (se1 == null) {
return;
}
SpeedoExtension se2 = reverse.getExtension(SpeedoProperties.VENDOR_NAME, ext2);
if (se2 == null) {
//define the extension on the reverse field with the same value
se2 = new SpeedoExtension(SpeedoProperties.VENDOR_NAME, ext2, se1.value, reverse);
reverse.addExtension(se2);
logger.log(BasicLevel.DEBUG, "add the extension(" + ext2
+ ", " + se1.value +") on the " + reverse.getSourceDesc());
} else if (!se2.value.equals(se1.value)) {
throw new SpeedoException(
"A bad mapping has been specified on the reverse "
+ reverse.getSourceDesc() + "' with regards to the "
+ sf.getSourceDesc());
} else if (debug) {
SpeedoClass sc1 = sf.moClass;
SpeedoClass sc2 = reverse.moClass;
logger.log(BasicLevel.DEBUG, "You could remove one of the following extensions:"
+ "\n- .jdo: '" + sc1.moPackage.xmlDescriptor.xmlFile
+ "', class: '" + sc1.getFQName()
+ "', field: '" + sf.name
+ "', extension: '" + ext1 + "'"
+ "\n- .jdo: '" + sc2.moPackage.xmlDescriptor.xmlFile
+ "', class: '" + sc2.getFQName()
+ "', field: '" + reverse.name
+ "', extension: '" + ext2 + "'"
);
}
}
}