From c659eb271eea2a02afa08ebbb36ed448ff78336a Mon Sep 17 00:00:00 2001 From: wwang Date: Tue, 6 Mar 2012 09:39:59 +0000 Subject: [PATCH] fix Bug TDI-18966: Support optional elements as loop element git-svn-id: http://talendforge.org/svn/tos/trunk@79306 f6f1c999-d317-4740-80b0-e6d1abc6f99e --- .../java/routines/system/Document.java | 75 +----- .../java/routines/system/DocumentToFlat.java | 226 ++++++++++++++++++ .../java/routines/system/NameSpaceTool.java | 113 +++++++++ 3 files changed, 350 insertions(+), 64 deletions(-) create mode 100644 org.talend.librariesmanager/resources/java/routines/system/DocumentToFlat.java create mode 100644 org.talend.librariesmanager/resources/java/routines/system/NameSpaceTool.java diff --git a/org.talend.librariesmanager/resources/java/routines/system/Document.java b/org.talend.librariesmanager/resources/java/routines/system/Document.java index 8fda1e61c9..ccfbe563b1 100644 --- a/org.talend.librariesmanager/resources/java/routines/system/Document.java +++ b/org.talend.librariesmanager/resources/java/routines/system/Document.java @@ -60,16 +60,15 @@ public class Document implements java.io.Serializable{ } List> result = new ArrayList>(); org.dom4j.Document document = doc.getDocument(); - org.dom4j.XPath xpathObjectForDoc = document.createXPath(loopXPath); - xpathObjectForDoc.setNamespaceURIs(nsMapping); - java.util.List nodes = xpathObjectForDoc.selectNodes(document); - if(nodes.size()==0) { - //set root as loop when no loop nodes - loopXPath = resetLoop(loopXPath,lookupInfo,xpathOfResults,xpathToTypeMap,xpathToPatternMap); - xpathObjectForDoc = document.createXPath(loopXPath); - xpathObjectForDoc.setNamespaceURIs(nsMapping); - nodes = xpathObjectForDoc.selectNodes(document); - } + + //init document to flat tool + DocumentToFlat docToFlat = new DocumentToFlat(lookupInfo, xpathOfResults, xpathToTypeMap, xpathToPatternMap); + docToFlat.setDoc(document); + docToFlat.setOriginalLoop(loopXPath); + docToFlat.setXmlNameSpaceMap(nsMapping); + docToFlat.flatForLookup(); + java.util.List nodes = docToFlat.getNodes(); + for (org.dom4j.tree.AbstractNode node : nodes) { boolean reject = false; // lookup action @@ -112,6 +111,8 @@ public class Document implements java.io.Serializable{ } } + //reset lookup info + lookupInfo.clear(); //set resultset int count = result.size(); if(count>0) { @@ -128,58 +129,4 @@ public class Document implements java.io.Serializable{ return result; } - private String resetLoop(String loop, Map lookupInfo, - Map xpathOfResults, Map xpathToTypeMap, Map xpathToPatternMap) { - - resetMapRelativeXpathKey(lookupInfo,loop); - resetMapRelativeXpathKey(xpathToTypeMap,loop); - resetMapRelativeXpathKey(xpathToPatternMap,loop); - resetMapRelativeXpathValue(xpathOfResults,loop); - - int index = loop.indexOf("/",1); - return loop.substring(0, index>0 ? index : loop.length()); - } - - private void resetMapRelativeXpathKey(Map source,String loop) { - Map content = new HashMap(); - for(String key : source.keySet()) { - String newKey = resetRelativeXPath(loop,key); - content.put(newKey, source.get(key)); - } - source.clear(); - source.putAll(content); - } - - private void resetMapRelativeXpathValue(Map source,String loop) { - Map content = new HashMap(); - for(String key : source.keySet()) { - String value = source.get(key); - String newValue = resetRelativeXPath(loop,value); - content.put(key, newValue); - } - source.clear(); - source.putAll(content); - } - - private String resetRelativeXPath(String loop,String relativePath) { - String absolutePath = loop; - for(String step : relativePath.split("/")) { - if("..".equals(step)) { - absolutePath = absolutePath.substring(0,absolutePath.lastIndexOf("/")); - } else if(".".equals(step)){ - //do nothing - } else if(!"".equals(step)){ - absolutePath += "/" + step; - } - } - String result = null; - int index = absolutePath.indexOf("/", 1); - if(index<0) { - result = "."; - } else { - result = absolutePath.substring(index+1); - } - return result; - } - } diff --git a/org.talend.librariesmanager/resources/java/routines/system/DocumentToFlat.java b/org.talend.librariesmanager/resources/java/routines/system/DocumentToFlat.java new file mode 100644 index 0000000000..84fbe4c1b9 --- /dev/null +++ b/org.talend.librariesmanager/resources/java/routines/system/DocumentToFlat.java @@ -0,0 +1,226 @@ +package routines.system; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.dom4j.XPath; +import org.dom4j.tree.AbstractNode; + +public class DocumentToFlat { + + private org.dom4j.Document doc; + + private String currentLoop; + + private String originalLoop; + private String[] currentRelativePathMappings; + private String[] absolutePathMappings; + + private Map xmlNameSpaceMap; + + private boolean top = false; + + //check whether namespace define exist in UI + private boolean defineNS = true; + private NameSpaceTool namespaceTool; + + private List nodes; + + //result show + private List> resultSet = new ArrayList>(); + + public DocumentToFlat() { + + } + + /** + * Document to Flat + */ + public void flat() { + XPath loopXpath = null; + if(!defineNS) { + loopXpath = doc.createXPath(namespaceTool.addDefaultNSPrefix(currentLoop, currentLoop)); + } else { + loopXpath = doc.createXPath(currentLoop); + } + loopXpath.setNamespaceURIs(xmlNameSpaceMap); + nodes = loopXpath.selectNodes(doc); + if(nodes.size() == 0 && !top) { + setParentAsLoop(); + flat(); + } else { + //reset relative paths + if(currentLoop != originalLoop) {//not point to the same string + for(int i=0;i row = new HashMap(); + resultSet.add(row); + //init columns for one row + for(int i=0;i 0) { + end = idx; + } else if(idx == 0) {//currentLoop is root + top = true; + } + currentLoop = currentLoop.substring(0, end); + } + + public List> getResultSet() { + return resultSet; + } + + public void setDoc(org.dom4j.Document doc) { + this.doc = doc; + } + + public void setOriginalLoop(String originalLoop) { + this.originalLoop = originalLoop; + this.currentLoop = originalLoop; + } + + public void setCurrentRelativePathMappings(String[] currentRelativePathMappings) { + this.currentRelativePathMappings = currentRelativePathMappings; + } + + public void setAbsolutePathMappings(String[] absolutePathMappings) { + this.absolutePathMappings = absolutePathMappings; + } + + public void setXmlNameSpaceMap(Map xmlNameSpaceMap) { + this.xmlNameSpaceMap = xmlNameSpaceMap; + } + + public void setDefineNS(boolean defineNS) { + this.defineNS = defineNS; + } + + public void setNamespaceTool(NameSpaceTool namespaceTool) { + this.namespaceTool = namespaceTool; + } + + private Map lookupInfo; + private Map xpathOfResults; + private Map xpathToTypeMap; + private Map xpathToPatternMap; + + public DocumentToFlat(Map lookupInfo, + Map xpathOfResults, + Map xpathToTypeMap, + Map xpathToPatternMap) { + this.lookupInfo = lookupInfo; + this.xpathOfResults = xpathOfResults; + this.xpathToTypeMap = xpathToTypeMap; + this.xpathToPatternMap = xpathToPatternMap; + } + + public void flatForLookup() { + XPath loopXpath = doc.createXPath(currentLoop); + loopXpath.setNamespaceURIs(xmlNameSpaceMap); + nodes = loopXpath.selectNodes(doc); + if(nodes.size() == 0 && !top) { + setParentAsLoop(); + flatForLookup(); + } else { + if(currentLoop != originalLoop) {//not point to the same string + reset(); + } + } + } + + private void reset() { + resetMapRelativeXpathKey(lookupInfo); + resetMapRelativeXpathKey(xpathToTypeMap); + resetMapRelativeXpathKey(xpathToPatternMap); + resetMapRelativeXpathValue(xpathOfResults); + } + + private void resetMapRelativeXpathKey(Map source) { + Map content = new HashMap(); + for(String key : source.keySet()) { + String newKey = resetRelativeXPath(key); + content.put(newKey, source.get(key)); + } + source.clear(); + source.putAll(content); + } + + private void resetMapRelativeXpathValue(Map source) { + Map content = new HashMap(); + for(String key : source.keySet()) { + String value = source.get(key); + String newValue = resetRelativeXPath(value); + content.put(key, newValue); + } + source.clear(); + source.putAll(content); + } + + public List getNodes() { + return nodes; + } + +} diff --git a/org.talend.librariesmanager/resources/java/routines/system/NameSpaceTool.java b/org.talend.librariesmanager/resources/java/routines/system/NameSpaceTool.java new file mode 100644 index 0000000000..72ea0a35f6 --- /dev/null +++ b/org.talend.librariesmanager/resources/java/routines/system/NameSpaceTool.java @@ -0,0 +1,113 @@ +package routines.system; + +public class NameSpaceTool { + + public java.util.HashMap xmlNameSpaceMap = new java.util.HashMap(); + + private java.util.List defualtNSPath = new java.util.ArrayList(); + + public void countNSMap(org.dom4j.Element el) { + for (org.dom4j.Namespace ns : (java.util.List) el.declaredNamespaces()) { + if (ns.getPrefix().trim().length() == 0) { + xmlNameSpaceMap.put("pre"+defualtNSPath.size(), ns.getURI()); + String path = ""; + org.dom4j.Element elTmp = el; + while (elTmp != null) { + if (elTmp.getNamespacePrefix() != null && elTmp.getNamespacePrefix().length() > 0) { + path = "/" + elTmp.getNamespacePrefix() + ":" + elTmp.getName() + path; + } else { + path = "/" + elTmp.getName() + path; + } + elTmp = elTmp.getParent(); + } + defualtNSPath.add(path); + } else { + xmlNameSpaceMap.put(ns.getPrefix(), ns.getURI()); + } + + } + for (org.dom4j.Element e : (java.util.List) el.elements()) { + countNSMap(e); + } + } + + public String addDefaultNSPrefix(String path, String loopPath) { + if (defualtNSPath.size() > 0) { + String fullPath = loopPath; + if(!path.equals(fullPath)){ + for (String tmp : path.split("/")) { + if (("..").equals(tmp)) { + fullPath = fullPath.substring(0, fullPath.lastIndexOf("/")); + } else { + fullPath += "/" + tmp; + } + } + } + int[] indexs = new int[fullPath.split("/").length - 1]; + java.util.Arrays.fill(indexs, -1); + int length = 0; + for (int i = 0; i < defualtNSPath.size(); i++) { + if (defualtNSPath.get(i).length() > length && fullPath.startsWith(defualtNSPath.get(i))) { + java.util.Arrays.fill(indexs, defualtNSPath.get(i).split("/").length - 2, indexs.length, i); + length = defualtNSPath.get(i).length(); + } + } + + StringBuilder newPath = new StringBuilder(); + String[] pathStrs = path.split("/"); + for (int i = 0; i < pathStrs.length; i++) { + String tmp = pathStrs[i]; + if (newPath.length() > 0) { + newPath.append("/"); + } + if (tmp.length() > 0 && tmp.indexOf(":") == -1 && tmp.indexOf(".") == -1 /*&& tmp.indexOf("@") == -1*/) { + int index = indexs[i + indexs.length - pathStrs.length]; + if (index >= 0) { + //==== add by wliu to support both filter and functions== + if(tmp.indexOf("[")>0 && tmp.indexOf("]")>tmp.indexOf("[")){//include filter + String tmpStr=replaceElementWithNS(tmp,"pre"+index+":"); + newPath.append(tmpStr); + }else{ + if(tmp.indexOf("@") != -1 || tmp.indexOf("(")