View Javadoc

1   package org.softnetwork.xml.dom.xpath;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.List;
6   import java.util.StringTokenizer;
7   import org.w3c.dom.Document;
8   import org.w3c.dom.Element;
9   import org.w3c.dom.Node;
10  
11  /**
12   * @author stephane.manciot@ebiznext.com
13   *
14   */
15  public final class LookupService implements XPath {
16      
17      final static String XPATH_TOKENIZER = XPATH_COND_BEGIN + ","
18              + XPATH_COND_END + ","
19              + XPATH_SEPARATOR;
20      
21      private LookupService() {
22      }
23      
24      public static Node[] selectNodes(Node current, String xPath)
25      throws XPathFormatException {
26          // check if xpath is null
27          if (xPath == null)
28              return EMPTY;
29          if (current == null)
30              return EMPTY;
31          boolean fromDocument = xPath.startsWith(XPATH_SEPARATOR);
32          StringTokenizer tokens = new StringTokenizer(xPath, XPATH_TOKENIZER,
33                  true);
34          if (fromDocument) {
35              if (current.getOwnerDocument() != null)
36                  current = current.getOwnerDocument();
37              if (current instanceof Document)
38                  current = ((Document) current).getDocumentElement();
39              String tagName = current.getNodeName();
40              String token = null;
41              while ((tokens.hasMoreElements())) {
42                  token = tokens.nextToken();
43                  if (!token.equals(XPATH_SEPARATOR))
44                      break;
45              }
46              if (!tagName.equals(token))// || token.equals(XPATH_ALL))
47                  return EMPTY;
48          }
49          List in = new ArrayList();
50          in.add(current);
51          return selectNodes(new ArrayList(), in, select(tokens));
52      }
53      
54      private static final XPathNode[] select(StringTokenizer tokens)
55      throws XPathFormatException {
56          List nodes = new ArrayList();
57          while (tokens.hasMoreTokens()) {
58              String token = tokens.nextToken();
59              if (!token.equals(XPATH_SEPARATOR)
60              && !token.equals(XPATH_COND_BEGIN)) {
61                  String name = token;
62                  List filters = new ArrayList();
63                  if (tokens.hasMoreElements()) {
64                      token = tokens.nextToken();
65                      if (token.equals(XPATH_COND_BEGIN)) {
66                          do {
67                              XPathFilter filter = null;
68                              String filterTokens = "";
69                              while ((tokens.hasMoreElements())
70                              && !(token = tokens.nextToken())
71                              .equals(XPATH_COND_END))
72                                  filterTokens += token;
73                              filter = new XPathFilter(filterTokens);
74                              filters.add(filter);
75                          } while ((tokens.hasMoreElements())
76                          && (token = tokens.nextToken())
77                          .equals(XPATH_COND_BEGIN));
78                      }
79                  }
80                  nodes.add(new XPathNode(name, (XPathFilter[]) filters
81                          .toArray(new XPathFilter[0])));
82              }
83          }
84          return (XPathNode[]) nodes.toArray(new XPathNode[0]);
85      }
86      
87      private static final Node[] selectNodes(List matches, List in,
88              XPathNode[] nodes) throws XPathFormatException {
89          // if (in.isEmpty())
90          // return EMPTY;
91          int nb = nodes.length;
92          if (nb == 0)
93              return (Node[]) in.toArray(new Node[0]);
94          Node current = null;
95          Node[] from = (Node[]) in.toArray(new Node[0]);
96          int len = from.length;
97          in.clear();
98          int i = 0;
99          for (; i < len; i++) {
100             current = from[i];
101             XPathNode node = nodes[0];
102             in.addAll(Arrays.asList(node.selectNodes(current)));
103             if (nb > 1) {
104                 XPathNode[] copy = new XPathNode[nb - 1];
105                 System.arraycopy(nodes, 1, copy, 0, nb - 1);
106                 selectNodes(matches, in, copy);
107             } else
108                 matches.addAll(in);
109         }
110         return (Node[]) matches.toArray(new Node[0]);
111     }
112     
113     public static Element[] selectElements(Element current, String xPath)
114     throws XPathFormatException {
115         // LightConsole.info(current.getXPathElement() + ", " + xPath);
116         // check if xpath is null
117         if (xPath == null)
118             return EMPTY;
119         if (current == null)
120             return EMPTY;
121         
122         boolean fromDocument = xPath.startsWith(XPATH_SEPARATOR);
123         if (fromDocument
124                 && !xPath.startsWith(XPATH_SEPARATOR + current.getTagName())) {
125             String currentXPath = XPathTools.getXpath(current);
126             if (!xPath.startsWith(currentXPath))
127                 xPath = currentXPath + xPath;
128         }
129         // LightConsole.debug(xPath);
130         StringTokenizer tokens = new StringTokenizer(xPath, XPATH_TOKENIZER,
131                 true);
132         if (fromDocument) {
133             current = current.getOwnerDocument().getDocumentElement();
134             String tagName = current.getTagName();
135             String token = null;
136             while ((tokens.hasMoreElements())) {
137                 token = tokens.nextToken();
138                 if (!token.equals(XPATH_SEPARATOR))
139                     break;
140             }
141             if (!tagName.equals(token))// || token.equals(XPATH_ALL))
142                 return EMPTY;
143         }
144         List in = new ArrayList();
145         in.add(current);
146         List elements = new ArrayList();
147         while (tokens.hasMoreTokens()) {
148             String token = tokens.nextToken();
149             if (!token.equals(XPATH_SEPARATOR)
150             && !token.equals(XPATH_COND_BEGIN)) {
151                 String name = token;
152                 List filters = new ArrayList();
153                 if (tokens.hasMoreElements()) {
154                     token = tokens.nextToken();
155                     if (token.equals(XPATH_COND_BEGIN)) {
156                         do {
157                             XPathFilter filter = null;
158                             String filterTokens = "";
159                             while ((tokens.hasMoreElements())
160                             && !(token = tokens.nextToken())
161                             .equals(XPATH_COND_END))
162                                 filterTokens += token;
163                             filter = new XPathFilter(filterTokens);
164                             filters.add(filter);
165                         } while ((tokens.hasMoreElements())
166                         && (token = tokens.nextToken())
167                         .equals(XPATH_COND_BEGIN));
168                     }
169                 }
170                 elements.add(new XPathElement(name, (XPathFilter[]) filters
171                         .toArray(new XPathFilter[0])));
172             }
173         }
174         Element[] selected = selectElements(new ArrayList(), in,
175                 (XPathElement[]) elements.toArray(new XPathElement[0]));
176         // if (selected != null) {
177         // int len = selected.length;
178         // for (int i = 0; i < len; i++)
179         // LightConsole
180         // .debug(((DOMElement) selected[i]).getXPathElement());
181         // }
182         return selected;
183     }
184     
185     private static final Element[] selectElements(List matches, List in,
186             XPathElement[] elements) throws XPathFormatException {
187         // if (in.isEmpty())
188         // return EMPTY;
189         int nb = elements.length;
190         if (nb == 0)
191             return (Element[]) in.toArray(new Element[0]);
192         Element current = null;
193         Element[] from = (Element[]) in.toArray(new Element[0]);
194         int len = from.length;
195         in.clear();
196         int i = 0;
197         for (; i < len; i++) {
198             current = from[i];
199             XPathElement element = elements[0];
200             in.addAll(Arrays.asList(element.selectElements(current)));
201             if (nb > 1) {
202                 XPathElement[] copy = new XPathElement[nb - 1];
203                 System.arraycopy(elements, 1, copy, 0, nb - 1);
204                 selectElements(matches, in, copy);
205             } else
206                 matches.addAll(in);
207         }
208         return (Element[]) matches.toArray(new Element[0]);
209     }
210     
211 }