You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/02/26 01:57:08 UTC
[4/4] incubator-freemarker git commit: Moved
o.a.f.core.model.impl.dom to org.apache.freemarker.dom,
so that later it can be a separate module (separate jar)
Moved o.a.f.core.model.impl.dom to org.apache.freemarker.dom, so that later it can be a separate module (separate jar)
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/59412b29
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/59412b29
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/59412b29
Branch: refs/heads/3
Commit: 59412b293d5beb364c2ddb35a6251efb4a065277
Parents: 4e60f9e
Author: ddekany <dd...@apache.org>
Authored: Sun Feb 26 02:53:31 2017 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Feb 26 02:56:54 2017 +0100
----------------------------------------------------------------------
.../freemarker/core/BuiltInsForNodes.java | 6 +-
.../org/apache/freemarker/core/_CoreLogs.java | 1 -
.../core/model/TemplateNodeModelEx.java | 2 +-
.../core/model/impl/DefaultObjectWrapper.java | 2 +-
.../freemarker/core/model/impl/dom/AtAtKey.java | 58 --
.../core/model/impl/dom/AttributeNodeModel.java | 69 ---
.../model/impl/dom/CharacterDataNodeModel.java | 46 --
.../core/model/impl/dom/DocumentModel.java | 76 ---
.../core/model/impl/dom/DocumentTypeModel.java | 56 --
.../core/model/impl/dom/DomStringUtil.java | 93 ---
.../core/model/impl/dom/ElementModel.java | 233 -------
.../core/model/impl/dom/JaxenXPathSupport.java | 238 -------
.../core/model/impl/dom/NodeListModel.java | 231 -------
.../core/model/impl/dom/NodeModel.java | 618 -------------------
.../core/model/impl/dom/NodeOutputter.java | 258 --------
.../core/model/impl/dom/PINodeModel.java | 45 --
.../impl/dom/SunInternalXalanXPathSupport.java | 163 -----
.../core/model/impl/dom/XPathSupport.java | 30 -
.../core/model/impl/dom/XalanXPathSupport.java | 163 -----
.../core/model/impl/dom/_ExtDomApi.java | 43 --
.../freemarker/core/model/impl/dom/package.html | 31 -
.../freemarker/core/util/_StringUtil.java | 22 +-
.../java/org/apache/freemarker/dom/AtAtKey.java | 58 ++
.../freemarker/dom/AttributeNodeModel.java | 69 +++
.../freemarker/dom/CharacterDataNodeModel.java | 46 ++
.../apache/freemarker/dom/DocumentModel.java | 76 +++
.../freemarker/dom/DocumentTypeModel.java | 56 ++
.../java/org/apache/freemarker/dom/DomLog.java | 32 +
.../apache/freemarker/dom/DomStringUtil.java | 70 +++
.../org/apache/freemarker/dom/ElementModel.java | 234 +++++++
.../freemarker/dom/JaxenXPathSupport.java | 238 +++++++
.../apache/freemarker/dom/NodeListModel.java | 231 +++++++
.../org/apache/freemarker/dom/NodeModel.java | 618 +++++++++++++++++++
.../apache/freemarker/dom/NodeOutputter.java | 258 ++++++++
.../org/apache/freemarker/dom/PINodeModel.java | 45 ++
.../dom/SunInternalXalanXPathSupport.java | 163 +++++
.../org/apache/freemarker/dom/XPathSupport.java | 30 +
.../freemarker/dom/XalanXPathSupport.java | 163 +++++
.../java/org/apache/freemarker/dom/package.html | 31 +
src/manual/en_US/FM3-CHANGE-LOG.txt | 2 +-
.../core/model/impl/dom/DOMSiblingTest.java | 99 ---
.../core/model/impl/dom/DOMSimplifiersTest.java | 201 ------
.../freemarker/core/model/impl/dom/DOMTest.java | 161 -----
.../apache/freemarker/dom/DOMSiblingTest.java | 99 +++
.../freemarker/dom/DOMSimplifiersTest.java | 201 ++++++
.../java/org/apache/freemarker/dom/DOMTest.java | 161 +++++
.../test/templatesuite/TemplateTestCase.java | 2 +-
.../test/templatesuite/TemplateTestSuite.java | 2 +-
.../apache/freemarker/test/util/XMLLoader.java | 2 +-
.../core/model/impl/dom/DOMSiblingTest.xml | 31 -
.../apache/freemarker/dom/DOMSiblingTest.xml | 31 +
51 files changed, 2938 insertions(+), 2956 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java b/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
index 4d808b3..3894c5b 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
@@ -28,7 +28,7 @@ import org.apache.freemarker.core.model.TemplateNodeModel;
import org.apache.freemarker.core.model.TemplateNodeModelEx;
import org.apache.freemarker.core.model.impl.SimpleScalar;
import org.apache.freemarker.core.model.impl.SimpleSequence;
-import org.apache.freemarker.core.model.impl.dom._ExtDomApi;
+import org.apache.freemarker.core.util._StringUtil;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -120,7 +120,7 @@ class BuiltInsForNodes {
static class AncestorSequence extends SimpleSequence implements TemplateMethodModel {
@SuppressFBWarnings(value="SE_BAD_FIELD",
- justification="Can't make this Serializable, and not extneding SimpleSequence would be non-BC.")
+ justification="Can't make this Serializable, and not extending SimpleSequence would be non-BC.")
private Environment env;
AncestorSequence(Environment env) {
@@ -143,7 +143,7 @@ class BuiltInsForNodes {
}
} else {
for (int j = 0; j < names.size(); j++) {
- if (_ExtDomApi.matchesName((String) names.get(j), nodeName, nsURI, env)) {
+ if (_StringUtil.matchesQName((String) names.get(j), nodeName, nsURI, env)) {
result.add(tnm);
break;
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/_CoreLogs.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_CoreLogs.java b/src/main/java/org/apache/freemarker/core/_CoreLogs.java
index 0e16f6c..1ccb915 100644
--- a/src/main/java/org/apache/freemarker/core/_CoreLogs.java
+++ b/src/main/java/org/apache/freemarker/core/_CoreLogs.java
@@ -32,7 +32,6 @@ public final class _CoreLogs {
public static final Logger ATTEMPT = LoggerFactory.getLogger("org.apache.freemarker.core.runtime.attempt");
public static final Logger SECURITY = LoggerFactory.getLogger("org.apache.freemarker.core.security");
public static final Logger BEANS_WRAPPER = LoggerFactory.getLogger("org.apache.freemarker.core.model.impl.beans");
- public static final Logger DOM_WRAPPER = LoggerFactory.getLogger("org.apache.freemarker.core.model.impl.dom");
public static final Logger TEMPLATE_RESOLVER = LoggerFactory.getLogger(
"org.apache.freemarker.core.templateresolver");
public static final Logger DEBUG_SERVER = LoggerFactory.getLogger("org.apache.freemarker.core.debug.server");
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java b/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
index 5c31d9a..27adb97 100644
--- a/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
+++ b/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
@@ -19,7 +19,7 @@
package org.apache.freemarker.core.model;
-import org.apache.freemarker.core.model.impl.dom.NodeModel;
+import org.apache.freemarker.dom.NodeModel;
/**
* A {@link NodeModel} that supports navigating to the previous and next sibling nodes.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
index 224836d..ba61a2c 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
@@ -37,7 +37,7 @@ import org.apache.freemarker.core.model.TemplateModelException;
import org.apache.freemarker.core.model.TemplateSequenceModel;
import org.apache.freemarker.core.model.impl.beans.BeansWrapper;
import org.apache.freemarker.core.model.impl.beans.BeansWrapperConfiguration;
-import org.apache.freemarker.core.model.impl.dom.NodeModel;
+import org.apache.freemarker.dom.NodeModel;
import org.w3c.dom.Node;
/**
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/AtAtKey.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/AtAtKey.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/AtAtKey.java
deleted file mode 100644
index a21ebcc..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/AtAtKey.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.freemarker.core.model.impl.dom;
-
-/**
- * The special hash keys that start with "@@".
- */
-enum AtAtKey {
-
- MARKUP("@@markup"),
- NESTED_MARKUP("@@nested_markup"),
- ATTRIBUTES_MARKUP("@@attributes_markup"),
- TEXT("@@text"),
- START_TAG("@@start_tag"),
- END_TAG("@@end_tag"),
- QNAME("@@qname"),
- NAMESPACE("@@namespace"),
- LOCAL_NAME("@@local_name"),
- ATTRIBUTES("@@"),
- PREVIOUS_SIBLING_ELEMENT("@@previous_sibling_element"),
- NEXT_SIBLING_ELEMENT("@@next_sibling_element");
-
- private final String key;
-
- public String getKey() {
- return key;
- }
-
- AtAtKey(String key) {
- this.key = key;
- }
-
- public static boolean containsKey(String key) {
- for (AtAtKey item : AtAtKey.values()) {
- if (item.getKey().equals(key)) {
- return true;
- }
- }
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/AttributeNodeModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/AttributeNodeModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/AttributeNodeModel.java
deleted file mode 100644
index 97915e6..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/AttributeNodeModel.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.w3c.dom.Attr;
-
-class AttributeNodeModel extends NodeModel implements TemplateScalarModel {
-
- public AttributeNodeModel(Attr att) {
- super(att);
- }
-
- @Override
- public String getAsString() {
- return ((Attr) node).getValue();
- }
-
- @Override
- public String getNodeName() {
- String result = node.getLocalName();
- if (result == null || result.equals("")) {
- result = node.getNodeName();
- }
- return result;
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-
- @Override
- String getQualifiedName() {
- String nsURI = node.getNamespaceURI();
- if (nsURI == null || nsURI.equals(""))
- return node.getNodeName();
- Environment env = Environment.getCurrentEnvironment();
- String defaultNS = env.getDefaultNS();
- String prefix = null;
- if (nsURI.equals(defaultNS)) {
- prefix = "D";
- } else {
- prefix = env.getPrefixForNamespace(nsURI);
- }
- if (prefix == null) {
- return null;
- }
- return prefix + ":" + node.getLocalName();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/CharacterDataNodeModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/CharacterDataNodeModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/CharacterDataNodeModel.java
deleted file mode 100644
index a488fee..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/CharacterDataNodeModel.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Comment;
-
-class CharacterDataNodeModel extends NodeModel implements TemplateScalarModel {
-
- public CharacterDataNodeModel(CharacterData text) {
- super(text);
- }
-
- @Override
- public String getAsString() {
- return ((org.w3c.dom.CharacterData) node).getData();
- }
-
- @Override
- public String getNodeName() {
- return (node instanceof Comment) ? "@comment" : "@text";
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentModel.java
deleted file mode 100644
index 0d15c71..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentModel.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
-
-/**
- * A class that wraps the root node of a parsed XML document, using
- * the W3C DOM_WRAPPER API.
- */
-
-class DocumentModel extends NodeModel implements TemplateHashModel {
-
- private ElementModel rootElement;
-
- DocumentModel(Document doc) {
- super(doc);
- }
-
- @Override
- public String getNodeName() {
- return "@document";
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (key.equals("*")) {
- return getRootElement();
- } else if (key.equals("**")) {
- NodeList nl = ((Document) node).getElementsByTagName("*");
- return new NodeListModel(nl, this);
- } else if (DomStringUtil.isXMLNameLike(key)) {
- ElementModel em = (ElementModel) NodeModel.wrap(((Document) node).getDocumentElement());
- if (em.matchesName(key, Environment.getCurrentEnvironment())) {
- return em;
- } else {
- return new NodeListModel(this);
- }
- }
- return super.get(key);
- }
-
- ElementModel getRootElement() {
- if (rootElement == null) {
- rootElement = (ElementModel) wrap(((Document) node).getDocumentElement());
- }
- return rootElement;
- }
-
- @Override
- public boolean isEmpty() {
- return false;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentTypeModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentTypeModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentTypeModel.java
deleted file mode 100644
index 768b1d6..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/DocumentTypeModel.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.w3c.dom.DocumentType;
-import org.w3c.dom.ProcessingInstruction;
-
-class DocumentTypeModel extends NodeModel {
-
- public DocumentTypeModel(DocumentType docType) {
- super(docType);
- }
-
- public String getAsString() {
- return ((ProcessingInstruction) node).getData();
- }
-
- public TemplateSequenceModel getChildren() throws TemplateModelException {
- throw new TemplateModelException("entering the child nodes of a DTD node is not currently supported");
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- throw new TemplateModelException("accessing properties of a DTD is not currently supported");
- }
-
- @Override
- public String getNodeName() {
- return "@document_type$" + node.getNodeName();
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/DomStringUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/DomStringUtil.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/DomStringUtil.java
deleted file mode 100644
index 23a9bd6..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/DomStringUtil.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.Template;
-
-/**
- * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
- * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
- * access things inside this package that users shouldn't.
- */
-final class DomStringUtil {
-
- private DomStringUtil() {
- // Not meant to be instantiated
- }
-
- static boolean isXMLNameLike(String name) {
- return isXMLNameLike(name, 0);
- }
-
- /**
- * Check if the name looks like an XML element name.
- *
- * @param firstCharIdx The index of the character in the string parameter that we treat as the beginning of the
- * string to check. This is to spare substringing that has become more expensive in Java 7.
- *
- * @return whether the name is a valid XML element name. (This routine might only be 99% accurate. REVISIT)
- */
- static boolean isXMLNameLike(String name, int firstCharIdx) {
- int ln = name.length();
- for (int i = firstCharIdx; i < ln; i++) {
- char c = name.charAt(i);
- if (i == firstCharIdx && (c == '-' || c == '.' || Character.isDigit(c))) {
- return false;
- }
- if (!Character.isLetterOrDigit(c) && c != '_' && c != '-' && c != '.') {
- if (c == ':') {
- if (i + 1 < ln && name.charAt(i + 1) == ':') {
- // "::" is used in XPath
- return false;
- }
- // We don't return here, as a lonely ":" is allowed.
- } else {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * @return whether the qname matches the combination of nodeName, nsURI, and environment prefix settings.
- */
- static boolean matchesName(String qname, String nodeName, String nsURI, Environment env) {
- String defaultNS = env.getDefaultNS();
- if ((defaultNS != null) && defaultNS.equals(nsURI)) {
- return qname.equals(nodeName)
- || qname.equals(Template.DEFAULT_NAMESPACE_PREFIX + ":" + nodeName);
- }
- if ("".equals(nsURI)) {
- if (defaultNS != null) {
- return qname.equals(Template.NO_NS_PREFIX + ":" + nodeName);
- } else {
- return qname.equals(nodeName) || qname.equals(Template.NO_NS_PREFIX + ":" + nodeName);
- }
- }
- String prefix = env.getPrefixForNamespace(nsURI);
- if (prefix == null) {
- return false; // Is this the right thing here???
- }
- return qname.equals(prefix + ":" + nodeName);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/ElementModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/ElementModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/ElementModel.java
deleted file mode 100644
index 6bfe08f..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/ElementModel.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import java.util.Collections;
-
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-class ElementModel extends NodeModel implements TemplateScalarModel {
-
- public ElementModel(Element element) {
- super(element);
- }
-
- @Override
- public boolean isEmpty() {
- return false;
- }
-
- /**
- * An Element node supports various hash keys.
- * Any key that corresponds to the tag name of any child elements
- * returns a sequence of those elements. The special key "*" returns
- * all the element's direct children.
- * The "**" key return all the element's descendants in the order they
- * occur in the document.
- * Any key starting with '@' is taken to be the name of an element attribute.
- * The special key "@@" returns a hash of all the element's attributes.
- * The special key "/" returns the root document node associated with this element.
- */
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (key.equals("*")) {
- NodeListModel ns = new NodeListModel(this);
- TemplateSequenceModel children = getChildNodes();
- for (int i = 0; i < children.size(); i++) {
- NodeModel child = (NodeModel) children.get(i);
- if (child.node.getNodeType() == Node.ELEMENT_NODE) {
- ns.add(child);
- }
- }
- return ns;
- } else if (key.equals("**")) {
- return new NodeListModel(((Element) node).getElementsByTagName("*"), this);
- } else if (key.startsWith("@")) {
- if (key.startsWith("@@")) {
- if (key.equals(AtAtKey.ATTRIBUTES.getKey())) {
- return new NodeListModel(node.getAttributes(), this);
- } else if (key.equals(AtAtKey.START_TAG.getKey())) {
- NodeOutputter nodeOutputter = new NodeOutputter(node);
- return new SimpleScalar(nodeOutputter.getOpeningTag((Element) node));
- } else if (key.equals(AtAtKey.END_TAG.getKey())) {
- NodeOutputter nodeOutputter = new NodeOutputter(node);
- return new SimpleScalar(nodeOutputter.getClosingTag((Element) node));
- } else if (key.equals(AtAtKey.ATTRIBUTES_MARKUP.getKey())) {
- StringBuilder buf = new StringBuilder();
- NodeOutputter nu = new NodeOutputter(node);
- nu.outputContent(node.getAttributes(), buf);
- return new SimpleScalar(buf.toString().trim());
- } else if (key.equals(AtAtKey.PREVIOUS_SIBLING_ELEMENT.getKey())) {
- Node previousSibling = node.getPreviousSibling();
- while (previousSibling != null && !isSignificantNode(previousSibling)) {
- previousSibling = previousSibling.getPreviousSibling();
- }
- return previousSibling != null && previousSibling.getNodeType() == Node.ELEMENT_NODE
- ? wrap(previousSibling) : new NodeListModel(Collections.emptyList(), null);
- } else if (key.equals(AtAtKey.NEXT_SIBLING_ELEMENT.getKey())) {
- Node nextSibling = node.getNextSibling();
- while (nextSibling != null && !isSignificantNode(nextSibling)) {
- nextSibling = nextSibling.getNextSibling();
- }
- return nextSibling != null && nextSibling.getNodeType() == Node.ELEMENT_NODE
- ? wrap(nextSibling) : new NodeListModel(Collections.emptyList(), null);
- } else {
- // We don't know anything like this that's element-specific; fall back
- return super.get(key);
- }
- } else { // Starts with "@", but not with "@@"
- if (DomStringUtil.isXMLNameLike(key, 1)) {
- Attr att = getAttribute(key.substring(1));
- if (att == null) {
- return new NodeListModel(this);
- }
- return wrap(att);
- } else if (key.equals("@*")) {
- return new NodeListModel(node.getAttributes(), this);
- } else {
- // We don't know anything like this that's element-specific; fall back
- return super.get(key);
- }
- }
- } else if (DomStringUtil.isXMLNameLike(key)) {
- // We interpret key as an element name
- NodeListModel result = ((NodeListModel) getChildNodes()).filterByName(key);
- return result.size() != 1 ? result : result.get(0);
- } else {
- // We don't anything like this that's element-specific; fall back
- return super.get(key);
- }
- }
-
- @Override
- public String getAsString() throws TemplateModelException {
- NodeList nl = node.getChildNodes();
- String result = "";
- for (int i = 0; i < nl.getLength(); i++) {
- Node child = nl.item(i);
- int nodeType = child.getNodeType();
- if (nodeType == Node.ELEMENT_NODE) {
- String msg = "Only elements with no child elements can be processed as text."
- + "\nThis element with name \""
- + node.getNodeName()
- + "\" has a child element named: " + child.getNodeName();
- throw new TemplateModelException(msg);
- } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) {
- result += child.getNodeValue();
- }
- }
- return result;
- }
-
- @Override
- public String getNodeName() {
- String result = node.getLocalName();
- if (result == null || result.equals("")) {
- result = node.getNodeName();
- }
- return result;
- }
-
- @Override
- String getQualifiedName() {
- String nodeName = getNodeName();
- String nsURI = getNodeNamespace();
- if (nsURI == null || nsURI.length() == 0) {
- return nodeName;
- }
- Environment env = Environment.getCurrentEnvironment();
- String defaultNS = env.getDefaultNS();
- String prefix;
- if (defaultNS != null && defaultNS.equals(nsURI)) {
- prefix = "";
- } else {
- prefix = env.getPrefixForNamespace(nsURI);
-
- }
- if (prefix == null) {
- return null; // We have no qualified name, because there is no prefix mapping
- }
- if (prefix.length() > 0) {
- prefix += ":";
- }
- return prefix + nodeName;
- }
-
- private Attr getAttribute(String qname) {
- Element element = (Element) node;
- Attr result = element.getAttributeNode(qname);
- if (result != null)
- return result;
- int colonIndex = qname.indexOf(':');
- if (colonIndex > 0) {
- String prefix = qname.substring(0, colonIndex);
- String uri;
- if (prefix.equals(Template.DEFAULT_NAMESPACE_PREFIX)) {
- uri = Environment.getCurrentEnvironment().getDefaultNS();
- } else {
- uri = Environment.getCurrentEnvironment().getNamespaceForPrefix(prefix);
- }
- String localName = qname.substring(1 + colonIndex);
- if (uri != null) {
- result = element.getAttributeNodeNS(uri, localName);
- }
- }
- return result;
- }
-
- private boolean isSignificantNode(Node node) throws TemplateModelException {
- return (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE)
- ? !isBlankXMLText(node.getTextContent())
- : node.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE && node.getNodeType() != Node.COMMENT_NODE;
- }
-
- private boolean isBlankXMLText(String s) {
- if (s == null) {
- return true;
- }
- for (int i = 0; i < s.length(); i++) {
- if (!isXMLWhiteSpace(s.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * White space according the XML spec.
- */
- private boolean isXMLWhiteSpace(char c) {
- return c == ' ' || c == '\t' || c == '\n' | c == '\r';
- }
-
- boolean matchesName(String name, Environment env) {
- return DomStringUtil.matchesName(name, getNodeName(), getNodeNamespace(), env);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/JaxenXPathSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/JaxenXPathSupport.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/JaxenXPathSupport.java
deleted file mode 100644
index 76d818f..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/JaxenXPathSupport.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.freemarker.core.CustomAttribute;
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.impl._StaticObjectWrappers;
-import org.apache.freemarker.core.util.UndeclaredThrowableException;
-import org.jaxen.BaseXPath;
-import org.jaxen.Function;
-import org.jaxen.FunctionCallException;
-import org.jaxen.FunctionContext;
-import org.jaxen.JaxenException;
-import org.jaxen.NamespaceContext;
-import org.jaxen.Navigator;
-import org.jaxen.UnresolvableException;
-import org.jaxen.VariableContext;
-import org.jaxen.XPathFunctionContext;
-import org.jaxen.dom.DocumentNavigator;
-import org.w3c.dom.Document;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-
-/**
- */
-class JaxenXPathSupport implements XPathSupport {
-
- private static final CustomAttribute XPATH_CACHE_ATTR =
- new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE) {
- @Override
- protected Object create() {
- return new HashMap<String, BaseXPath>();
- }
- };
-
- // [2.4] Can't we just use Collections.emptyList()?
- private final static ArrayList EMPTY_ARRAYLIST = new ArrayList();
-
- @Override
- public TemplateModel executeQuery(Object context, String xpathQuery) throws TemplateModelException {
- try {
- BaseXPath xpath;
- Map<String, BaseXPath> xpathCache = (Map<String, BaseXPath>) XPATH_CACHE_ATTR.get();
- synchronized (xpathCache) {
- xpath = xpathCache.get(xpathQuery);
- if (xpath == null) {
- xpath = new BaseXPath(xpathQuery, FM_DOM_NAVIGATOR);
- xpath.setNamespaceContext(customNamespaceContext);
- xpath.setFunctionContext(FM_FUNCTION_CONTEXT);
- xpath.setVariableContext(FM_VARIABLE_CONTEXT);
- xpathCache.put(xpathQuery, xpath);
- }
- }
- List result = xpath.selectNodes(context != null ? context : EMPTY_ARRAYLIST);
- if (result.size() == 1) {
- // [2.4] Use the proper object wrapper (argument in 2.4)
- return _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER.wrap(result.get(0));
- }
- NodeListModel nlm = new NodeListModel(result, null);
- nlm.xpathSupport = this;
- return nlm;
- } catch (UndeclaredThrowableException e) {
- Throwable t = e.getUndeclaredThrowable();
- if (t instanceof TemplateModelException) {
- throw (TemplateModelException) t;
- }
- throw e;
- } catch (JaxenException je) {
- throw new TemplateModelException(je);
- }
- }
-
- static private final NamespaceContext customNamespaceContext = new NamespaceContext() {
-
- @Override
- public String translateNamespacePrefixToUri(String prefix) {
- if (prefix.equals(Template.DEFAULT_NAMESPACE_PREFIX)) {
- return Environment.getCurrentEnvironment().getDefaultNS();
- }
- return Environment.getCurrentEnvironment().getNamespaceForPrefix(prefix);
- }
- };
-
- private static final VariableContext FM_VARIABLE_CONTEXT = new VariableContext() {
- @Override
- public Object getVariableValue(String namespaceURI, String prefix, String localName)
- throws UnresolvableException {
- try {
- TemplateModel model = Environment.getCurrentEnvironment().getVariable(localName);
- if (model == null) {
- throw new UnresolvableException("Variable \"" + localName + "\" not found.");
- }
- if (model instanceof TemplateScalarModel) {
- return ((TemplateScalarModel) model).getAsString();
- }
- if (model instanceof TemplateNumberModel) {
- return ((TemplateNumberModel) model).getAsNumber();
- }
- if (model instanceof TemplateDateModel) {
- return ((TemplateDateModel) model).getAsDate();
- }
- if (model instanceof TemplateBooleanModel) {
- return Boolean.valueOf(((TemplateBooleanModel) model).getAsBoolean());
- }
- } catch (TemplateModelException e) {
- throw new UndeclaredThrowableException(e);
- }
- throw new UnresolvableException(
- "Variable \"" + localName + "\" exists, but it's not a string, number, date, or boolean");
- }
- };
-
- private static final FunctionContext FM_FUNCTION_CONTEXT = new XPathFunctionContext() {
- @Override
- public Function getFunction(String namespaceURI, String prefix, String localName)
- throws UnresolvableException {
- try {
- return super.getFunction(namespaceURI, prefix, localName);
- } catch (UnresolvableException e) {
- return super.getFunction(null, null, localName);
- }
- }
- };
-
- /**
- * Stores the the template parsed as {@link Document} in the template itself.
- */
- private static final CustomAttribute FM_DOM_NAVIAGOTOR_CACHED_DOM
- = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
-
- private static final Navigator FM_DOM_NAVIGATOR = new DocumentNavigator() {
- @Override
- public Object getDocument(String uri) throws FunctionCallException {
- try {
- Template raw = getTemplate(uri);
- Document doc = (Document) FM_DOM_NAVIAGOTOR_CACHED_DOM.get(raw);
- if (doc == null) {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- DocumentBuilder builder = factory.newDocumentBuilder();
- FmEntityResolver er = new FmEntityResolver();
- builder.setEntityResolver(er);
- doc = builder.parse(createInputSource(null, raw));
- // If the entity resolver got called 0 times, the document
- // is standalone, so we can safely cache it
- if (er.getCallCount() == 0) {
- FM_DOM_NAVIAGOTOR_CACHED_DOM.set(doc, raw);
- }
- }
- return doc;
- } catch (Exception e) {
- throw new FunctionCallException("Failed to parse document for URI: " + uri, e);
- }
- }
- };
-
- // [FM3] Look into this "hidden" feature
- static Template getTemplate(String systemId) throws IOException {
- Environment env = Environment.getCurrentEnvironment();
- String encoding = env.getCurrentTemplate().getEncoding(); // [FM3] Encoding shouldn't be inherited anymore
- if (encoding == null) {
- encoding = env.getConfiguration().getEncoding(env.getLocale());
- }
- String templatePath = env.getCurrentTemplate().getName();
- int lastSlash = templatePath.lastIndexOf('/');
- templatePath = lastSlash == -1 ? "" : templatePath.substring(0, lastSlash + 1);
- systemId = env.toFullTemplateName(templatePath, systemId);
- return env.getConfiguration().getTemplate(systemId, env.getLocale(), encoding, false);
- }
-
- private static InputSource createInputSource(String publicId, Template raw) throws IOException, SAXException {
- StringWriter sw = new StringWriter();
- try {
- raw.process(Collections.EMPTY_MAP, sw);
- } catch (TemplateException e) {
- throw new SAXException(e);
- }
- InputSource is = new InputSource();
- is.setPublicId(publicId);
- is.setSystemId(raw.getName());
- is.setCharacterStream(new StringReader(sw.toString()));
- return is;
- }
-
- private static class FmEntityResolver implements EntityResolver {
- private int callCount = 0;
-
- @Override
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException, IOException {
- ++callCount;
- return createInputSource(publicId, getTemplate(systemId));
- }
-
- int getCallCount() {
- return callCount;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeListModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeListModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeListModel.java
deleted file mode 100644
index 1a70524..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeListModel.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel;
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateNodeModel;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Used when the result set contains 0 or multiple nodes; shouldn't be used when you have exactly 1 node. For exactly 1
- * node, use {@link NodeModel#wrap(Node)}, because {@link NodeModel} subclasses can have extra features building on that
- * restriction, like single elements with text content can be used as FTL string-s.
- *
- * <p>
- * This class is not guaranteed to be thread safe, so instances of this shouldn't be used as shared variable (
- * {@link Configuration#setSharedVariable(String, Object)}).
- */
-class NodeListModel extends SimpleSequence implements TemplateHashModel, _UnexpectedTypeErrorExplainerTemplateModel {
-
- // [2.4] make these private
- NodeModel contextNode;
- XPathSupport xpathSupport;
-
- private static ObjectWrapper nodeWrapper = new ObjectWrapper() {
- @Override
- public TemplateModel wrap(Object obj) {
- if (obj instanceof NodeModel) {
- return (NodeModel) obj;
- }
- return NodeModel.wrap((Node) obj);
- }
- };
-
- NodeListModel(Node contextNode) {
- this(NodeModel.wrap(contextNode));
- }
-
- NodeListModel(NodeModel contextNode) {
- super(nodeWrapper);
- this.contextNode = contextNode;
- }
-
- NodeListModel(NodeList nodeList, NodeModel contextNode) {
- super(nodeWrapper);
- for (int i = 0; i < nodeList.getLength(); i++) {
- list.add(nodeList.item(i));
- }
- this.contextNode = contextNode;
- }
-
- NodeListModel(NamedNodeMap nodeList, NodeModel contextNode) {
- super(nodeWrapper);
- for (int i = 0; i < nodeList.getLength(); i++) {
- list.add(nodeList.item(i));
- }
- this.contextNode = contextNode;
- }
-
- NodeListModel(List list, NodeModel contextNode) {
- super(list, nodeWrapper);
- this.contextNode = contextNode;
- }
-
- NodeListModel filterByName(String name) throws TemplateModelException {
- NodeListModel result = new NodeListModel(contextNode);
- int size = size();
- if (size == 0) {
- return result;
- }
- Environment env = Environment.getCurrentEnvironment();
- for (int i = 0; i < size; i++) {
- NodeModel nm = (NodeModel) get(i);
- if (nm instanceof ElementModel) {
- if (((ElementModel) nm).matchesName(name, env)) {
- result.add(nm);
- }
- }
- }
- return result;
- }
-
- @Override
- public boolean isEmpty() {
- return size() == 0;
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (size() == 1) {
- NodeModel nm = (NodeModel) get(0);
- return nm.get(key);
- }
- if (key.startsWith("@@")) {
- if (key.equals(AtAtKey.MARKUP.getKey())
- || key.equals(AtAtKey.NESTED_MARKUP.getKey())
- || key.equals(AtAtKey.TEXT.getKey())) {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < size(); i++) {
- NodeModel nm = (NodeModel) get(i);
- TemplateScalarModel textModel = (TemplateScalarModel) nm.get(key);
- result.append(textModel.getAsString());
- }
- return new SimpleScalar(result.toString());
- } else if (key.length() != 2 /* to allow "@@" to fall through */) {
- // As @@... would cause exception in the XPath engine, we throw a nicer exception now.
- if (AtAtKey.containsKey(key)) {
- throw new TemplateModelException(
- "\"" + key + "\" is only applicable to a single XML node, but it was applied on "
- + (size() != 0
- ? size() + " XML nodes (multiple matches)."
- : "an empty list of XML nodes (no matches)."));
- } else {
- throw new TemplateModelException("Unsupported @@ key: " + key);
- }
- }
- }
- if (DomStringUtil.isXMLNameLike(key)
- || ((key.startsWith("@")
- && (DomStringUtil.isXMLNameLike(key, 1) || key.equals("@@") || key.equals("@*"))))
- || key.equals("*") || key.equals("**")) {
- NodeListModel result = new NodeListModel(contextNode);
- for (int i = 0; i < size(); i++) {
- NodeModel nm = (NodeModel) get(i);
- if (nm instanceof ElementModel) {
- TemplateSequenceModel tsm = (TemplateSequenceModel) nm.get(key);
- if (tsm != null) {
- int size = tsm.size();
- for (int j = 0; j < size; j++) {
- result.add(tsm.get(j));
- }
- }
- }
- }
- if (result.size() == 1) {
- return result.get(0);
- }
- return result;
- }
- XPathSupport xps = getXPathSupport();
- if (xps != null) {
- Object context = (size() == 0) ? null : rawNodeList();
- return xps.executeQuery(context, key);
- } else {
- throw new TemplateModelException(
- "Can't try to resolve the XML query key, because no XPath support is available. "
- + "This is either malformed or an XPath expression: " + key);
- }
- }
-
- private List rawNodeList() throws TemplateModelException {
- int size = size();
- ArrayList al = new ArrayList(size);
- for (int i = 0; i < size; i++) {
- al.add(((NodeModel) get(i)).node);
- }
- return al;
- }
-
- XPathSupport getXPathSupport() throws TemplateModelException {
- if (xpathSupport == null) {
- if (contextNode != null) {
- xpathSupport = contextNode.getXPathSupport();
- } else if (size() > 0) {
- xpathSupport = ((NodeModel) get(0)).getXPathSupport();
- }
- }
- return xpathSupport;
- }
-
- @Override
- public Object[] explainTypeError(Class[] expectedClasses) {
- for (Class expectedClass : expectedClasses) {
- if (TemplateScalarModel.class.isAssignableFrom(expectedClass)
- || TemplateDateModel.class.isAssignableFrom(expectedClass)
- || TemplateNumberModel.class.isAssignableFrom(expectedClass)
- || TemplateBooleanModel.class.isAssignableFrom(expectedClass)) {
- return newTypeErrorExplanation("string");
- } else if (TemplateNodeModel.class.isAssignableFrom(expectedClass)) {
- return newTypeErrorExplanation("node");
- }
- }
- return null;
- }
-
- private Object[] newTypeErrorExplanation(String type) {
- return new Object[] {
- "This XML query result can't be used as ", type, " because for that it had to contain exactly "
- + "1 XML node, but it contains ", Integer.valueOf(size()), " nodes. "
- + "That is, the constructing XML query has found ",
- isEmpty()
- ? "no matches."
- : "multiple matches."
- };
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/59412b29/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeModel.java b/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeModel.java
deleted file mode 100644
index ca04d53..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/dom/NodeModel.java
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.model.impl.dom;
-
-
-import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core._CoreLogs;
-import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel;
-import org.apache.freemarker.core.model.AdapterTemplateModel;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateNodeModel;
-import org.apache.freemarker.core.model.TemplateNodeModelEx;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.WrapperTemplateModel;
-import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
-import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.slf4j.Logger;
-import org.w3c.dom.Attr;
-import org.w3c.dom.CDATASection;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Document;
-import org.w3c.dom.DocumentType;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.ProcessingInstruction;
-import org.w3c.dom.Text;
-
-/**
- * A base class for wrapping a single W3C DOM_WRAPPER Node as a FreeMarker template model.
- *
- * <p>
- * Note that {@link DefaultObjectWrapper} automatically wraps W3C DOM_WRAPPER {@link Node}-s into this, so you may need do that
- * with this class manually. However, before dropping the {@link Node}-s into the data-model, you certainly want to
- * apply {@link NodeModel#simplify(Node)} on them.
- *
- * <p>
- * This class is not guaranteed to be thread safe, so instances of this shouldn't be used as shared variable (
- * {@link Configuration#setSharedVariable(String, Object)}).
- *
- * <p>
- * To represent a node sequence (such as a query result) of exactly 1 nodes, this class should be used instead of
- * {@link NodeListModel}, as it adds extra capabilities by utilizing that we have exactly 1 node. If you need to wrap a
- * node sequence of 0 or multiple nodes, you must use {@link NodeListModel}.
- */
-abstract public class NodeModel
-implements TemplateNodeModelEx, TemplateHashModel, TemplateSequenceModel,
- AdapterTemplateModel, WrapperTemplateModel, _UnexpectedTypeErrorExplainerTemplateModel {
-
- static private final Logger LOG = _CoreLogs.DOM_WRAPPER;
-
- private static final Object STATIC_LOCK = new Object();
-
- static private final Map xpathSupportMap = Collections.synchronizedMap(new WeakHashMap());
-
- static private XPathSupport jaxenXPathSupport;
-
- static Class xpathSupportClass;
-
- static {
- try {
- useDefaultXPathSupport();
- } catch (Exception e) {
- // do nothing
- }
- if (xpathSupportClass == null && LOG.isWarnEnabled()) {
- LOG.warn("No XPath support is available.");
- }
- }
-
- /**
- * The W3C DOM_WRAPPER Node being wrapped.
- */
- final Node node;
- private TemplateSequenceModel children;
- private NodeModel parent;
-
- protected NodeModel(Node node) {
- this.node = node;
- }
-
- /**
- * @return the underling W3C DOM_WRAPPER Node object that this TemplateNodeModel
- * is wrapping.
- */
- public Node getNode() {
- return node;
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (key.startsWith("@@")) {
- if (key.equals(AtAtKey.TEXT.getKey())) {
- return new SimpleScalar(getText(node));
- } else if (key.equals(AtAtKey.NAMESPACE.getKey())) {
- String nsURI = node.getNamespaceURI();
- return nsURI == null ? null : new SimpleScalar(nsURI);
- } else if (key.equals(AtAtKey.LOCAL_NAME.getKey())) {
- String localName = node.getLocalName();
- if (localName == null) {
- localName = getNodeName();
- }
- return new SimpleScalar(localName);
- } else if (key.equals(AtAtKey.MARKUP.getKey())) {
- StringBuilder buf = new StringBuilder();
- NodeOutputter nu = new NodeOutputter(node);
- nu.outputContent(node, buf);
- return new SimpleScalar(buf.toString());
- } else if (key.equals(AtAtKey.NESTED_MARKUP.getKey())) {
- StringBuilder buf = new StringBuilder();
- NodeOutputter nu = new NodeOutputter(node);
- nu.outputContent(node.getChildNodes(), buf);
- return new SimpleScalar(buf.toString());
- } else if (key.equals(AtAtKey.QNAME.getKey())) {
- String qname = getQualifiedName();
- return qname != null ? new SimpleScalar(qname) : null;
- } else {
- // As @@... would cause exception in the XPath engine, we throw a nicer exception now.
- if (AtAtKey.containsKey(key)) {
- throw new TemplateModelException(
- "\"" + key + "\" is not supported for an XML node of type \"" + getNodeType() + "\".");
- } else {
- throw new TemplateModelException("Unsupported @@ key: " + key);
- }
- }
- } else {
- XPathSupport xps = getXPathSupport();
- if (xps != null) {
- return xps.executeQuery(node, key);
- } else {
- throw new TemplateModelException(
- "Can't try to resolve the XML query key, because no XPath support is available. "
- + "This is either malformed or an XPath expression: " + key);
- }
- }
- }
-
- @Override
- public TemplateNodeModel getParentNode() {
- if (parent == null) {
- Node parentNode = node.getParentNode();
- if (parentNode == null) {
- if (node instanceof Attr) {
- parentNode = ((Attr) node).getOwnerElement();
- }
- }
- parent = wrap(parentNode);
- }
- return parent;
- }
-
- @Override
- public TemplateNodeModelEx getPreviousSibling() throws TemplateModelException {
- return wrap(node.getPreviousSibling());
- }
-
- @Override
- public TemplateNodeModelEx getNextSibling() throws TemplateModelException {
- return wrap(node.getNextSibling());
- }
-
- @Override
- public TemplateSequenceModel getChildNodes() {
- if (children == null) {
- children = new NodeListModel(node.getChildNodes(), this);
- }
- return children;
- }
-
- @Override
- public final String getNodeType() throws TemplateModelException {
- short nodeType = node.getNodeType();
- switch (nodeType) {
- case Node.ATTRIBUTE_NODE : return "attribute";
- case Node.CDATA_SECTION_NODE : return "text";
- case Node.COMMENT_NODE : return "comment";
- case Node.DOCUMENT_FRAGMENT_NODE : return "document_fragment";
- case Node.DOCUMENT_NODE : return "document";
- case Node.DOCUMENT_TYPE_NODE : return "document_type";
- case Node.ELEMENT_NODE : return "element";
- case Node.ENTITY_NODE : return "entity";
- case Node.ENTITY_REFERENCE_NODE : return "entity_reference";
- case Node.NOTATION_NODE : return "notation";
- case Node.PROCESSING_INSTRUCTION_NODE : return "pi";
- case Node.TEXT_NODE : return "text";
- }
- throw new TemplateModelException("Unknown node type: " + nodeType + ". This should be impossible!");
- }
-
- public TemplateModel exec(List args) throws TemplateModelException {
- if (args.size() != 1) {
- throw new TemplateModelException("Expecting exactly one arguments");
- }
- String query = (String) args.get(0);
- // Now, we try to behave as if this is an XPath expression
- XPathSupport xps = getXPathSupport();
- if (xps == null) {
- throw new TemplateModelException("No XPath support available");
- }
- return xps.executeQuery(node, query);
- }
-
- /**
- * Always returns 1.
- */
- @Override
- public final int size() {
- return 1;
- }
-
- @Override
- public final TemplateModel get(int i) {
- return i == 0 ? this : null;
- }
-
- @Override
- public String getNodeNamespace() {
- int nodeType = node.getNodeType();
- if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.ELEMENT_NODE) {
- return null;
- }
- String result = node.getNamespaceURI();
- if (result == null && nodeType == Node.ELEMENT_NODE) {
- result = "";
- } else if ("".equals(result) && nodeType == Node.ATTRIBUTE_NODE) {
- result = null;
- }
- return result;
- }
-
- @Override
- public final int hashCode() {
- return node.hashCode();
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == null) return false;
- return other.getClass() == getClass()
- && ((NodeModel) other).node.equals(node);
- }
-
- /**
- * Creates a {@link NodeModel} from a DOM {@link Node}. It's strongly recommended modify the {@link Node} with
- * {@link #simplify(Node)}, so the DOM will be easier to process in templates.
- *
- * @param node
- * The DOM node to wrap. This is typically an {@link Element} or a {@link Document}, but all kind of node
- * types are supported. If {@code null}, {@code null} will be returned.
- */
- static public NodeModel wrap(Node node) {
- if (node == null) {
- return null;
- }
- NodeModel result = null;
- switch (node.getNodeType()) {
- case Node.DOCUMENT_NODE : result = new DocumentModel((Document) node); break;
- case Node.ELEMENT_NODE : result = new ElementModel((Element) node); break;
- case Node.ATTRIBUTE_NODE : result = new AttributeNodeModel((Attr) node); break;
- case Node.CDATA_SECTION_NODE :
- case Node.COMMENT_NODE :
- case Node.TEXT_NODE : result = new CharacterDataNodeModel((org.w3c.dom.CharacterData) node); break;
- case Node.PROCESSING_INSTRUCTION_NODE : result = new PINodeModel((ProcessingInstruction) node); break;
- case Node.DOCUMENT_TYPE_NODE : result = new DocumentTypeModel((DocumentType) node); break;
- default: throw new IllegalArgumentException(
- "Unsupported node type: " + node.getNodeType() + " ("
- + node.getClass().getName() + ")");
- }
- return result;
- }
-
- /**
- * Recursively removes all comment nodes from the subtree.
- *
- * @see #simplify
- */
- static public void removeComments(Node parent) {
- Node child = parent.getFirstChild();
- while (child != null) {
- Node nextSibling = child.getNextSibling();
- if (child.getNodeType() == Node.COMMENT_NODE) {
- parent.removeChild(child);
- } else if (child.hasChildNodes()) {
- removeComments(child);
- }
- child = nextSibling;
- }
- }
-
- /**
- * Recursively removes all processing instruction nodes from the subtree.
- *
- * @see #simplify
- */
- static public void removePIs(Node parent) {
- Node child = parent.getFirstChild();
- while (child != null) {
- Node nextSibling = child.getNextSibling();
- if (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
- parent.removeChild(child);
- } else if (child.hasChildNodes()) {
- removePIs(child);
- }
- child = nextSibling;
- }
- }
-
- /**
- * Merges adjacent text nodes (where CDATA counts as text node too). Operates recursively on the entire subtree.
- * The merged node will have the type of the first node of the adjacent merged nodes.
- *
- * <p>Because XPath assumes that there are no adjacent text nodes in the tree, not doing this can have
- * undesirable side effects. Xalan queries like {@code text()} will only return the first of a list of matching
- * adjacent text nodes instead of all of them, while Jaxen will return all of them as intuitively expected.
- *
- * @see #simplify
- */
- static public void mergeAdjacentText(Node parent) {
- mergeAdjacentText(parent, new StringBuilder(0));
- }
-
- static private void mergeAdjacentText(Node parent, StringBuilder collectorBuf) {
- Node child = parent.getFirstChild();
- while (child != null) {
- Node next = child.getNextSibling();
- if (child instanceof Text) {
- boolean atFirstText = true;
- while (next instanceof Text) { //
- if (atFirstText) {
- collectorBuf.setLength(0);
- collectorBuf.ensureCapacity(child.getNodeValue().length() + next.getNodeValue().length());
- collectorBuf.append(child.getNodeValue());
- atFirstText = false;
- }
- collectorBuf.append(next.getNodeValue());
-
- parent.removeChild(next);
-
- next = child.getNextSibling();
- }
- if (!atFirstText && collectorBuf.length() != 0) {
- ((CharacterData) child).setData(collectorBuf.toString());
- }
- } else {
- mergeAdjacentText(child, collectorBuf);
- }
- child = next;
- }
- }
-
- /**
- * Removes all comments and processing instruction, and unites adjacent text nodes (here CDATA counts as text as
- * well). This is similar to applying {@link #removeComments(Node)}, {@link #removePIs(Node)}, and finally
- * {@link #mergeAdjacentText(Node)}, but it does all that somewhat faster.
- */
- static public void simplify(Node parent) {
- simplify(parent, new StringBuilder(0));
- }
-
- static private void simplify(Node parent, StringBuilder collectorTextChildBuff) {
- Node collectorTextChild = null;
- Node child = parent.getFirstChild();
- while (child != null) {
- Node next = child.getNextSibling();
- if (child.hasChildNodes()) {
- if (collectorTextChild != null) {
- // Commit pending text node merge:
- if (collectorTextChildBuff.length() != 0) {
- ((CharacterData) collectorTextChild).setData(collectorTextChildBuff.toString());
- collectorTextChildBuff.setLength(0);
- }
- collectorTextChild = null;
- }
-
- simplify(child, collectorTextChildBuff);
- } else {
- int type = child.getNodeType();
- if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE ) {
- if (collectorTextChild != null) {
- if (collectorTextChildBuff.length() == 0) {
- collectorTextChildBuff.ensureCapacity(
- collectorTextChild.getNodeValue().length() + child.getNodeValue().length());
- collectorTextChildBuff.append(collectorTextChild.getNodeValue());
- }
- collectorTextChildBuff.append(child.getNodeValue());
- parent.removeChild(child);
- } else {
- collectorTextChild = child;
- collectorTextChildBuff.setLength(0);
- }
- } else if (type == Node.COMMENT_NODE) {
- parent.removeChild(child);
- } else if (type == Node.PROCESSING_INSTRUCTION_NODE) {
- parent.removeChild(child);
- } else if (collectorTextChild != null) {
- // Commit pending text node merge:
- if (collectorTextChildBuff.length() != 0) {
- ((CharacterData) collectorTextChild).setData(collectorTextChildBuff.toString());
- collectorTextChildBuff.setLength(0);
- }
- collectorTextChild = null;
- }
- }
- child = next;
- }
-
- if (collectorTextChild != null) {
- // Commit pending text node merge:
- if (collectorTextChildBuff.length() != 0) {
- ((CharacterData) collectorTextChild).setData(collectorTextChildBuff.toString());
- collectorTextChildBuff.setLength(0);
- }
- }
- }
-
- NodeModel getDocumentNodeModel() {
- if (node instanceof Document) {
- return this;
- } else {
- return wrap(node.getOwnerDocument());
- }
- }
-
- /**
- * Tells the system to use (restore) the default (initial) XPath system used by
- * this FreeMarker version on this system.
- */
- static public void useDefaultXPathSupport() {
- synchronized (STATIC_LOCK) {
- xpathSupportClass = null;
- jaxenXPathSupport = null;
- try {
- useXalanXPathSupport();
- } catch (Exception e) {
- // ignore
- }
- if (xpathSupportClass == null) try {
- useSunInternalXPathSupport();
- } catch (Exception e) {
- // ignore
- }
- if (xpathSupportClass == null) try {
- useJaxenXPathSupport();
- } catch (Exception e) {
- // ignore
- }
- }
- }
-
- /**
- * Convenience method. Tells the system to use Jaxen for XPath queries.
- * @throws Exception if the Jaxen classes are not present.
- */
- static public void useJaxenXPathSupport() throws Exception {
- Class.forName("org.jaxen.dom.DOMXPath");
- Class c = Class.forName("org.apache.freemarker.core.model.impl.dom.JaxenXPathSupport");
- jaxenXPathSupport = (XPathSupport) c.newInstance();
- synchronized (STATIC_LOCK) {
- xpathSupportClass = c;
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("Using Jaxen classes for XPath support");
- }
- }
-
- /**
- * Convenience method. Tells the system to use Xalan for XPath queries.
- * @throws Exception if the Xalan XPath classes are not present.
- */
- static public void useXalanXPathSupport() throws Exception {
- Class.forName("org.apache.xpath.XPath");
- Class c = Class.forName("org.apache.freemarker.core.model.impl.dom.XalanXPathSupport");
- synchronized (STATIC_LOCK) {
- xpathSupportClass = c;
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("Using Xalan classes for XPath support");
- }
- }
-
- static public void useSunInternalXPathSupport() throws Exception {
- Class.forName("com.sun.org.apache.xpath.internal.XPath");
- Class c = Class.forName("org.apache.freemarker.core.model.impl.dom.SunInternalXalanXPathSupport");
- synchronized (STATIC_LOCK) {
- xpathSupportClass = c;
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("Using Sun's internal Xalan classes for XPath support");
- }
- }
-
- /**
- * Set an alternative implementation of org.apache.freemarker.core.model.impl.dom.XPathSupport to use
- * as the XPath engine.
- * @param cl the class, or <code>null</code> to disable XPath support.
- */
- static public void setXPathSupportClass(Class cl) {
- if (cl != null && !XPathSupport.class.isAssignableFrom(cl)) {
- throw new RuntimeException("Class " + cl.getName()
- + " does not implement org.apache.freemarker.core.model.impl.dom.XPathSupport");
- }
- synchronized (STATIC_LOCK) {
- xpathSupportClass = cl;
- }
- }
-
- /**
- * Get the currently used org.apache.freemarker.core.model.impl.dom.XPathSupport used as the XPath engine.
- * Returns <code>null</code> if XPath support is disabled.
- */
- static public Class getXPathSupportClass() {
- synchronized (STATIC_LOCK) {
- return xpathSupportClass;
- }
- }
-
- static private String getText(Node node) {
- String result = "";
- if (node instanceof Text || node instanceof CDATASection) {
- result = ((org.w3c.dom.CharacterData) node).getData();
- } else if (node instanceof Element) {
- NodeList children = node.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- result += getText(children.item(i));
- }
- } else if (node instanceof Document) {
- result = getText(((Document) node).getDocumentElement());
- }
- return result;
- }
-
- XPathSupport getXPathSupport() {
- if (jaxenXPathSupport != null) {
- return jaxenXPathSupport;
- }
- XPathSupport xps = null;
- Document doc = node.getOwnerDocument();
- if (doc == null) {
- doc = (Document) node;
- }
- synchronized (doc) {
- WeakReference ref = (WeakReference) xpathSupportMap.get(doc);
- if (ref != null) {
- xps = (XPathSupport) ref.get();
- }
- if (xps == null) {
- try {
- xps = (XPathSupport) xpathSupportClass.newInstance();
- xpathSupportMap.put(doc, new WeakReference(xps));
- } catch (Exception e) {
- LOG.error("Error instantiating xpathSupport class", e);
- }
- }
- }
- return xps;
- }
-
-
- String getQualifiedName() throws TemplateModelException {
- return getNodeName();
- }
-
- @Override
- public Object getAdaptedObject(Class hint) {
- return node;
- }
-
- @Override
- public Object getWrappedObject() {
- return node;
- }
-
- @Override
- public Object[] explainTypeError(Class[] expectedClasses) {
- for (Class expectedClass : expectedClasses) {
- if (TemplateDateModel.class.isAssignableFrom(expectedClass)
- || TemplateNumberModel.class.isAssignableFrom(expectedClass)
- || TemplateBooleanModel.class.isAssignableFrom(expectedClass)) {
- return new Object[]{
- "XML node values are always strings (text), that is, they can't be used as number, "
- + "date/time/datetime or boolean without explicit conversion (such as "
- + "someNode?number, someNode?datetime.xs, someNode?date.xs, someNode?time.xs, "
- + "someNode?boolean).",
- };
- }
- }
- return null;
- }
-
-}