1 /*
2  * Copyright (c) 2001-2004 World Wide Web Consortium,
3  * (Massachusetts Institute of Technology, Institut National de
4  * Recherche en Informatique et en Automatique, Keio University). All
5  * Rights Reserved. This program is distributed under the W3C's Software
6  * Intellectual Property License. This program is distributed in the
7  * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
8  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9  * PURPOSE.
10  * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
11  */
12 
13 package org.w3c.domts;
14 
15 import java.lang.reflect.Method;
16 import java.util.ArrayList;
17 import java.util.List;
18 
19 import org.w3c.dom.DOMImplementation;
20 import org.w3c.dom.Document;
21 
22 /**
23  * This class represents a particular parser and configuration
24  * (such as entity-expanding, non-validating, whitespace ignoring)
25  * for a test session.  Individual tests or suites within a
26  * session can override the session properties on a call to
27  * createBuilderFactory.
28  *
29  * @author Curt Arnold
30  */
31 public abstract class DOMTestDocumentBuilderFactory {
32   /**
33    *   Parser configuration
34    */
35   private final DocumentBuilderSetting[] settings;
36 
37   /**
38    *   Constructor
39    *   @param properties Array of parser settings, may be null.
40    */
DOMTestDocumentBuilderFactory(DocumentBuilderSetting[] settings)41   public DOMTestDocumentBuilderFactory(DocumentBuilderSetting[] settings) throws
42       DOMTestIncompatibleException {
43     if (settings == null) {
44       this.settings = new DocumentBuilderSetting[0];
45     }
46     else {
47       this.settings = (DocumentBuilderSetting[]) settings.clone();
48     }
49   }
50 
51   /**
52    *   Returns an instance of DOMTestDocumentBuilderFactory
53    *   with the settings from the argument list
54    *   and any non-revoked settings from the current object.
55    *   @param settings array of settings, may be null.
56    */
newInstance( DocumentBuilderSetting[] settings)57   public abstract DOMTestDocumentBuilderFactory newInstance(
58       DocumentBuilderSetting[] settings) throws DOMTestIncompatibleException;
59 
getDOMImplementation()60   public abstract DOMImplementation getDOMImplementation();
61 
hasFeature(String feature, String version)62   public abstract boolean hasFeature(String feature, String version);
63 
load(java.net.URL url)64   public abstract Document load(java.net.URL url) throws DOMTestLoadException;
65 
66   /**
67    *  Creates XPath evaluator
68    *  @param doc DOM document, may not be null
69    */
createXPathEvaluator(Document doc)70   public Object createXPathEvaluator(Document doc) {
71     try {
72       Method getFeatureMethod = doc.getClass().getMethod("getFeature",
73           new Class[] {String.class, String.class});
74       if (getFeatureMethod != null) {
75         return getFeatureMethod.invoke(doc, new Object[] {"XPath", null});
76       }
77     }
78     catch (Exception ex) {
79     }
80     return doc;
81   }
82 
83   /**
84    *   Merges the settings from the specific test case or suite
85    *   with the existing (typically session) settings.
86    *   @param settings new settings, may be null which will
87    *   return clone of existing settings.
88    */
mergeSettings(DocumentBuilderSetting[] newSettings)89   protected DocumentBuilderSetting[] mergeSettings(DocumentBuilderSetting[]
90       newSettings) {
91     if (newSettings == null) {
92       return (DocumentBuilderSetting[]) settings.clone();
93     }
94     List mergedSettings = new ArrayList(settings.length + newSettings.length);
95     //
96     //    all new settings are respected
97     //
98     for (int i = 0; i < newSettings.length; i++) {
99       mergedSettings.add(newSettings[i]);
100     }
101     //
102     //    for all previous settings, take only those that
103     //       do not conflict with existing settings
104     for (int i = 0; i < settings.length; i++) {
105       DocumentBuilderSetting setting = settings[i];
106       boolean hasConflict = false;
107       for (int j = 0; j < newSettings.length; j++) {
108         DocumentBuilderSetting newSetting = newSettings[j];
109         if (newSetting.hasConflict(setting) || setting.hasConflict(newSetting)) {
110           hasConflict = true;
111           break;
112         }
113       }
114       if (!hasConflict) {
115         mergedSettings.add(setting);
116       }
117     }
118 
119     DocumentBuilderSetting[] mergedArray =
120         new DocumentBuilderSetting[mergedSettings.size()];
121     for (int i = 0; i < mergedSettings.size(); i++) {
122       mergedArray[i] = (DocumentBuilderSetting) mergedSettings.get(i);
123     }
124     return mergedArray;
125   }
126 
addExtension(String testFileName)127   public String addExtension(String testFileName) {
128     String contentType = getContentType();
129     if ("text/html".equals(contentType)) {
130       return testFileName + ".html";
131     }
132     if ("image/svg+xml".equals(contentType)) {
133       return testFileName + ".svg";
134     }
135     if ("application/xhtml+xml".equals(contentType)) {
136       return testFileName + ".xhtml";
137     }
138     return testFileName + ".xml";
139   }
140 
isCoalescing()141   public abstract boolean isCoalescing();
142 
isExpandEntityReferences()143   public abstract boolean isExpandEntityReferences();
144 
isIgnoringElementContentWhitespace()145   public abstract boolean isIgnoringElementContentWhitespace();
146 
isNamespaceAware()147   public abstract boolean isNamespaceAware();
148 
isValidating()149   public abstract boolean isValidating();
150 
getContentType()151   public String getContentType() {
152     return System.getProperty("org.w3c.domts.contentType", "text/xml");
153   }
154 
155   /**
156    * Creates an array of all determinable settings for the DocumentBuilder
157    * including those at implementation defaults.
158    * @param builder must not be null
159    */
getActualSettings()160   public final DocumentBuilderSetting[] getActualSettings() {
161 
162     DocumentBuilderSetting[] allSettings = new DocumentBuilderSetting[] {
163         DocumentBuilderSetting.coalescing,
164         DocumentBuilderSetting.expandEntityReferences,
165         DocumentBuilderSetting.hasNullString,
166         DocumentBuilderSetting.ignoringElementContentWhitespace,
167         DocumentBuilderSetting.namespaceAware,
168         DocumentBuilderSetting.signed,
169         DocumentBuilderSetting.validating,
170         DocumentBuilderSetting.notCoalescing,
171         DocumentBuilderSetting.notExpandEntityReferences,
172         DocumentBuilderSetting.notHasNullString,
173         DocumentBuilderSetting.notIgnoringElementContentWhitespace,
174         DocumentBuilderSetting.notNamespaceAware,
175         DocumentBuilderSetting.notSigned,
176         DocumentBuilderSetting.notValidating
177     };
178 
179     List list = new ArrayList(allSettings.length / 2);
180     for (int i = 0; i < allSettings.length; i++) {
181       if (allSettings[i].hasSetting(this)) {
182         list.add(allSettings[i]);
183       }
184     }
185     DocumentBuilderSetting[] settings = new DocumentBuilderSetting[list.size()];
186     for (int i = 0; i < settings.length; i++) {
187       settings[i] = (DocumentBuilderSetting) list.get(i);
188     }
189     return settings;
190   }
191 
192 }
193