How can an interface be made for this code:
package com.ejada.alinma.edh.xsdtransform;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/*import org.apache.log4j.Logger;*/
import org.apache.log4j.PropertyConfigurator;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
/**
* An XSD Transformer that replaces the "name" attribute's value in T24 XSDs
* with the "shortname" attribute's value
*
* @author ahusseiny
*
*/
public class XSDTransformer {
/**
* constants representing the XSD tags and attributes' names used in the parse process
*/
public static final String TAG_SCHEMA = "xsd:schema";
public static final String TAG_TEXT = "#text";
public static final String TAG_COMPLEX_TYPE = "xsd:complexType";
public static final String TAG_SIMPLE_TYPE = "xsd:simpleType";
public static final String TAG_SEQUENCE = "xsd:sequence";
public static final String TAG_ATTRIBUTE = "xsd:attribute";
public static final String TAG_ELEMENT = "xsd:element";
public static final String TAG_ANNOTATION = "xsd:annotation";
public static final String TAG_APP_INFO = "xsd:appinfo";
public static final String TAG_HAS_PROPERTY = "xsd:hasProperty";
public static final String TAG_RESTRICTION = "xsd:restriction";
public static final String TAG_MAX_LENGTH = "xsd:maxLength";
public static final String ATTR_NAME = "name";
public static final String ATTR_VALUE = "value";
public static final String ATTR_TYPE = "type";
public static final String ATTR_MIXED = "mixed";
public static final String ATTR_USE = "use";
public static final String ATTR_REF = "ref";
public static final String ATTR_MAX_OCCURS = "maxOccurs";
/**
* constants representing specific XSD attributes' values used in the parse process
*/
public static final String FIELD_TAG = "fieldtag";
public static final String FIELD_NUMBER = "fieldnumber";
public static final String FIELD_DATA_TYPE = "fielddatatype";
public static final String FIELD_FMT = "fieldfmt";
public static final String FIELD_LEN = "fieldlen";
public static final String FIELD_INPUT_LEN = "fieldinputlen";
public static final String FIELD_GROUP_NUMBER = "fieldgroupnumber";
public static final String FIELD_MV_GROUP_NUMBER = "fieldmvgroupnumber";
public static final String FIELD_SHORT_NAME = "fieldshortname";
public static final String FIELD_NAME = "fieldname";
public static final String FIELD_COLUMN_NAME = "fieldcolumnname";
public static final String FIELD_GROUP_NAME = "fieldgroupname";
public static final String FIELD_MV_GROUP_NAME = "fieldmvgroupname";
public static final String FIELD_JUSTIFICATION = "fieldjustification";
public static final String FIELD_TYPE = "fieldtype";
public static final String FIELD_SINGLE_OR_MULTI = "singleormulti";
public static final String DELIMITER_COLUMN_TYPE = "#";
public static final String COLUMN_FK_ROW = "FK_ROW";
public static final String COLUMN_XPK_ROW = "XPK_ROW";
public static final int SQL_VIEW_MULTI = 1;
public static final int SQL_VIEW_SINGLE = 2;
public static final String DATA_TYPE_XSD_NUMERIC = "numeric";
public static final String DATA_TYPE_XSD_DECIMAL = "decimal";
public static final String DATA_TYPE_XSD_STRING = "string";
public static final String DATA_TYPE_XSD_DATE = "date";
/**
* application configuration properties
*/
public static final String PROP_LOG4J_CONFIG_FILE = "log4j_config";
public static final String PROP_MAIN_VIEW_NAME_SINGLE = "view_name_single";
public static final String PROP_MAIN_VIEW_NAME_MULTI = "view_name_multi";
public static final String PROP_MAIN_TABLE_NAME = "main_edh_table_name";
public static final String PROP_SUB_TABLE_PREFIX = "sub_table_prefix";
public static final String PROP_SOURCE_XSD_FULLNAME = "source_xsd_fullname";
public static final String PROP_RESULTS_PATH = "results_path";
public static final String PROP_NEW_XSD_FILENAME = "new_xsd_filename";
public static final String PROP_CSV_FILENAME = "csv_filename";
/**
* static holders for application-level utilities
*/
private static Properties appProps;
private static Logger appLogger;
/**
*
*/
private StringBuffer sqlViewColumnsSingle = null;
private StringBuffer sqlViewSelectSingle = null;
private StringBuffer columnsCSV = null;
private ArrayList<String> singleValueTableColumns = null;
private HashMap<String, String> multiValueTablesSQL = null;
private HashMap<Object, HashMap<String, Object>> groupAttrs = null;
public XSDTransformer(String appConfigPropsPath) {
if (appProps == null) {
appProps = new Properties();
}
try {
init(appConfigPropsPath);
} catch (Exception e) {
appLogger.error(e.getMessage());
}
}
/**
* initialization
*/
private void init(String appConfigPropsPath) throws Exception {
// init the properties object
FileReader in = new FileReader(appConfigPropsPath);
appProps.load(in);
// init the logger
if ((appProps.getProperty(XSDTransformer.PROP_LOG4J_CONFIG_FILE) != null)
&& (!appProps.getProperty(XSDTransformer.PROP_LOG4J_CONFIG_FILE).equals(""))) {
PropertyConfigurator.configure(appProps.getProperty(XSDTransformer.PROP_LOG4J_CONFIG_FILE));
if (appLogger == null) {
appLogger = Logger.getLogger(XSDTransformer.class.getName());
}
appLogger.info("Application initialization successful.");
}
sqlViewColumnsSingle = new StringBuffer();
sqlViewSelectSingle = new StringBuffer();
columnsCSV = new StringBuffer(XSDTransformer.FIELD_TAG + "," + XSDTransformer.FIELD_NUMBER + ","
+ XSDTransformer.FIELD_DATA_TYPE + "," + XSDTransformer.FIELD_FMT + "," + XSDTransformer.FIELD_LEN + ","
+ XSDTransformer.FIELD_INPUT_LEN + "," + XSDTransformer.FIELD_GROUP_NUMBER + ","
+ XSDTransformer.FIELD_MV_GROUP_NUMBER + "," + XSDTransformer.FIELD_SHORT_NAME + ","
+ XSDTransformer.FIELD_NAME + "," + XSDTransformer.FIELD_COLUMN_NAME + "," + XSDTransformer.FIELD_GROUP_NAME
+ "," + XSDTransformer.FIELD_MV_GROUP_NAME + "," + XSDTransformer.FIELD_JUSTIFICATION + ","
+ XSDTransformer.FIELD_TYPE + "," + XSDTransformer.FIELD_SINGLE_OR_MULTI + System.getProperty("line.separator"));
singleValueTableColumns = new ArrayList<String>();
singleValueTableColumns.add(XSDTransformer.COLUMN_XPK_ROW + XSDTransformer.DELIMITER_COLUMN_TYPE
+ XSDTransformer.DATA_TYPE_XSD_NUMERIC);
multiValueTablesSQL = new HashMap<String, String>();
groupAttrs = new HashMap<Object, HashMap<String, Object>>();
}
/**
* initialize the <code>DocumentBuilder</code> and read the XSD file
*
* @param docPath
* @return the <code>Document</code> object representing the read XSD file
*/
private Document retrieveDoc(String docPath) {
Document xsdDoc = null;
File file = new File(docPath);
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
xsdDoc = builder.parse(file);
} catch (Exception e) {
appLogger.error(e.getMessage());
}
return xsdDoc;
}
/**
* perform the iteration/modification on the document
* iterate to the level which contains all the elements (Single-Value, and Groups) and start processing each
*
* @param xsdDoc
* @return
*/
private Document transformDoc(Document xsdDoc) {
ArrayList<Object> newElementsList = new ArrayList<Object>();
HashMap<String, Object> docAttrMap = new HashMap<String, Object>();
Element sequenceElement = null;
Element schemaElement = null;
// get document's root element
NodeList nodes = xsdDoc.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
if (XSDTransformer.TAG_SCHEMA.equals(nodes.item(i).getNodeName())) {
schemaElement = (Element) nodes.item(i);
break;
}
}
// process the document (change single-value elements, collect list of new elements to be added)
for (int i1 = 0; i1 < schemaElement.getChildNodes().getLength(); i1++) {
Node childLevel1 = (Node) schemaElement.getChildNodes().item(i1);
// <ComplexType> element
if (childLevel1.getNodeName().equals(XSDTransformer.TAG_COMPLEX_TYPE)) {
// first, get the main attributes and put it in the csv file
for (int i6 = 0; i6 < childLevel1.getChildNodes().getLength(); i6++) {
Node child6 = childLevel1.getChildNodes().item(i6);
if (XSDTransformer.TAG_ATTRIBUTE.equals(child6.getNodeName())) {
if (child6.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME) != null) {
String attrName = child6.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME).getNodeValue();
if (((Element) child6).getElementsByTagName(XSDTransformer.TAG_SIMPLE_TYPE).getLength() != 0) {
Node simpleTypeElement = ((Element) child6).getElementsByTagName(XSDTransformer.TAG_SIMPLE_TYPE)
.item(0);
if (((Element) simpleTypeElement).getElementsByTagName(XSDTransformer.TAG_RESTRICTION).getLength() != 0) {
Node restrictionElement = ((Element) simpleTypeElement).getElementsByTagName(
XSDTransformer.TAG_RESTRICTION).item(0);
if (((Element) restrictionElement).getElementsByTagName(XSDTransformer.TAG_MAX_LENGTH).getLength() != 0) {
Node maxLengthElement = ((Element) restrictionElement).getElementsByTagName(
XSDTransformer.TAG_MAX_LENGTH).item(0);
HashMap<String, String> elementProperties = new HashMap<String, String>();
elementProperties.put(XSDTransformer.FIELD_TAG, attrName);
elementProperties.put(XSDTransformer.FIELD_NUMBER, "0");
elementProperties.put(XSDTransformer.FIELD_DATA_TYPE, XSDTransformer.DATA_TYPE_XSD_STRING);
elementProperties.put(XSDTransformer.FIELD_FMT, "");
elementProperties.put(XSDTransformer.FIELD_NAME, attrName);
elementProperties.put(XSDTransformer.FIELD_SHORT_NAME, attrName);
elementProperties.put(XSDTransformer.FIELD_COLUMN_NAME, attrName);
elementProperties.put(XSDTransformer.FIELD_SINGLE_OR_MULTI, "S");
elementProperties.put(XSDTransformer.FIELD_LEN, maxLengthElement.getAttributes().getNamedItem(
XSDTransformer.ATTR_VALUE).getNodeValue());
elementProperties.put(XSDTransformer.FIELD_INPUT_LEN, maxLengthElement.getAttributes()
.getNamedItem(XSDTransformer.ATTR_VALUE).getNodeValue());
constructElementRow(elementProperties);
// add the attribute as a column in the single-value table
singleValueTableColumns.add(attrName + XSDTransformer.DELIMITER_COLUMN_TYPE
+ XSDTransformer.DATA_TYPE_XSD_STRING + XSDTransformer.DELIMITER_COLUMN_TYPE
+ maxLengthElement.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE).getNodeValue());
// add the attribute as a column in the single-values view
sqlViewColumnsSingle.append(System.getProperty("line.separator") + attrName + ", ");
sqlViewSelectSingle.append(System.getProperty("line.separator") + attrName + ", ");
appLogger.debug("added attribute: " + attrName);
}
}
}
}
}
}
// now, loop on the elements and process them
for (int i2 = 0; i2 < childLevel1.getChildNodes().getLength(); i2++) {
Node childLevel2 = (Node) childLevel1.getChildNodes().item(i2);
// <Sequence> element
if (childLevel2.getNodeName().equals(XSDTransformer.TAG_SEQUENCE)) {
sequenceElement = (Element) childLevel2;
for (int i3 = 0; i3 < childLevel2.getChildNodes().getLength(); i3++) {
Node childLevel3 = (Node) childLevel2.getChildNodes().item(i3);
// <Element> element
if (childLevel3.getNodeName().equals(XSDTransformer.TAG_ELEMENT)) {
// check if single element or group
if (isGroup(childLevel3)) {
processGroup(childLevel3, true, null, docAttrMap, xsdDoc, newElementsList);
// insert a new comment node with the contents of the group tag
sequenceElement.insertBefore(xsdDoc.createComment(serialize(childLevel3)), childLevel3);
// remove the group tag
sequenceElement.removeChild(childLevel3);
} else {
processElement(childLevel3);
}
}
}
}
}
}
}
// add new elements
// this step should be after finishing processing the whole document. when you add new elements to the document
// while you are working on it, those new elements will be included in the processing. We don't need that!
for (int i = 0; i < newElementsList.size(); i++) {
sequenceElement.appendChild((Element) newElementsList.get(i));
}
// write the new required attributes to the schema element
Iterator<String> attrIter = docAttrMap.keySet().iterator();
while(attrIter.hasNext()) {
Element attr = (Element) docAttrMap.get(attrIter.next());
Element newAttrElement = xsdDoc.createElement(XSDTransformer.TAG_ATTRIBUTE);
appLogger.debug("appending attr. [" + attr.getAttribute(XSDTransformer.ATTR_NAME) + "]...");
newAttrElement.setAttribute(XSDTransformer.ATTR_NAME, attr.getAttribute(XSDTransformer.ATTR_NAME));
newAttrElement.setAttribute(XSDTransformer.ATTR_TYPE, attr.getAttribute(XSDTransformer.ATTR_TYPE));
schemaElement.appendChild(newAttrElement);
}
return xsdDoc;
}
/**
* check if the <code>element</code> sent is single-value element or group
* element. the comparison depends on the children of the element. if found one of type
* <code>ComplexType</code> then it's a group element, and if of type
* <code>SimpleType</code> then it's a single-value element
*
* @param element
* @return <code>true</code> if the element is a group element,
* <code>false</code> otherwise
*/
private boolean isGroup(Node element) {
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node child = (Node) element.getChildNodes().item(i);
if (child.getNodeName().equals(XSDTransformer.TAG_COMPLEX_TYPE)) { // found a ComplexType child (Group element)
return true;
} else if (child.getNodeName().equals(XSDTransformer.TAG_SIMPLE_TYPE)) { // found a SimpleType child (Single-Value element)
return false;
}
}
return false;
/*
String attrName = null;
if (element.getAttributes() != null) {
Node attribute = element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME);
if (attribute != null) {
attrName = attribute.getNodeValue();
}
}
if (attrName.startsWith("g")) { // group element
return true;
} else { // single element
return false;
}
*/
}
/**
* process a group element. recursively, process groups till no more group elements are found
*
* @param element
* @param isFirstLevelGroup
* @param attrMap
* @param docAttrMap
* @param xsdDoc
* @param newElementsList
*/
private void processGroup(Node element, boolean isFirstLevelGroup, Node parentGroup, HashMap<String, Object> docAttrMap,
Document xsdDoc, ArrayList<Object> newElementsList) {
String elementName = null;
HashMap<String, Object> groupAttrMap = new HashMap<String, Object>();
HashMap<String, Object> parentGroupAttrMap = new HashMap<String, Object>();
if (element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME) != null) {
elementName = element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME).getNodeValue();
}
appLogger.debug("processing group [" + elementName + "]...");
// get the attributes if a non-first-level-group
// attributes are: groups's own attributes + parent group's attributes
if (!isFirstLevelGroup) {
// get the current element (group) attributes
for (int i1 = 0; i1 < element.getChildNodes().getLength(); i1++) {
if (XSDTransformer.TAG_COMPLEX_TYPE.equals(element.getChildNodes().item(i1).getNodeName())) {
Node complexTypeNode = element.getChildNodes().item(i1);
for (int i2 = 0; i2 < complexTypeNode.getChildNodes().getLength(); i2++) {
if (XSDTransformer.TAG_ATTRIBUTE.equals(complexTypeNode.getChildNodes().item(i2).getNodeName())) {
appLogger.debug("add group attr: " + ((Element) complexTypeNode.getChildNodes().item(i2)).getAttribute(XSDTransformer.ATTR_NAME));
groupAttrMap.put(((Element) complexTypeNode.getChildNodes().item(i2)).getAttribute(XSDTransformer.ATTR_NAME), complexTypeNode.getChildNodes().item(i2));
docAttrMap.put(((Element) complexTypeNode.getChildNodes().item(i2)).getAttribute(XSDTransformer.ATTR_NAME), complexTypeNode.getChildNodes().item(i2));
}
}
}
}
// now, get the parent's attributes
parentGroupAttrMap = groupAttrs.get(parentGroup);
if (parentGroupAttrMap != null) {
Iterator<String> iter = parentGroupAttrMap.keySet().iterator();
while (iter.hasNext()) {
String attrName = iter.next();
groupAttrMap.put(attrName, parentGroupAttrMap.get(attrName));
}
}
// put the attributes in the attributes map
groupAttrs.put(element, groupAttrMap);
}
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node childLevel1 = (Node) element.getChildNodes().item(i);
if (childLevel1.getNodeName().equals(XSDTransformer.TAG_COMPLEX_TYPE)) {
for (int j = 0; j < childLevel1.getChildNodes().getLength(); j++) {
Node childLevel2 = (Node) childLevel1.getChildNodes().item(j);
if (childLevel2.getNodeName().equals(XSDTransformer.TAG_SEQUENCE)) {
for (int k = 0; k < childLevel2.getChildNodes().getLength(); k++) {
Node childLevel3 = (Node) childLevel2.getChildNodes().item(k);
if (childLevel3.getNodeName().equals(XSDTransformer.TAG_ELEMENT)) {
// check if single element or group
if (isGroup(childLevel3)) { // another group element..
// unfortunately, a recursion is
// needed here!!! :-(
processGroup(childLevel3, false, element, docAttrMap, xsdDoc, newElementsList);
} else { // reached a single-value element.. copy it under the
// main sequence and apply the name-shorname
// replacement
processGroupElement(childLevel3, element, isFirstLevelGroup, xsdDoc, newElementsList);
}
}
}
}
}
}
}
appLogger.debug("finished processing group [" + elementName + "].");
}
/**
* process the sent <code>element</code> to extract/modify required
* information:
* 1. replace the <code>name</code> attribute with the <code>shortname</code>.
*
* @param element
*/
private void processElement(Node element) {
String fieldShortName = null;
String fieldColumnName = null;
String fieldDataType = null;
String fieldFormat = null;
String fieldInputLength = null;
String elementName = null;
HashMap<String, String> elementProperties = new HashMap<String, String>();
if (element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME) != null) {
elementName = element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME).getNodeValue();
}
appLogger.debug("processing element [" + elementName + "]...");
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node childLevel1 = (Node) element.getChildNodes().item(i);
if (childLevel1.getNodeName().equals(XSDTransformer.TAG_ANNOTATION)) {
for (int j = 0; j < childLevel1.getChildNodes().getLength(); j++) {
Node childLevel2 = (Node) childLevel1.getChildNodes().item(j);
if (childLevel2.getNodeName().equals(XSDTransformer.TAG_APP_INFO)) {
for (int k = 0; k < childLevel2.getChildNodes().getLength(); k++) {
Node childLevel3 = (Node) childLevel2.getChildNodes().item(k);
if (childLevel3.getNodeName().equals(XSDTransformer.TAG_HAS_PROPERTY)) {
if (childLevel3.getAttributes() != null) {
String attrName = null;
Node attribute = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME);
if (attribute != null) {
attrName = attribute.getNodeValue();
elementProperties.put(attrName, childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue());
if (attrName.equals(XSDTransformer.FIELD_SHORT_NAME)) {
fieldShortName = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue();
} else if (attrName.equals(XSDTransformer.FIELD_COLUMN_NAME)) {
fieldColumnName = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue();
} else if (attrName.equals(XSDTransformer.FIELD_DATA_TYPE)) {
fieldDataType = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue();
} else if (attrName.equals(XSDTransformer.FIELD_FMT)) {
fieldFormat = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue();
} else if (attrName.equals(XSDTransformer.FIELD_INPUT_LEN)) {
fieldInputLength = childLevel3.getAttributes().getNamedItem(XSDTransformer.ATTR_VALUE)
.getNodeValue();
}
}
}
}
}
}
}
}
}
if (element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME) != null) {
element.getAttributes().getNamedItem(XSDTransformer.ATTR_NAME).setNodeValue(fieldShortName);
}
sqlViewColumnsSingle.append(System.getProperty("line.separator") + fieldColumnName + ", ");
sqlViewSelectSingle.append(System.getProperty("line.separator") + fieldShortName + ", ");
elementProperties.put(XSDTransformer.FIELD_SINGLE_OR_MULTI, "S");
constructElementRow(elementProperties);
singleValueTableColumns.add(fieldShortName + XSDTransformer.DELIMITER_COLUMN_TYPE + fieldDataType + fieldFormat
+ XSDTransformer.DELIMITER_COLUMN_TYPE + fieldInputLength);
appLogger.debug("finished processing element [" + elementName + "].");
}
/**
* process the sent <code>element</code> to extract/modify required
* information:
* 1. copy the element under the main sequence
* 2. replace the <code>name</code> attribute with the <code>shortname</code>.
* 3. add the attributes of the parent groups (if non-first-level-group)
*
* @param element
*/
private void proc