package com.openMap1.mapper.mapping;
import com.openMap1.mapper.core.ClassSet;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.util.ModelUtil;
import com.openMap1.mapper.util.messageChannel;
import com.openMap1.mapper.util.GenUtil;
import com.openMap1.mapper.ModelAssocFilter;
import java.util.Iterator;
import java.util.Vector;
/**
* represents one association inclusion filter in an object mapping;
* the object must be associated by the association in order to be represented in the XML
*
* This class is a wrapper around the model class ModelAssocFilter
*
* @author Robert Worden
* @version 1.0
*/
public class filterAssoc extends filter
{
private ClassSet cSet1,cSet2; // names of the two classes involved in the condition
private String assocName; // name of the association
private int otherEnd = 0; // the end of the association for the non-dependent object; = 1 or 2.
private String otherRole; // the role name for the non-dependent object
private String otherCName,otherSubset;
String[] filterAtts = {"assocName","otherClass","otherSubset","otherEnd","otherRole"};
private boolean failToInclude;
/**
* @return true if the object should NOT have the association in order to be included
*/
public boolean failToInclude() {return failToInclude;}
/** name of the association */
public String assocName() {return assocName;}
/** (class,subset) at end 1 of the association */
public ClassSet cSet1() {return cSet1;}
/** (class,subet) at end 2 of the association */
public ClassSet cSet2() {return cSet2;}
/** the end of the association for the non-dependent object; = 1 or 2. */
public int otherEnd() {return otherEnd;}
/** role name at the end of the association for the non-dependent object; = 1 or 2. */
public String otherRole() {return otherRole;}
// called with an me:filterAssoc element as argument
/**
* called with an me:filterAssoc element as argument
* @param md MDLBase
* @param el Element an me:filterAssoc element
* @param thisCSet ClassSet
* @throws MDLReadException
*/
public filterAssoc(messageChannel mc, ModelAssocFilter maf, ClassSet thisCSet) throws MapperException
{
super(mc,thisCSet);
otherCName = ModelUtil.getQualifiedClassName(GenUtil.gaplessForm(maf.getOtherClassName()),
maf.getOtherPackageName());
otherSubset = GenUtil.gaplessForm(maf.getOtherSubset());
ClassSet otherCSet = new ClassSet(otherCName,otherSubset);
setDepCSet(otherCSet);
assocName = GenUtil.gaplessForm(maf.getAssocName());
otherRole = maf.getOtherRoleName();
// FIXME; we should not really use the description field to denote 'fail to include' associations
failToInclude = ((maf.getDescription() != null)&& (maf.getDescription().startsWith("NOT")));
otherEnd = maf.getOtherEnd();
if (otherEnd == 1)
{
cSet1 = otherCSet;
cSet2 = thisCSet;
}
else if (otherEnd == 2)
{
cSet2 = otherCSet;
cSet1 = thisCSet;
}
else {throw new MapperException("Filter association end should be 1 or 2 but is '" + otherEnd + "'"); }
}
/** make a filter from a required association mapping
where otherEnd (= 1 or 2) is not the end required to have that association.
Beware - thisEnd is in the (0,1) convention .... */
public filterAssoc(messageChannel mc, AssociationMapping am, int thisEnd) throws MapperException
{
super(mc,am.assocEnd(thisEnd).cSet());
otherEnd = 2 - thisEnd; // 1 or 2
otherRole = am.assocEnd(otherEnd-1).roleName();
setDepCSet(am.assocEnd(otherEnd-1).cSet());
cSet1 = am.assocEnd(0).cSet();
cSet2 = am.assocEnd(1).cSet();
assocName = am.assocName();
}
/**
* described in the user manual as the constructor to use in an objectCapability.
* thisEnd is in 1,2 convention.
*/
/* convert this constructor later
public filterAssoc(MDLBase md, String thisClass, String assName,
int thisEnd, String otherClass, String othRole)
{
super(md,new ClassSet(thisClass,""));
otherEnd = 3 - thisEnd; // 1 or 2
otherRole = othRole;
ClassSet cThis = new ClassSet(thisClass,"");
ClassSet cThat = new ClassSet(otherClass,"");
setDepCSet(cThat);
if (thisEnd == 1) {cSet1 = cThis; cSet2 = cThat;}
else if (thisEnd == 2) {cSet2 = cThis; cSet1 = cThat;}
assocName = assName;
} */
/**
* equality test
* @param fa filterAssoc
* @return boolean
*/
public boolean sameFilter(filterAssoc fa)
{
return ((cSet1().className().equals(fa.cSet1().className()))
&& (cSet2().className().equals(fa.cSet2().className()))
&& (assocName().equals(fa.assocName())));
}
/** true if this filter is in a vector of filters */
public boolean inFilters(Vector<filter> filters)
{
int i;
filter f;
filterAssoc fa;
boolean res = false;
for (i = 0; i < filters.size(); i++)
{
f = (filter)filters.elementAt(i);
if (f instanceof filterAssoc)
{
fa = (filterAssoc)f;
if (sameFilter(fa)) res = true;
}
}
return res;
}
/** write a readable form of the inclusion filter */
public void write()
{
String classSet = "null";
if (onCSet() != null) classSet = onCSet().stringForm();
String sign = "";
if (failToInclude()) sign = "NOT ";
mChan().message("Class " + classSet + " requires " + sign + stringForm());
}
/** string form of the association */
public String stringForm()
{
return ("[" + cSet1.stringForm() + "]"
+ assocName
+ "[" + cSet2.stringForm() + "]");
}
public static Vector<filterAssoc> vCopy(Vector<filterAssoc> v)
{
Vector<filterAssoc> res = new Vector<filterAssoc>();
for (Iterator<filterAssoc> it = v.iterator();it.hasNext();) res.add(it.next());
return res;
}
}