/**
* Copyright (C) 2001-2006 France Telecom R&D
*/
package org.objectweb.speedo.generation.mivisitor;
import org.objectweb.asm.Type;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoColumn;
import org.objectweb.speedo.metadata.SpeedoDiscriminator;
import org.objectweb.speedo.metadata.SpeedoElement;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.speedo.metadata.SpeedoNoFieldColumn;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
public class DiscriminatorVisitor extends AbstractMetaInfoVisitor {
public DiscriminatorVisitor(Personality p) {
super(p);
}
protected String getLoggerName() {
return super.getLoggerName() + ".discriminator";
}
public void visitClass(SpeedoClass sc) throws SpeedoException {
getDiscriminatorFromParent(sc);
super.visitClass(sc);
}
private SpeedoDiscriminator getDiscriminatorFromParent(SpeedoClass sc) throws SpeedoException {
if (sc.inheritance == null) {
return null;
}
SpeedoDiscriminator sd = sc.inheritance.discriminator;
SpeedoClass parent = sc.getSuper();
if (parent == null) {
// sc is the root of the tree
if (sd != null) {
checkColumn(sc, sd);
if (sd.strategy == SpeedoDiscriminator.STRATEGY_CLASS_NAME) {
SpeedoElement se = (SpeedoElement) sd.elements.get(0);
if (se instanceof SpeedoNoFieldColumn) {
((SpeedoNoFieldColumn) se).type = Type.getDescriptor(String.class);
}
}
}
} else {
sd = getDiscriminatorFromParent(parent);
// use the discriminator of parent
if (sd != null) {
SpeedoDiscriminator oldsd = sc.inheritance.discriminator;
if (oldsd != sd) {
sc.inheritance.discriminator = sd;
if (sc.inheritance.discriminatorValues != null) {
//Replace old keys in discriminator map values
replaceOldKeys(sd, oldsd, sc.inheritance.discriminatorValues);
}
}
}
}
if (sd != null && sd.strategy == SpeedoDiscriminator.STRATEGY_CLASS_NAME
&& sc.inheritance.discriminatorValues == null) {
//Assign the value corresponding to the strategy
sc.inheritance.discriminatorValues =
Collections.singletonMap(sd.elements.get(0), sc.getFQName());
}
return sd;
}
private void replaceOldKeys(SpeedoDiscriminator sd, SpeedoDiscriminator oldsd, Map discValues) {
if (oldsd == null || sd == null) {
return;
}
if (sd.elements.size() == 1 && oldsd.elements.size() == 1) {
Object val = discValues.get(oldsd.elements.get(0));
discValues.put(sd.elements.get(0), val);
return;
}
for (Iterator it = oldsd.elements.iterator(); it.hasNext();) {
SpeedoElement oldse = (SpeedoElement) it.next();
if (oldse instanceof SpeedoNoFieldColumn) {
SpeedoNoFieldColumn snfc = (SpeedoNoFieldColumn) oldse;
SpeedoElement inheritedse = null;
for (Iterator it2 = sd.elements.iterator(); inheritedse == null && it2.hasNext();) {
SpeedoElement currentse = (SpeedoElement) it2.next();
if (currentse instanceof SpeedoNoFieldColumn) {
if (snfc.column.name.equals(
((SpeedoNoFieldColumn) currentse).column.name)) {
inheritedse = currentse;
}
} else if (currentse instanceof SpeedoField) {
if (snfc.column.name.equals(
((SpeedoField) currentse).columns[0].name)) {
inheritedse = currentse;
}
}
}
if (inheritedse != null) {
Object val = discValues.get(oldse);
discValues.put(inheritedse, val);
}
}
}
}
private void checkColumn(SpeedoClass sc, SpeedoDiscriminator sd) throws SpeedoException {
for (int i = 0; i < sd.elements.size(); i++) {
SpeedoElement se = (SpeedoElement) sd.elements.get(i);
if (se instanceof SpeedoNoFieldColumn) {
SpeedoColumn col = ((SpeedoNoFieldColumn) se).column;
SpeedoField sf = sc.getFieldFromColumn(col.name);
if (sf != null) {
// the specified column correspond to a primitive persistent
// field. Then the SpeedoNoFieldColumn is replaced by the
// the found field.
sd.elements.set(i, sf);
}
}
}
}
}