/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*******************************************************************************/
package org.ebayopensource.turmeric.tools.library.builders;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.ebayopensource.turmeric.runtime.common.impl.internal.config.DomParseUtils;
import org.ebayopensource.turmeric.runtime.common.impl.utils.CallTrackingLogger;
import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager;
import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException;
import org.ebayopensource.turmeric.tools.codegen.external.WSDLUtil;
import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil;
import org.ebayopensource.turmeric.tools.library.TypeLibraryConstants;
import org.ebayopensource.turmeric.tools.library.utils.AdditionalXSDInformation;
import org.ebayopensource.turmeric.tools.library.utils.TypeLibraryUtilities;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
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;
public class EpisodeGenerator {
private static CallTrackingLogger logger = LogManager
.getInstance(EpisodeGenerator.class);
private static CallTrackingLogger getLogger() {
return logger;
}
public EpisodeGenerator() {
}
public static String getJavaClassName(String episodeFilePath) {
Element topLevel = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document result = null;
String javaClassName = null;
// TODO: schema validation of the XML file against the
// TypeInformation.xsd
try {
DocumentBuilder builder = factory.newDocumentBuilder();
result = builder.parse(episodeFilePath);
topLevel = result.getDocumentElement();
// System.out.println("Top Level Element = " + topLevel);
NodeList bindings = DomParseUtils.getImmediateChildrenByTagName(
topLevel, "bindings");
for (int i = 0; i < bindings.getLength(); i++) {
Element bindingsElement = (Element) bindings.item(i);
String bindingsNodeName = bindingsElement.getNodeName();
// System.out.println("Child Element = " + bindingsElement);
if (bindingsNodeName.equals("bindings")) {
NodeList bindingsChildList = DomParseUtils
.getImmediateChildrenByTagName(bindingsElement,
"bindings");
for (int j = 0; j < bindingsChildList.getLength(); j++) {
Element bindingsChildElement = (Element) bindingsChildList
.item(j);
String bindingsChildNode = bindingsChildElement
.getNodeName();
// System.out.println("Child Element = " + topLevel);
if (bindingsNodeName.equals("bindings")) {
NodeList classList = DomParseUtils
.getImmediateChildrenByTagName(
bindingsChildElement, "class");
for (int k = 0; k < classList.getLength(); k++) {
Element classElement = (Element) classList
.item(j);
String classNode = classElement.getNodeName();
javaClassName = classElement
.getAttribute("ref");
// System.out.println("Class Node = " +
// classNode);
}
}
}
}
}
} catch (Exception e) {
getLogger().log(Level.SEVERE, e.getMessage());
// throw e;
}
return javaClassName;
}
public static void genSunJaxbEpisodeFile(String epsiodeFileLocation,
List<String> xsdTypes, String sunJaxbEpisodeSrcpath, Map<String, String> typesVersion,
ArrayList<AdditionalXSDInformation> simpleTypesAdditionalXSDInfo) {
getLogger().entering();
HashSet nameSpaceList = new HashSet();
HashSet<String> typesAddedInMasterEpisode = new HashSet<String>();
Document dom = null;
boolean headerBindingAdded = false;
Element bindingsElement = null;
// remove .xsd from the type names
for (int i = 0; i < xsdTypes.size(); i++) {
String temp = xsdTypes.get(i);
temp = temp.substring(0, temp.indexOf("."));
xsdTypes.set(i, temp);
}
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// get an instance of builder
DocumentBuilder db = dbf.newDocumentBuilder();
// create an instance of DOM
dom = db.newDocument();
// bindings root element
Element root = dom.createElement("bindings");
root.setAttribute("version", "2.1");
root.setAttribute("xmlns", "http://java.sun.com/xml/ns/jaxb");
dom.appendChild(root);
// create comment
Comment commentNode = dom
.createComment("Generated File. Any changes will lost upon regeneration");
root.appendChild(commentNode);
commentNode = dom.createComment(TypeLibraryConstants.MASTER_EPISODE_TURMERIC_START_COMMNENT);
root.appendChild(commentNode);
// Parsing DOM
DocumentBuilderFactory dbfForParser = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilderForParser = dbfForParser.newDocumentBuilder();
String[] episodeFiles = TypeLibraryUtilities.getFilesInDir(
epsiodeFileLocation, ".episode");
for (int k = 0; k < episodeFiles.length; k++) {
String episodeFileName = episodeFiles[k];
String episodeSrc = epsiodeFileLocation + File.separator
+ episodeFileName;
Document doc = null;
FileInputStream inputStream = null;
try{
inputStream = new FileInputStream(episodeSrc);
doc = documentBuilderForParser.parse(inputStream);
}finally{
CodeGenUtil.closeQuietly(inputStream);
}
// NodeList schemas = doc.getElementsByTagName("bindings");
NodeList rootNode = doc.getDocumentElement().getChildNodes();
// System.out.println("Child Nodes for the bindings element = "
// + doc.getDocumentElement().getChildNodes());
for (int j = 0; j < rootNode.getLength(); j++) {
Node childNode = rootNode.item(j);
String nameSpaceDoc = "";
String childNodeName = childNode.getNodeName();
if (childNodeName.indexOf("bindings") >= 0) {
NodeList childNodeL1 = childNode.getChildNodes();
// childNodeL1.getAttributes().getNamedItem("scd").getNodeValue()
nameSpaceDoc = childNode.getAttributes().getNamedItem(
"xmlns:tns").getNodeValue();
if (!nameSpaceList.contains(nameSpaceDoc)) {
// Add the namespace to the hash set
nameSpaceList.add(nameSpaceDoc);
headerBindingAdded = true;
// create bindings element
bindingsElement = dom.createElement("bindings");
bindingsElement
.setAttribute("scd", "x-schema::tns");
bindingsElement.setAttribute("xmlns:tns",
nameSpaceDoc);
root.appendChild(bindingsElement);
// create schemaBindings element
Element schemaBindingsElement = dom
.createElement("schemaBindings");
schemaBindingsElement.setAttribute("map", "true");
bindingsElement.appendChild(schemaBindingsElement);
addChild(childNodeL1, bindingsElement, dom,
typesAddedInMasterEpisode,
xsdTypes,typesVersion);
} else {
Node parentNode = getParentNode(dom, nameSpaceDoc);
addChild(childNodeL1, parentNode, dom,
typesAddedInMasterEpisode,
xsdTypes,typesVersion);
}
}
}
}
// This a code tweak to add the binding for simple types , since XJC does not generate the binding for simple types even
// when it creates the corresponding java type.
boolean areBindingsToBeAddedManuallyForSimpleTypes = false;
if (simpleTypesAdditionalXSDInfo != null && simpleTypesAdditionalXSDInfo.size() > 0){
for(AdditionalXSDInformation simpleInformation : simpleTypesAdditionalXSDInfo){
if(simpleInformation.isJavaFileGenerated()){
areBindingsToBeAddedManuallyForSimpleTypes = true;
}
}
}
if(areBindingsToBeAddedManuallyForSimpleTypes){
String nameSpace = simpleTypesAdditionalXSDInfo.get(0).getTargetNamespace();
if(!headerBindingAdded){
// create bindings element
bindingsElement = dom.createElement("bindings");
bindingsElement
.setAttribute("scd", "x-schema::tns");
bindingsElement.setAttribute("xmlns:tns",
nameSpace);
root.appendChild(bindingsElement);
// create schemaBindings element
Element schemaBindingsElement = dom
.createElement("schemaBindings");
schemaBindingsElement.setAttribute("map", "true");
bindingsElement.appendChild(schemaBindingsElement);
}
for(int i=0;i<simpleTypesAdditionalXSDInfo.size() ;i++){
AdditionalXSDInformation currAdditionalXSDInformation = simpleTypesAdditionalXSDInfo.get(i);
if(!currAdditionalXSDInformation.isJavaFileGenerated())
continue;
Element individualBindElement = null;
individualBindElement = dom.createElement("bindings");
individualBindElement.setAttribute("if-exists", "true");
individualBindElement.setAttribute("scd", "~tns:" + currAdditionalXSDInformation.getTypeName());
bindingsElement.appendChild(individualBindElement);
Element classElement = dom.createElement("class");
classElement.setAttribute("ref",WSDLUtil.getPackageFromNamespace(currAdditionalXSDInformation.getTargetNamespace()) + "." + currAdditionalXSDInformation.getTypeName());
individualBindElement.appendChild(classElement);
}
}
commentNode = dom.createComment(TypeLibraryConstants.MASTER_EPISODE_TURMERIC_END_COMMNENT);
root.appendChild(commentNode);
TransformerFactory transferFact = TransformerFactory.newInstance();
Transformer transformer = null;
try {
transformer = transferFact.newTransformer();
// Bug in java5 transformer, indentation does not work.
// refer to
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
} catch (TransformerConfigurationException e) {
getLogger().log(Level.SEVERE, e.getMessageAndLocation());
throw new CodeGenFailedException(e.getMessage());
}
//following lines are commented due to use of internal classes.
//not permitted
// OutputFormat outputOptions = new OutputFormat();
// outputOptions.setIndenting(true);
// outputOptions.setStandalone(true);
// Writer output = new BufferedWriter(new FileWriter(fileOutput));
// DOMSerializer serializer = new XMLSerializer(output,
// outputOptions);
// serializer.serialize(dom);
File fileOutput = new File(sunJaxbEpisodeSrcpath + File.separator
+ "sun-jaxb.episode");
DOMSource sourcewsdl = new DOMSource(dom);
FileOutputStream output = null;
try {
output = new FileOutputStream(fileOutput);
StreamResult newWsdl = new StreamResult(output);
sourcewsdl.setNode(dom);
transformer.transform(sourcewsdl, newWsdl);
} finally {
CodeGenUtil.closeQuietly(output);
}
getLogger().log(Level.INFO, "sun-jaxb.episode file created successfully.");
} catch (Exception e) {
getLogger().log(Level.SEVERE, e.getMessage());
}
getLogger().exiting();
}
private static Node getParentNode(Document dom, String nameSpaceDoc) {
NodeList childNodes = dom.getDocumentElement().getChildNodes();
Node parentNode = null;
for (int i = 0; i < childNodes.getLength(); i++) {
parentNode = childNodes.item(i);
String nodeName = childNodes.item(i).getNodeName();
// System.out.println("Document Child Name = " + nodeName);
if (nodeName.indexOf("bindings") >= 0) {
String nameSpaceDom = parentNode.getAttributes().getNamedItem(
"xmlns:tns").getNodeValue();
if (nameSpaceDom.equals(nameSpaceDoc)) {
return parentNode;
}
}
}
return parentNode;
}
private static void addChild(NodeList childNodeL1, Node parentNode,
Document dom,
HashSet<String> typesAddedInMasterEpisode, List<String> xsdTypes, Map<String, String> typesVersion) {
for (int i = childNodeL1.getLength() - 1; i >= 0; i--) {
Node childNode1 = childNodeL1.item(i);
String childNodeName1 = childNode1.getNodeName();
if (childNodeName1.indexOf("bindings") >= 0) {
Node tempNode = dom.importNode(childNode1, true);
String xmlTypeName = tempNode.getAttributes().getNamedItem(
"scd").getNodeValue();
NamedNodeMap attributes = tempNode.getAttributes();
Attr attributeToAdd = dom.createAttribute("if-exists");
attributeToAdd.setNodeValue("true");
attributes.setNamedItem(attributeToAdd);
if (typesAddedInMasterEpisode.contains(xmlTypeName))
continue; // the type is already added to the master
// episode file, so skip it
parentNode.appendChild(tempNode);
typesAddedInMasterEpisode.add(xmlTypeName);
xmlTypeName = TypeLibraryUtilities.removePrefix(xmlTypeName);
}
}
}
}