package com.openMap1.mapper.converters;
import java.util.StringTokenizer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.structures.MapperWrapper;
import com.openMap1.mapper.util.XMLUtil;
import com.openMap1.mapper.MappedStructure;
public class OMLWrapper extends AbstractMapperWrapper implements MapperWrapper {
/**
* @param ms set of mappings which uses this wrapper transform
* @param spare spare argument, set to name of topElementDef
*/
public OMLWrapper(MappedStructure ms, Object spare) throws MapperException
{
super(ms,spare);
}
/**
* @return the type of document transformed to and from;
* see static constants in class AbstractMapperWrapper.
*/
public int transformType() {return AbstractMapperWrapper.XML_TYPE;}
/**
*
* @return the file extension of the outer document, with initial '*.'
*/
public String fileExtension() {return "*.xml";}
//--------------------------------------------------------------------------------------------
// Transform methods in the MapperWrapper Interface
//--------------------------------------------------------------------------------------------
/**
*
* @param incoming; must be of class Element or InputStream
* @return the result of the in wrapper transform
*/
public Document transformIn(Object incoming) throws MapperException
{
if (!(incoming instanceof Element)) throw new MapperException("Document root is not an Element");
Element mappingRoot = (Element)incoming;
String mappingRootPath = "/MappingSet";
inResultDoc = XMLUtil.makeOutDoc();
// vanilla copy unless overridden for specific paths
Element inRoot = scanDocument(mappingRoot, mappingRootPath, AbstractMapperWrapper.IN_TRANSFORM);
inResultDoc.appendChild(inRoot);
return inResultDoc;
}
/**
* @param outgoing the root element produced by the XMLWriter when
* writing out from a class model instance (seen through an objectGetter)
* @return the result of the out wrapper transform;
* must be of class Document or OutputStream
*/
public Object transformOut(Element outgoing) throws MapperException
{
String mappingRootPath = "/MappingSet";
outResultDoc = XMLUtil.makeOutDoc();
// vanilla copy unless overridden for specific paths
Element outRoot = scanDocument(outgoing, mappingRootPath, AbstractMapperWrapper.OUT_TRANSFORM);
outResultDoc.appendChild(outRoot);
return outResultDoc;
}
/**
* copy for each node in the in transform
* super.inTransformNode makes a vanilla copy,
* which this method overrides for specific XPaths
*/
protected Element inTransformNode(Element el, String path) throws MapperException
{
String cellPath = "/MappingSet/Mappings/row/";
String content = XMLUtil.getText(el);
if (content == null) content="";
/* parse out package name, class name and subset
* FIXME - what should this do for 'Class' and 'Feature' when class names contain a '.' ?*/
if (path.equals(cellPath + "Class"))
{
Element classEl = inResultDoc.createElement("Class");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,".");
// if there are any '.', the package name is before the first '.'
if (st.countTokens() > 1)
{
String packageName = st.nextToken();
classEl.appendChild(XMLUtil.textElement(inResultDoc, "package",packageName));
// strip off the package name and '.'
content = content.substring(packageName.length() + 1);
}
classEl.appendChild(XMLUtil.textElement(inResultDoc, "class", className(content)));
classEl.appendChild(XMLUtil.textElement(inResultDoc, "subset", subset(content)));
}
return classEl;
}
// parse out role name, target class and subset for associations
else if (path.equals(cellPath + "Feature"))
{
Element featureEl = inResultDoc.createElement("Feature");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,".");
if (st.countTokens() == 1)
{
featureEl.appendChild(XMLUtil.textElement(inResultDoc, "attribute", st.nextToken()));
}
else if (st.countTokens() > 1)
{
String roleName = st.nextToken();
featureEl.appendChild(XMLUtil.textElement(inResultDoc, "role", roleName));
// strip off the role name and '.'
content = content.substring(roleName.length() + 1);
featureEl.appendChild(XMLUtil.textElement(inResultDoc, "class", className(content)));
featureEl.appendChild(XMLUtil.textElement(inResultDoc, "subset", subset(content)));
}
}
return featureEl;
}
else if (path.equals(cellPath + "Condition"))
{
Element conditionEl = inResultDoc.createElement("Condition");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,";");
while (st.hasMoreTokens())
{
String cond = st.nextToken();
Element condEl = inResultDoc.createElement("Cond");
conditionEl.appendChild(condEl);
makeCondition(cond,condEl);
}
}
return conditionEl;
}
else if (path.equals(cellPath + "Key"))
{
Element keyEl = inResultDoc.createElement("Key");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,";");
while (st.hasMoreTokens())
{
String key = st.nextToken();
Element kEl = XMLUtil.textElement(inResultDoc, "keyField", key);
keyEl.appendChild(kEl);
}
}
return keyEl;
}
else if (path.equals(cellPath + "Filter"))
{
Element filterEl = inResultDoc.createElement("Filter");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,";");
while (st.hasMoreTokens())
{
String filt = st.nextToken();
Element filtEl = inResultDoc.createElement("Filt");
filterEl.appendChild(filtEl);
makeFilter(filt,filtEl);
}
}
return filterEl;
}
else if (path.equals(cellPath + "Convert_In"))
{
Element convertEl = inResultDoc.createElement("Convert_In");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,";");
while (st.hasMoreTokens())
{
String convert = st.nextToken();
Element convEl = XMLUtil.textElement(inResultDoc, "convert", convert);
convertEl.appendChild(convEl);
}
}
return convertEl;
}
else if (path.equals(cellPath + "Convert_Out"))
{
Element convertEl = inResultDoc.createElement("Convert_Out");
if (content.length() > 0)
{
StringTokenizer st = new StringTokenizer(content,";");
while (st.hasMoreTokens())
{
String convert = st.nextToken();
Element convEl = XMLUtil.textElement(inResultDoc, "convert", convert);
convertEl.appendChild(convEl);
}
}
return convertEl;
}
// other paths - vanilla copy
else return super.inTransformNode(el, path);
}
/**
* @param cond string condition
* @param condEl Element, whose child elements are to represent the condition
*/
private void makeCondition(String cond,Element condEl) throws MapperException
{
// strip off initial blanks
while (cond.startsWith(" ")) cond = cond.substring(1);
StringTokenizer st = new StringTokenizer(cond,"()");
if (st.countTokens() == 3)
{
condEl.setAttribute("type", "cross");
condEl.appendChild(XMLUtil.textElement(inResultDoc, "LHSPath", st.nextToken()));
condEl.appendChild(XMLUtil.textElement(inResultDoc, "test", stripBlanks(st.nextToken())));
condEl.appendChild(XMLUtil.textElement(inResultDoc, "RHSPath", st.nextToken()));
}
else if (st.countTokens() == 2)
{
condEl.setAttribute("type", "value");
condEl.appendChild(XMLUtil.textElement(inResultDoc, "LHSPath", st.nextToken()));
String remainder = st.nextToken();
StringTokenizer rm =new StringTokenizer(remainder,"'");
if (rm.countTokens() != 2) throw new MapperException("Invalid condition '" + cond + "'");
condEl.appendChild(XMLUtil.textElement(inResultDoc, "test", stripBlanks(rm.nextToken())));
condEl.appendChild(XMLUtil.textElement(inResultDoc, "RHSValue", rm.nextToken()));
}
else throw new MapperException("Invalid condition '" + cond + "' " + st.countTokens());
}
/**
*
* @param filt string filter; can only handle '=' conditions so far
* @param filtEl - filter element
* FIXME - drops any blanks from within the quoted string
*/
private void makeFilter(String filt,Element filtEl) throws MapperException
{
StringTokenizer st = new StringTokenizer(filt,"=' ");
if (st.countTokens() == 2)
{
filtEl.appendChild(XMLUtil.textElement(inResultDoc, "attribute", stripBlanks(st.nextToken())));
filtEl.appendChild(XMLUtil.textElement(inResultDoc, "value", st.nextToken()));
}
}
/**
*
* @param s a string
* @return the first non-blank substring
*/
private String stripBlanks(String s)
{
StringTokenizer st = new StringTokenizer(s," ");
return st.nextToken();
}
/**
*
* @param classSet class name, with or without subset in brackets
* @return class name
*/
private String className(String classSet)
{
StringTokenizer cs = new StringTokenizer(classSet,"()");
return cs.nextToken();
}
/**
*
* @param classSet class name, with or without subset in brackets
* @return subset ("" if no brackets)
*/
private String subset(String classSet)
{
String subset = "";
StringTokenizer cs = new StringTokenizer(classSet,"()");
if (cs.countTokens() == 2) {cs.nextToken();subset = cs.nextToken();}
return subset;
}
}