1 52 53 package freemarker.ext.xml; 54 55 import java.io.StringWriter ; 56 import java.util.HashMap ; 57 import java.util.List ; 58 import java.util.Map ; 59 import java.util.WeakHashMap ; 60 61 import org.jaxen.NamespaceContext; 62 63 import freemarker.template.TemplateModelException; 64 65 69 abstract class Navigator { 70 private final Map xpathCache = new WeakHashMap (); 72 private final Map operators = createOperatorMap(); 74 private final NodeOperator attributeOperator = getOperator("_attributes"); 75 private final NodeOperator childrenOperator = getOperator("_children"); 76 77 NodeOperator getOperator(String key) { 78 return (NodeOperator)operators.get(key); 79 } 80 81 NodeOperator getAttributeOperator() { 82 return attributeOperator; 83 } 84 85 NodeOperator getChildrenOperator() { 86 return childrenOperator; 87 } 88 89 abstract void getAsString(Object node, StringWriter sw) 90 throws 91 TemplateModelException; 92 93 List applyXPath(List nodes, String xpathString, Object namespaces) 94 throws 95 TemplateModelException 96 { 97 XPathEx xpath = null; 98 try 99 { 100 synchronized(xpathCache) 101 { 102 xpath = (XPathEx)xpathCache.get(xpathString); 103 if (xpath == null) 104 { 105 xpath = createXPathEx(xpathString); 106 xpathCache.put(xpathString, xpath); 107 } 108 } 109 return xpath.selectNodes(nodes, (NamespaceContext)namespaces); 110 } 111 catch(Exception e) 112 { 113 throw new TemplateModelException("Could not evaulate XPath expression " + xpathString, e); 114 } 115 } 116 117 interface XPathEx 118 { 119 List selectNodes(Object nodes, NamespaceContext namespaces) throws TemplateModelException; 120 } 121 122 abstract XPathEx createXPathEx(String xpathString) throws TemplateModelException; 123 124 abstract void getChildren(Object node, String localName, String namespaceUri, List result); 125 126 abstract void getAttributes(Object node, String localName, String namespaceUri, List result); 127 128 abstract void getDescendants(Object node, List result); 129 130 abstract Object getParent(Object node); 131 132 abstract Object getDocument(Object node); 133 134 abstract Object getDocumentType(Object node); 135 136 private void getAncestors(Object node, List result) 137 { 138 for(;;) { 139 Object parent = getParent(node); 140 if(parent == null) { 141 break; 142 } 143 result.add(parent); 144 node = parent; 145 } 146 } 147 148 abstract void getContent(Object node, List result); 149 150 abstract String getText(Object node); 151 152 abstract String getLocalName(Object node); 153 154 abstract String getNamespacePrefix(Object node); 155 156 String getQualifiedName(Object node) { 157 String lname = getLocalName(node); 158 if(lname == null) { 159 return null; 160 } 161 String nsprefix = getNamespacePrefix(node); 162 if(nsprefix == null || nsprefix.length() == 0) { 163 return lname; 164 } 165 else { 166 return nsprefix + ":" + lname; 167 } 168 } 169 170 abstract String getType(Object node); 171 172 abstract String getNamespaceUri(Object node); 173 174 boolean equal(String s1, String s2) { 175 return s1 == null ? s2 == null : s1.equals(s2); 176 } 177 178 private Map createOperatorMap() { 179 Map map = new HashMap (); 180 map.put("_attributes", new AttributesOp()); 181 map.put("@*", map.get("_attributes")); 182 map.put("_children", new ChildrenOp()); 183 map.put("*", map.get("_children")); 184 map.put("_descendantOrSelf", new DescendantOrSelfOp()); 185 map.put("_descendant", new DescendantOp()); 186 map.put("_document", new DocumentOp()); 187 map.put("_doctype", new DocumentTypeOp()); 188 map.put("_ancestor", new AncestorOp()); 189 map.put("_ancestorOrSelf", new AncestorOrSelfOp()); 190 map.put("_content", new ContentOp()); 191 map.put("_name", new LocalNameOp()); 192 map.put("_nsprefix", new NamespacePrefixOp()); 193 map.put("_nsuri", new NamespaceUriOp()); 194 map.put("_parent", new ParentOp()); 195 map.put("_qname", new QualifiedNameOp()); 196 map.put("_text", new TextOp()); 197 map.put("_type", new TypeOp()); 198 return map; 199 } 200 201 private class ChildrenOp implements NodeOperator { 202 public void process(Object node, String localName, String namespaceUri, List result) 203 { 204 getChildren(node, localName, namespaceUri, result); 205 } 206 } 207 208 private class AttributesOp implements NodeOperator { 209 public void process(Object node, String localName, String namespaceUri, List result) 210 { 211 getAttributes(node, localName, namespaceUri, result); 212 } 213 } 214 215 private class DescendantOrSelfOp implements NodeOperator { 216 public void process(Object node, String localName, String namespaceUri, List result) 217 { 218 result.add(node); 219 getDescendants(node, result); 220 } 221 } 222 223 private class DescendantOp implements NodeOperator { 224 public void process(Object node, String localName, String namespaceUri, List result) 225 { 226 getDescendants(node, result); 227 } 228 } 229 230 private class AncestorOrSelfOp implements NodeOperator { 231 public void process(Object node, String localName, String namespaceUri, List result) 232 { 233 result.add(node); 234 getAncestors(node, result); 235 } 236 } 237 238 private class AncestorOp implements NodeOperator { 239 public void process(Object node, String localName, String namespaceUri, List result) 240 { 241 getAncestors(node, result); 242 } 243 } 244 245 private class ParentOp implements NodeOperator { 246 public void process(Object node, String localName, String namespaceUri, List result) 247 { 248 Object parent = getParent(node); 249 if(parent != null) { 250 result.add(parent); 251 } 252 } 253 } 254 255 private class DocumentOp implements NodeOperator { 256 public void process(Object node, String localName, String namespaceUri, List result) 257 { 258 Object document = getDocument(node); 259 if(document != null) { 260 result.add(document); 261 } 262 } 263 } 264 265 private class DocumentTypeOp implements NodeOperator { 266 public void process(Object node, String localName, String namespaceUri, List result) 267 { 268 Object documentType = getDocumentType(node); 269 if(documentType != null) { 270 result.add(documentType); 271 } 272 } 273 } 274 275 private class ContentOp implements NodeOperator { 276 public void process(Object node, String localName, String namespaceUri, List result) 277 { 278 getContent(node, result); 279 } 280 } 281 282 private class TextOp implements NodeOperator { 283 public void process(Object node, String localName, String namespaceUri, List result) 284 { 285 String text = getText(node); 286 if(text != null) { 287 result.add(text); 288 } 289 } 290 } 291 292 private class LocalNameOp implements NodeOperator { 293 public void process(Object node, String localName, String namespaceUri, List result) 294 { 295 String text = getLocalName(node); 296 if(text != null) { 297 result.add(text); 298 } 299 } 300 } 301 302 private class QualifiedNameOp implements NodeOperator { 303 public void process(Object node, String localName, String namespaceUri, List result) 304 { 305 String qname = getQualifiedName(node); 306 if(qname != null) { 307 result.add(qname); 308 } 309 } 310 } 311 312 private class NamespacePrefixOp implements NodeOperator { 313 public void process(Object node, String localName, String namespaceUri, List result) 314 { 315 String text = getNamespacePrefix(node); 316 if(text != null) { 317 result.add(text); 318 } 319 } 320 } 321 322 private class NamespaceUriOp implements NodeOperator { 323 public void process(Object node, String localName, String namespaceUri, List result) 324 { 325 String text = getNamespaceUri(node); 326 if(text != null) { 327 result.add(text); 328 } 329 } 330 } 331 332 private class TypeOp implements NodeOperator { 333 public void process(Object node, String localName, String namespaceUri, List result) 334 { 335 result.add(getType(node)); 336 } 337 } 338 } 339 | Popular Tags |