Capstone Project Group #3 The TieFlow WorkFlow ToolKit Process Definition XML

DEMO 1 Date: April 5, 2007 Venue: Tietronix Inc.

Members:

Jigyasa Dubey Plabita Baruah Preetha Boisen Paul Sarjana Singh

Instructor: Dr.Kwok Bun Yue

Mentors: Mr. Scott Hetherington Mr. Abbasi Dhilawa

1 Contents 1. Use case diagram ……………………………………………………………

2. Class Diagram ………………………………………………………………

3. Activity Diagram ……………………………………………………………

4. Sequence Diagram ………………………………………………………….

5. Mapping File 5.1. Mapping.xls ……………………………………………………………

6. Configuration File 6.1. TieFlow-XpdlTransformation.xml ……………………………………

7. Source Code 6.0 TieflowXmlConverter.java 7.1. XMLTranslator.java …………………………………………………….. 7.2. XMLTranslatorUtility.java ……………………………………………… 7.3. NodeTranslator.java ……………………………………………………… 7.4. ElementToElementTranslator.java ………………………………………. 7.5. ElementToAttributeTranslator.java ………………………………………. 7.6. AttributeToElementTranslator.java ………………………………………. 7.7. AttributeToAttributeTranslator.java ………………………………………

8. Test Run and sample output

2 Use Case Diagram

Translate User

Class Diagram

3. Activity Diagram :

3 User

Select Files

Select XML Select File Configuration XML

Translate XML File to String

Parse XML File

Create Hash Maps

Translate Node

Output XML

Validate

4 xmltranslator : translatorutil:XMLTranslatorUtility nodetranslator:NodeTranslator new() : new():ElementtoElementTran new() : new() : XMLTranslator : XMLTranslatorUtility : NodeTranslator ElementtoElementTranslator slator : ElementtoAttribute AttriuttoElement AttributetoAttribute : User translatexmlfiletostring( )

translate( )

translatorutil( )

void( )

translateNode( )

createlastNode( )

void( )

createlastNode( )

void( )

createlastNode( )

void( )

createlastNode( )

void( )

void( )

Sequence Diagram

Configuration File

File name: TieFlow-XpdlTransformation.xml

Package Package::Role Package::Lane Package::Role::id Package::Lane::id Package::Role::name Package::Lane::name Package::Process Package::WorkFlowProcess Package::Process::id Package::WorkFlowProcess::id Package::Process::name Package::WorkFlowProcess::name

5 Package::Process::(empty) Package::WorkFlowProcess::ProcessHeader Package::Process::timeUnit Package::WorkFlowProcess::ProcessHeader::DurationUnit Package::RulesFileReference Package::Association Package::RulesFileReference::rulesFileId Package::Association::Id Package::RulesFile Package::Artifact Package::RulesFile::id Package::Artifact::Id Package::RulesFile::type Package::Artifact::Name Package::ContentDataSection Package::DataFields Package::ContentDataSection::ContentDataSectionField Package::DataFields::DataField Package::ContentDataSection::ContentDataSectionField::id Package::DataFields::DataField::Id Package::ContentDataSection::ContentDataSectionField::name Package::DataFields::DataField::Name Package::ContentDataSection::ContentDataSectionField::dataType Package::DataFields::DataField::DataType Package::ContentDataSection::ContentDataSectionField::size Package::DataFields::DataField::Length

TieflowXmlConverter.java [ Main GUI program ]

import java.io.*; import java.awt.*;

6 import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.*; public class TieflowXmlConverter extends JPanel implements ActionListener { static private final String newline = "\n"; JButton openButton, outButton, saveButton; JTextArea log; JFileChooser fc; //, fc_out; JLabel lblFilePath; JLabel lblHeader;

public TieflowXmlConverter() { super(new BorderLayout());

//Create the log first, because the action listeners //need to refer to it. log = new JTextArea(5,20); log.setMargin(new Insets(10,10,10,10)); log.setEditable(false); JScrollPane logScrollPane = new JScrollPane(log);

//Create a file chooser fc = new JFileChooser(); //fc_out = new JFileChooser(); //fc_out.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

openButton = new JButton("Get Tietronix XML..."); openButton.addActionListener(this);

outButton = new JButton("Output XML Location..."); outButton.addActionListener(this);

saveButton = new JButton("Translate to XPDL..."); saveButton.addActionListener(this);

//For layout purposes, put the buttons in a separate panel JPanel buttonPanel = new JPanel(); //use FlowLayout buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); buttonPanel.add(openButton); buttonPanel.add(outButton); buttonPanel.add(saveButton);

lblHeader = new JLabel("Tietronix XML Transformer"); lblFilePath = new JLabel("XML File path to be displayed here kjhkjhjhjh");

//Add the buttons and the log to this panel. add(lblHeader, BorderLayout.PAGE_START); add(buttonPanel, BorderLayout.CENTER); add(logScrollPane, BorderLayout.LINE_END); add(lblFilePath, BorderLayout.PAGE_END);

setBackground(Color.green); }

public void actionPerformed(ActionEvent e) {

//Handle open button action. if (e.getSource() == openButton) { int returnVal = fc.showOpenDialog(TieflowXmlConverter.this);

if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile();

log.append("Opening: " + file.getName() + "." + newline); lblFilePath.setText(file.getPath());

7 } else { log.append("Open command cancelled by user." + newline); } log.setCaretPosition(log.getDocument().getLength());

} else if (e.getSource() == outButton) {

/* int returnVal = fc.showOpenDialog(TieflowXmlConverter.this);

if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc_out.getSelectedFile();

log.append("Opening: " + file.getName() + "." + newline); lblFilePath.setText(file.getPath()); } else { log.append("Open command cancelled by user." + newline); } log.setCaretPosition(log.getDocument().getLength()); */

} //Handle save button action. else if (e.getSource() == saveButton) {

log.append("Translating to XPDL standard. Please wait." + newline);

XMLTranslator translater = new XMLTranslator(); String OutputXMLString = translater.translateXMLFileToString(lblFilePath.getText(), "C:\\Capstone\\TieFlow-XpdlTransformation.xml"); System.out.println(OutputXMLString); translater.WriteOutputXMLStringToXMLFile(OutputXMLString, lblFilePath.getText());

log.append("Translated to c:\\Capstone\\output_file.xml." + newline);

log.setCaretPosition(log.getDocument().getLength()); } }

/** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("TieflowXmlConverter"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane. JComponent newContentPane = new TieflowXmlConverter(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane);

//Display the window. frame.pack(); frame.setVisible(true); }

public static void main(String[] args) { //Schedule a job for the event-dispatching thread:

8 //creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } XMLTranslator.java import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.io.FileOutputStream; import java.io.PrintStream; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.traversal.DocumentTraversal; import org.w3c.dom.traversal.NodeFilter; import org.w3c.dom.traversal.NodeIterator; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

/** * @author BPaul * Created: Mar 15, 2007 */ public class XMLTranslator { protected DocumentBuilderFactory _docBuilderFactory; protected HashMap _configNamesToConfigNodesMap; protected HashMap _configNamesXrefMap; protected XMLTranslatorUtility _translatorUtil;

/* This method reads the contents of input XML file as a string and the configuration * file and translates it * to output XML based upon the configuration file. The output XML is returned in a * string format */ public String translateXMLStringToString(String inputXml, String configFileName){ try{ InputSource inXmlSource = new InputSource(new StringReader(inputXml)); FileInputStream configFis = new FileInputStream(new File(configFileName)); String outXml = translate(inXmlSource.getByteStream(), configFis); configFis.close(); return outXml; } catch(FileNotFoundException ex){ ex.printStackTrace(); } catch(IOException ex){

9 ex.printStackTrace(); } return ""; }

/* This method reads the contents of input XML file given the input file name and the * configuration file and translates it to output XML based upon the configuration file. * The output XML is returned in a string format */ public String translateXMLFileToString(String inputXmlFile, String configFileName){ try{ //read from the input XML file FileInputStream fis = new FileInputStream(new File(inputXmlFile)); //read from the configuration file FileInputStream configFis = new FileInputStream(new File(configFileName)); String outXml = translate(fis, configFis);

fis.close(); configFis.close(); return outXml; } catch(FileNotFoundException ex){ ex.printStackTrace(); } catch(IOException ex){ ex.printStackTrace(); }

return ""; }

/* This method reads from the given input file as a string. It checks the configuration file given the * the configuration file name, translates the XML file and writes it to the output file * given the output file name */

public String translateXMLStringToFile(String inputXml, String configFileName, String outputFile){ try{ InputSource inXmlSource = new InputSource(new StringReader(inputXml)); FileInputStream configFis = new FileInputStream(new File(configFileName)); String outXml = translate(inXmlSource.getByteStream(), configFis); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(outputFile)))); out.writeChars(outXml); out.close(); configFis.close(); return outXml; } catch(FileNotFoundException ex){ ex.printStackTrace(); } catch(IOException ex){ ex.printStackTrace(); } return ""; }

/* This method reads the from the given input file. It checks the configuration file given the * the configuration file name, translates the XML file and writes it to the output file * given the output file name */ public String translateXMLFileToFile(String inputXmlFile, String configFileName, String outputFile){ try{ FileInputStream fis = new FileInputStream(new File(inputXmlFile)); FileInputStream configFis = new FileInputStream(new File(configFileName)); String outXml = translate(fis, configFis); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(outputFile)))); out.writeChars(outXml); out.close();

10 fis.close(); configFis.close(); return outXml; } catch(FileNotFoundException ex){ ex.printStackTrace(); } catch(IOException ex){ ex.printStackTrace(); }

return ""; }

/*The private utility method to parse the input XML file and do the actual translation */ private String translate(InputStream inputXmlStream, InputStream configXmlStream){ try{

DocumentBuilder docBuilder = getDocBuilderFactory().newDocumentBuilder(); getDocBuilderFactory().setValidating(true); Document inputDoc = docBuilder.parse(inputXmlStream); System.out.println(" Successfully parsed the input XML");

getDocBuilderFactory().setValidating(false); docBuilder = getDocBuilderFactory().newDocumentBuilder();

//parse the configuration file Document configDoc = docBuilder.parse(configXmlStream);

//create an empty output document Document outputDoc = docBuilder.newDocument();

//create and append root element for the output document Element root = createRoot(inputDoc.getDocumentElement(), configDoc, outputDoc); root.appendChild(outputDoc.createTextNode("\n")); outputDoc.appendChild(root);

//get the instance of XMLTranslatorUtility class and call its method getTranslatorUtil().loadConfigXml(configDoc);

translateNodes(inputDoc, outputDoc.getDocumentElement());

StringWriter writer = new StringWriter(); XMLSerializer serializer = new XMLSerializer(writer,null); serializer.serialize(outputDoc); writer.close();

return writer.toString(); } catch(ParserConfigurationException ex){ System.out.println("Parser not configured...."); ex.printStackTrace(); } catch(SAXException ex){ System.out.println("Input XML has parse errors...."); ex.printStackTrace(); } catch(IOException ex){ System.out.println("Error reading input XML...."); ex.printStackTrace(); } return null; }

/* This private helper method is used to create the root element for the output * XML document generated. */ private Element createRoot(Element inRoot, Document configDoc, Document outDoc){

11 //the root node of the input XML document NodeList list = configDoc.getElementsByTagName("RootNodeName");

String configRootName = getTranslatorUtil().getElementTextContent((Element)list.item(0));

if(list.getLength() > 1 && configRootName.equals(inRoot.getTagName())){ configRootName = getTranslatorUtil().getElementTextContent((Element)list.item(1)); }

return outDoc.createElement(configRootName); } private void translateNodes(Document inDoc, Element outRoot){ DocumentTraversal traversable = (DocumentTraversal) inDoc; NodeIterator iterator = traversable.createNodeIterator(inDoc, NodeFilter.SHOW_ALL, null, true);

Node node; while((node = iterator.nextNode()) != null) { if(node.getNodeType() == Node.ELEMENT_NODE){ translateNode(node, outRoot); NamedNodeMap attrNodes = node.getAttributes(); for(int i = 0; i < attrNodes.getLength(); i++){ Attr attr = (Attr) attrNodes.item(i); translateNode(attr, outRoot); } } } } private void translateNode(Node inNode, Element outRoot){ String fullyQualifiedNodeName = getTranslatorUtil().getFullyQualifiedNodeName(inNode); String outNodeName = getTranslatorUtil().getCorrespondingConfigName(fullyQualifiedNodeName); if(outNodeName != null){ Element configElement = getTranslatorUtil().getConfigElement(outNodeName); NodeTranslator translator = createNewTranslator(configElement); translator.translateNode(inNode, outRoot, configElement); } } private NodeTranslator createNewTranslator(Element configElement){ String className = configElement.getAttribute("translatorClassName"); try{ NodeTranslator tran = (NodeTranslator)Class.forName(className).newInstance(); tran.setTranslatorUtil(getTranslatorUtil()); return tran; } catch(InstantiationException e) { e.printStackTrace(); throw new RuntimeException(e); } catch (IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException(e); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException(e); } }

/* Protected helper method to get an instance of the XMLTranslatorUtility class * This XMLTranslatorUtility class is a helper class. */ protected XMLTranslatorUtility getTranslatorUtil() {

if(_translatorUtil == null){ _translatorUtil = new XMLTranslatorUtility(); } return _translatorUtil; }

12 private DocumentBuilderFactory getDocBuilderFactory() { if(_docBuilderFactory == null){ _docBuilderFactory = DocumentBuilderFactory.newInstance(); _docBuilderFactory.setIgnoringComments(true); } return _docBuilderFactory; }

public void WriteOutputXMLStringToXMLFile( String OutputXMLString, String InFileName ) { FileOutputStream out; // declare a file output object PrintStream p; // declare a print stream object

try { // Create a new file output stream // connected to "output_file.xml" out = new FileOutputStream("output_file.xml");

// Connect print stream to the output stream p = new PrintStream( out );

p.println ( OutputXMLString );

p.close(); } catch (Exception e) { System.err.println ("Error writing to file"); } }

public boolean IsFileValid( String strInputFile ) { File xmlInputFile = new File(strInputFile); if (xmlInputFile.exists()) { return false; } // the file exists else { return true; } // the file does not exist }

} XMLTranslatorUtility.java import java.util.HashMap; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class XMLTranslatorUtility {

//Hash map that has the protected HashMap _configNamesToConfigNodesMap; protected HashMap _configNamesXrefMap;

public void loadConfigXml(Document configDoc){

_configNamesToConfigNodesMap = new HashMap(); _configNamesXrefMap = new HashMap();

//get all the Elements in document with a given tag name NodeList list = configDoc.getElementsByTagName("NodeName"); for(int i = 0; i < list.getLength(); i++){ Element element = (Element) list.item(i);

13 String configName = getElementTextContent(element); if(configName.trim().length() > 0){ _configNamesToConfigNodesMap.put(configName, element); NodeList siblings = ((Element)element.getParentNode()).getElementsByTagName("NodeName"); Element sibling = (Element) siblings.item(0); String siblingConfigName = getElementTextContent(sibling); //if more than one and the fuly qualified name is same as 0th Ele //then sibling is the next one if(siblings.getLength() > 1 && siblingConfigName.equals(configName)){ sibling = (Element) siblings.item(1); siblingConfigName = getElementTextContent(sibling); } _configNamesXrefMap.put(configName, siblingConfigName); } } } public String getElementTextContent(Element ele){

NodeList list = ele.getChildNodes(); for(int i = 0; i < list.getLength(); i++){ Node child = (Node) list.item(i); if(child.getNodeType() == Node.TEXT_NODE){ return child.getNodeValue(); } } return ""; } public Element getConfigElement(String configName){ return (Element)_configNamesToConfigNodesMap.get(configName); } public String getCorrespondingConfigName(String configName){ return (String)_configNamesXrefMap.get(configName); }

/* This method helps to find the fully qualified name of a particular node * that occurs in the input DOM tree */ public String getFullyQualifiedNodeName(Node node){

Node parentNode = null; //check if the current node is an attrubute node or an element node if(node.getNodeType() == Node.ATTRIBUTE_NODE){ parentNode = ((Attr)node).getOwnerElement(); } else{ parentNode = node.getParentNode(); } String fullyQualifiedNodeName = node.getNodeName(); //continue adding the parent nodes to make the fully qualified node name while(parentNode.getNodeType() == Node.ELEMENT_NODE) { fullyQualifiedNodeName = parentNode.getNodeName() + "::" + fullyQualifiedNodeName; parentNode = parentNode.getParentNode(); } return fullyQualifiedNodeName; } public Element getCorrespondingConfigElement(Element element){ String correspondingName = (String) getCorrespondingConfigName(getElementTextContent(element)); return getConfigElement(correspondingName); } public String getCorrespondingAttributeName(Attr attr){ String fullyQualifiedNodeName = getFullyQualifiedNodeName(attr); String correspoindingConfigName = getCorrespondingConfigName(fullyQualifiedNodeName); if(correspoindingConfigName.indexOf("::") != -1){ return correspoindingConfigName.substring(correspoindingConfigName.lastIndexOf("::") + 2);

14 }

return ""; } } NodeTranslator.java import java.util.Vector; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public abstract class NodeTranslator{ protected Vector _nodeNames; protected Node _inputNode; protected Element _configElement; protected XMLTranslatorUtility _translatorUtil;

public void translateNode(Node inputNode, Node outRoot, Element configElement) { createNodeNames(configElement); setConfigElement(configElement); setInputNode(inputNode); createNodesRecursive(outRoot, 1); // 1st element is root which is already created }

protected boolean createNodesRecursive(Node parentNode, int index) { Node next = parentNode.getFirstChild(); while(next != null) { if(next.getNodeType() == Node.ELEMENT_NODE && next.getNodeName().equals(getNodeNames().get(index))){ if(index == getNodeNames().size() - 1){ boolean isCreated = createLastNode(parentNode); if(isCreated){ return true; //else continue with next sibling } } else{ int temp = index + 1; boolean isCreated = createNodesRecursive(next, temp); if(isCreated){ return true; //else continue with next sibling } } } next = next.getNextSibling(); } return createElementsFrom(index, parentNode); }

protected boolean isOnlyOneAllowed(int index){ String name = (String)getNodeNames().get(index); index--; while(index >= 0){ name = (String)getNodeNames().get(index) + "::" + name; index--; } Attr cardinality = null; if(getTranslatorUtil().getConfigElement(name) != null){ cardinality = getTranslatorUtil().getConfigElement(name).getAttributeNode("onlyOne"); } return cardinality != null && cardinality.getValue().equals("true"); }

protected boolean isLastNodeAttribute(){ return false; }

15 protected Element createElement(Node parent, int index){ String nodeName = (String)getNodeNames().get(index); Element element = parent.getOwnerDocument().createElement(nodeName); return element; } protected boolean createElementsFrom(int index, Node parent){ while(index < getNodeNames().size() - 1){//last node will be create by subclass Element temp = createNewElementsForParent(parent, index); if(temp == null){ return false; } //parent.appendChild(parent.getOwnerDocument().createTextNode("\n")); parent = temp; index++; } return createLastNode(parent); } protected Element createNewElementsForParent(Node parent, int index){ Attr cardinality = getConfigElement().getAttributeNode("onlyOne"); if(!isOnlyOneAllowed(index)){ return createNewElement(parent, index); } else{ String nodeName = (String)getNodeNames().get(index); Element parentEle = (Element) parent.getParentNode(); NodeList list = parentEle.getElementsByTagName(parent.getNodeName()); for(int i = 0; i < list.getLength(); i++){ Element element = (Element) list.item(i); if(element.getElementsByTagName(nodeName).getLength() == 0 && isMatchesWithInputParent(element)){ return createNewElement(element, index); } } } return null; } protected Element createNewElement(Node parent, int index){ Element element = createElement(parent, index); parent.appendChild(element); String emptyTag = getTranslatorUtil().getElementTextContent(getConfigElement()) + "::(empty)"; String childNodeName = getTranslatorUtil().getCorrespondingConfigName(emptyTag); if(childNodeName != null){ childNodeName = childNodeName.substring(childNodeName.indexOf("::") + 2); Element child = element.getOwnerDocument().createElement(childNodeName); element.appendChild(child); } parent.appendChild(parent.getOwnerDocument().createTextNode("\n")); return element; } protected boolean isMatchesWithInputParent(Element element){ Element inputParent = (Element)getInputNode().getParentNode(); NamedNodeMap newAttrNodes = element.getAttributes(); for(int i = 0; i < newAttrNodes.getLength(); i++){ Attr newAttr = (Attr) newAttrNodes.item(i); Attr inputAttr = inputParent.getAttributeNode(getTranslatorUtil().getCorrespondingAttributeName(newAttr)); if(inputAttr == null || !inputAttr.getValue().equals(newAttr.getValue())){ return false; } } return true; } protected abstract boolean createLastNode(Node parent);

16 protected void createNodeNames(Element configElement){ String nameString = getTranslatorUtil().getElementTextContent(configElement); _nodeNames = new Vector(); while(nameString.indexOf("::") != -1){ _nodeNames.add(nameString.substring(0, nameString.indexOf("::"))); nameString = nameString.substring(nameString.indexOf("::") + 2); } if(nameString.length() > 0){ _nodeNames.add(nameString); } }

protected Vector getNodeNames(){ return _nodeNames; }

protected Node getInputNode() { return _inputNode; }

protected void setInputNode(Node node) { _inputNode = node; }

protected Element getConfigElement() { return _configElement; }

protected void setConfigElement(Element element) { _configElement = element; } public XMLTranslatorUtility getTranslatorUtil() { return _translatorUtil; } public void setTranslatorUtil(XMLTranslatorUtility aTranslatorUtil) { _translatorUtil = aTranslatorUtil; } } ElementToElementTranslator.java import org.w3c.dom.Element; import org.w3c.dom.Node; public class ElementToElementTranslator extends NodeTranslator {

protected boolean createLastNode(Node parent){ Element element = createNewElementsForParent(parent, getNodeNames().size() - 1); if(element != null){ String text = getTranslatorUtil().getElementTextContent((Element) getInputNode()).trim(); if(text.length() > 0){ Node node = parent.getOwnerDocument().createTextNode(text); element.appendChild(node); } return true; } else{ return false; } } } ElementToAttributeTranslator.java import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList;

17 public class ElementToAttributeTranslator extends NodeTranslator { public boolean createLastNode(Node parent){ String lastNodeName = (String)getNodeNames().lastElement(); Element parentEle = (Element) parent.getParentNode(); NodeList list = parentEle.getElementsByTagName(parent.getNodeName()); String text = getTranslatorUtil().getElementTextContent((Element) getInputNode()).trim(); for(int i = 0; i < list.getLength(); i++){ Element element = (Element) list.item(i); if(element.getAttributeNode(lastNodeName) == null){ element.setAttribute(lastNodeName, text); return true; } } return false; }

protected boolean isLastNodeAttribute(){ return true; } } AttributeToAttributeTranslator.java import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class AttributeToAttributeTranslator extends NodeTranslator {

protected boolean createLastNode(Node parent){ String lastNodeName = (String)getNodeNames().lastElement(); Element parentEle = (Element) parent.getParentNode(); NodeList list = parentEle.getElementsByTagName(parent.getNodeName()); for(int i = 0; i < list.getLength(); i++){ Element element = (Element) list.item(i); if(element.getAttributeNode(lastNodeName) == null && isMatchesWithInputParent(element)){ element.setAttribute(lastNodeName, ((Attr)getInputNode()).getValue()); return true; } } return false; }

protected boolean isMatchesWithInputParent(Element element){ Element inputParent = ((Attr)getInputNode()).getOwnerElement(); NamedNodeMap newAttrNodes = element.getAttributes(); for(int i = 0; i < newAttrNodes.getLength(); i++){ Attr newAttr = (Attr) newAttrNodes.item(i); Attr inputAttr = inputParent.getAttributeNode(getTranslatorUtil().getCorrespondingAttributeName(newAttr)); if(inputAttr == null || !inputAttr.getValue().equals(newAttr.getValue())){ return false; } }

return true; }

protected boolean isLastNodeAttribute(){ return true; } } AttributeToElementTranslator.java import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node;

18 public class AttributeToElementTranslator extends NodeTranslator {

protected boolean createLastNode(Node parent) { Element element = createElement(parent, getNodeNames().size() - 1); Node node = parent.getOwnerDocument().createTextNode(((Attr)getInputNode()).getValue()); element.appendChild(node); parent.appendChild(element); String emptyTag = getTranslatorUtil().getElementTextContent(getConfigElement()) + "::(empty)"; String childNodeName = getTranslatorUtil().getCorrespondingConfigName(emptyTag); if(childNodeName != null){ childNodeName = childNodeName.substring(childNodeName.indexOf("::") + 2); Element child = element.getOwnerDocument().createElement(childNodeName); element.appendChild(child); } parent.appendChild(parent.getOwnerDocument().createTextNode("\n")); return true; } } TEST RUN Sample input XML file: BPSCM.xml

Sample output : output_file.xml

c:/Projects/SDA/rules/rules_3.1.drl c:/Projects/SDA/rules/rules_role.drl

19

20

21

22

23

24

25

26