package com.openMap1.mapper.mapping;
import com.openMap1.mapper.util.messageChannel;
import com.openMap1.mapper.writer.XSLGenerator;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.ModelAssocFilter;
import com.openMap1.mapper.ModelFilter;
import com.openMap1.mapper.ModelPropertyFilter;
import com.openMap1.mapper.ObjMapping;
import java.util.Vector;
import java.util.Iterator;
/**
* An object mapping - defines how an object of some class is represented in XML
* <p>
*
* This is a wrapper for the model class ObjMapping.
* @author Robert Worden
* @version 1.0
*/
public class objectMapping extends MappingTwo
{
ObjMapping oMap() {return (ObjMapping)map();}
// object mappings have no link conditions, as they only involve one node
private Vector<filter> inclusionFilters = new Vector<filter>();
/** inclusion filters saying which objects in the class are represented by this node */
public Vector<filter> inclusionFilters(){return inclusionFilters;}
private boolean isUnique = true;
/** true if theXML represents each object uniquely,
i.e. does not represent multiple copies of the same object */
public boolean isUnique() {return isUnique;}
/** add an inclusion filter saying which objects in the class are represented by this node */
public void addInclusionFilter(filter f) {inclusionFilters.addElement(f);}
/** set to true if theXML represents each object uniquely,
i.e. does not represent multiple copies of the same object */
public void setIsUnique(boolean is) {isUnique = is;}
private boolean isParameterMapping = false; // for mapping modules
/** a parameter mapping of a mapping module */
public boolean isParameterMapping() {return isParameterMapping;}
/**
* make this a parameter mapping only if isParam = 'true'
*
* @param isParam String
*/
public void setIsParam(String isParam) {if (isParam.equals("true")) isParameterMapping = true;}
/**
* when generating XSLT with imported mapping sets in the input
* @return full XPath from the root to this mapping - longer than the piece
* within this mapping set
*/
public String getFullXPath() {return fullXPath;}
private String fullXPath = "";
/**
* when generating XSLT with imported mapping sets in the input
* set the full XPath from the root to this mapping - longer than the piece
* within this mapping set
*/
public void setFullXPath(String fullXPath) {this.fullXPath = fullXPath;}
/**
* @param om the ObjMapping in the EMF model
* @param mc for writing out messages
*/
public objectMapping(ObjMapping om, messageChannel mc) throws MapperException
{
super(om, mc);
mappingType = MappingTwo.OBJECT;
if (oMap().getModelFilterSet() != null)
for (Iterator<ModelFilter> it = oMap().getModelFilterSet().getModelFilters().iterator();it.hasNext();)
{
ModelFilter mf = it.next();
if (mf instanceof ModelPropertyFilter)
{addInclusionFilter(new filterProp(mChan(),(ModelPropertyFilter)mf,oMap().getClassSet()));}
else if (mf instanceof ModelAssocFilter)
{addInclusionFilter(new filterAssoc(mChan(),(ModelAssocFilter)mf,oMap().getClassSet()));}
}
}
/** write a text description of the object mapping */
public void write()
{
mChan().message("");
mChan().message("Object mapping of class " + cSet().stringForm() + " to node " + nodePath().stringForm());
writeConditions();
}
/** vector of association filters (one type of inclusion filter) */
public Vector<filterAssoc> filterAssocs()
{
Vector<filterAssoc> res = new Vector<filterAssoc>();
int i;
filter filt;
for (i = 0; i < inclusionFilters.size(); i++)
{
filt = inclusionFilters.elementAt(i);
if (filt instanceof filterAssoc)
{res.addElement((filterAssoc)filt);}
}
return res;
}
/** vector of property filters (one type of inclusion filter) */
public Vector<filterProp> filterProps()
{
Vector<filterProp> res = new Vector<filterProp>();
int i;
filter filt;
for (i = 0; i < inclusionFilters.size(); i++)
{
filt = inclusionFilters.elementAt(i);
if (filt instanceof filterProp)
{res.addElement((filterProp)filt);}
}
return res;
}
/** true if the set of filters for this object mapping is mutually exclusive
with the set of filters for some other object mapping - i.e if no
object can satisfy both sets at once.
Appropriate when the object mappings are for different subsets of the same class. */
public boolean exclusiveFilters(objectMapping om)
{
int i,j;
filterProp f1,f2;
boolean res = false;
for (i = 0; i < filterProps().size(); i++)
{
f1 = filterProps().elementAt(i);
for (j = 0; j < om.filterProps().size(); j++)
{
f2 = om.filterProps().elementAt(j);
if (f1.mutuallyExclusive(f2)) res = true;
}
}
return res;
}
/** short text description */
public String description()
{
return("mapping for class '" + className() + "'");
}
/**
* A vector of association inclusion filters that must be included in XSLT,
* i.e excluding any that use the same association just navigated to get the object.
*
* @param inputAssoc associationMapping association just navigated to get the object, or null if none was navigated
* @return Vector of all other association filters */
public Vector<filterAssoc> filterAssocsForXSLT(AssociationMapping inputAssoc)
throws MapperException
{
Vector<filterAssoc> filters = new Vector<filterAssoc>();
for (int i = 0; i < filterAssocs().size(); i++)
{
boolean checkNeeded = true;
filterAssoc fa = filterAssocs().elementAt(i);
if (inputAssoc != null) // if this object was got by navigating an association...
{
// and if the navigated association is the same as the association filter...
if ((fa.cSet1().className().equals(inputAssoc.assocEnd(0).className())) &&
(fa.cSet2().className().equals(inputAssoc.assocEnd(1).className())) &&
(fa.assocName().equals(inputAssoc.assocName())))
checkNeeded = false; // ...then it is not necessary to check the association filter
}
if (checkNeeded)
{
filters.addElement(fa);
}
}
return filters;
}
/** this is called on an output XML mapping, looking at the input mappings
* to construct the XPath expression for the output property inclusion filters in terms of input XPaths.
* if the input property mapping has a default, check that against the required value. */
public String XPathPropertyInclusionFilter(XSLGenerator XX, objectMapping inputObject)
throws MapperException
{
propertyMapping pm = null;
String res = "";
if (filterProps().size() > 0)
{
res = "[";
for (int i = 0; i < filterProps().size(); i++)
{
filterProp fp = filterProps().elementAt(i);
// find input property mapping for the property used in the filter
pm = XX.getInputPropertyMapping(inputObject.XSLCSet(),fp.property());
if (!(fp.test().equals("=")))
{
mChan().message("XSLT generation currently only supports '=' tests in inclusion filters.");
}
else
{
if (i > 0) res = res + " and ";
String XPath = null;
// for fixed property mappings, use the fixed value in stead of the XPath
if (pm.fixed()) XPath = "'" + pm.value() + "'";
// non-fixed property mappings have a non-null object-to-property path
else
{
XPath = XX.convertPathPrefixes(pm.objectToProperty().stringForm());
XPath = XPath + pm.XPathWhenTests(XX) + pm.XPathLinkTests(XX,true,null);
}
String cond = "(" + XPath + " = " + "'" + fp.value() + "')";
// if the property is not given in the input, and has the required default, let it pass
if ((pm.hasDefault()) && (pm.defaultValue().equals(fp.value())))
{cond = "(" + cond + " or ((not (" + XPath + "))))";}
res = res + cond;
}
}
res = res + "]";
}
return res;
}
/** to write this mapping out to an XML file (without its XPath) */
/*
public Element objectMapEl(XMLFile xf)
{
Element objEl = xf.NSElement(MDLPrefix(),"object",MDLURI());
objEl.setAttribute("class",className());
if (!subset().equals("")) objEl.setAttribute("subset",subset());
addXMLConditions(objEl); // add when-conditions
return objEl;
} */
}