Project

Profile

Help

Revision 2de52089

Added by Michael Kay over 1 year ago

Migrate 10.0 bug fixes from development branch to released 10.0 repositories (os and priv)

View differences:

latest10/hej/net/sf/saxon/Configuration.java
4003 4003
        return pipe;
4004 4004
    }
4005 4005

  
4006
    /**
4007
     * Make a SchemaURIResolver that wraps a supplied URIResolver
4008
     *
4009
     * @return a new SchemaURIResolver (or null if this is not an EnterpriseConfiguration)
4010
     * @since 10.0
4011
     */
4012

  
4013
    public SchemaURIResolver makeSchemaURIResolver(URIResolver resolver) {
4014
        return null;
4015
    }
4016

  
4006 4017
    /**
4007 4018
     * Get the configuration, given the context. This is provided as a static method to make it accessible
4008 4019
     * as an extension function.
latest10/hej/net/sf/saxon/Gizmo.java
8 8
package net.sf.saxon;
9 9

  
10 10
import net.sf.saxon.event.Builder;
11
import net.sf.saxon.event.ComplexContentOutputter;
11 12
import net.sf.saxon.event.PipelineConfiguration;
12 13
import net.sf.saxon.event.Receiver;
13 14
import net.sf.saxon.expr.parser.Loc;
......
230 231
        env.declareNamespace("array", NamespaceConstant.ARRAY_FUNCTIONS);
231 232
        env.declareNamespace("", "");
232 233

  
233
        env.setUnprefixedElementPolicy(UnprefixedElementMatchingPolicy.ANY_NAMESPACE);
234
        env.setUnprefixedElementMatchingPolicy(UnprefixedElementMatchingPolicy.ANY_NAMESPACE);
234 235

  
235 236
        System.out.println("Saxon Gizmo " + Version.getProductVersion());
236 237
        executeCommands(talker, interactive);
......
300 301
                SubCommand cmd = subCommands.get(keyword);
301 302
                if (cmd == null) {
302 303
                    if (interactive) {
303
                        System.out.println("Unknown command " + cmd + " (Use 'quit' to exit)");
304
                        System.out.println("Unknown command " + keyword + " (Use 'quit' to exit)");
304 305
                        help(new StringBuffer("?"));
305 306
                    } else {
306 307
                        throw new XPathException("\"Unknown command \" + cmd + \"");
......
773 774

  
774 775
        GroundedValue value = getSelectedItems(new StringBuffer(buffer.substring(ws + 1)), Token.EOF).materialize();
775 776
        if (varName.equals(".")) {
776
            if (!(value.getLength() == 1) && value.itemAt(0) instanceof DocumentImpl) {
777
                throw new XPathException("Value for context item must be a single document node");
778
            }
779 777
            saveCurrentDoc();
780
            currentDoc = (DocumentImpl) value.itemAt(0);
778
            if (value.getLength() == 1 && value.itemAt(0) instanceof DocumentImpl) {
779
                currentDoc = (DocumentImpl) value.itemAt(0);
780
            } else {
781
                try {
782
                    Builder builder = new LinkedTreeBuilder(config.makePipelineConfiguration());
783
                    ComplexContentOutputter cco = new ComplexContentOutputter(builder);
784
                    cco.open();
785
                    cco.startDocument(0);
786
                    for (Item it : value.asIterable()) {
787
                        cco.append(it);
788
                    }
789
                    cco.endDocument();
790
                    cco.close();
791
                    currentDoc = (DocumentImpl) builder.getCurrentRoot();
792
                } catch (XPathException e) {
793
                    throw new XPathException("Cannot save the value as a document (" + e.getMessage() + ")");
794
                }
795
            }
796

  
781 797
        } else {
782 798
            StructuredQName name = getQName(varName);
783 799
            variables.put(name, value);
......
838 854
        for (Item item : value.asIterable()) {
839 855
            if (item instanceof NodeInfo) {
840 856
                System.out.println(QueryResult.serialize((NodeInfo) item));
841
            } else {
857
            } else if (item instanceof AtomicValue) {
842 858
                System.out.println(item.getStringValue());
859
            } else {
860
                StringWriter sw = new StringWriter();
861
                SerializationProperties props = new SerializationProperties();
862
                props.setProperty("method", "adaptive");
863
                Receiver r = config.getSerializerFactory().getReceiver(new StreamResult(sw), props);
864
                r.append(item);
865
                System.out.println(sw.toString());
843 866
            }
844 867
        }
845 868
    }
latest10/hej/net/sf/saxon/dom/DOMAttributeMap.java
9 9

  
10 10
import net.sf.saxon.Configuration;
11 11
import net.sf.saxon.lib.NamespaceConstant;
12
import net.sf.saxon.om.AxisInfo;
13
import net.sf.saxon.om.NamespaceBinding;
14
import net.sf.saxon.om.NodeInfo;
12
import net.sf.saxon.om.*;
15 13
import net.sf.saxon.tree.NamespaceNode;
16 14
import net.sf.saxon.tree.iter.AxisIterator;
15
import net.sf.saxon.type.Type;
17 16
import org.w3c.dom.DOMException;
18 17
import org.w3c.dom.NamedNodeMap;
19 18
import org.w3c.dom.Node;
......
26 25

  
27 26
class DOMAttributeMap implements NamedNodeMap {
28 27

  
29
    private NodeInfo parent;
30
    private NamespaceBinding[] namespaceBindings;
28
    private NodeInfo element;
29
    private NamespaceBinding[] namespaceDeltas;
31 30
    private boolean excludeNamespaceUndeclarations;
32 31

  
33 32
    /**
34 33
     * Construct an AttributeMap for a given element node
35 34
     *
36
     * @param parent the element node owning the attributes
35
     * @param element the element node owning the attributes
37 36
     */
38 37

  
39
    public DOMAttributeMap(NodeInfo parent) {
40
        this.parent = parent;
41
        if (parent.getConfiguration().getXMLVersion() == Configuration.XML10) {
38
    public DOMAttributeMap(NodeInfo element) {
39
        this.element = element;
40
        if (element.getConfiguration().getXMLVersion() == Configuration.XML10) {
42 41
            excludeNamespaceUndeclarations = true;
43 42
        }
44 43
    }
45 44

  
46 45
    /**
47
     * Filter out namespace undeclarations (other than the undeclaration of the default namespace)
46
     * Filter out redundant namespace declarations, and namespace undeclarations
47
     * (other than the undeclaration of the default namespace)
48 48
     */
49 49

  
50
    private NamespaceBinding[] removeUndeclarations(NamespaceBinding[] bindings) {
51
        if (excludeNamespaceUndeclarations) {
52
            int keep = 0;
53
            for (NamespaceBinding b : bindings) {
54
                if (b != null && (b.getPrefix().isEmpty() || !b.getURI().isEmpty())) {
55
                    keep++;
56
                }
57
            }
58
            NamespaceBinding[] b2 = new NamespaceBinding[keep];
59
            keep = 0;
60
            for (NamespaceBinding b : bindings) {
61
                if (b != null && (b.getPrefix().isEmpty() || !b.getURI().isEmpty())) {
62
                    b2[keep++] = b;
63
                }
64
            }
65
            return b2;
50
    private NamespaceBinding[] getNamespaceDeltas() {
51
        NamespaceMap allNamespaces = element.getAllNamespaces();
52
        NamespaceBinding[] bindings;
53
        NodeInfo parent = element.getParent();
54
        if (parent != null && parent.getNodeKind() == Type.ELEMENT) {
55
            bindings = allNamespaces.getDifferences(parent.getAllNamespaces(), !excludeNamespaceUndeclarations);
66 56
        } else {
67
            return bindings;
57
            bindings = allNamespaces.getNamespaceBindings();
68 58
        }
59
        return bindings;
69 60
    }
70 61

  
71 62
    /**
......
79 70
                if (nsarray[i] == null) {
80 71
                    return null;
81 72
                } else if (nsarray[i].getPrefix().isEmpty()) {
82
                    NamespaceNode nn = new NamespaceNode(parent, nsarray[i], i + 1);
73
                    NamespaceNode nn = new NamespaceNode(element, nsarray[i], i + 1);
83 74
                    return NodeOverNodeInfo.wrap(nn);
84 75
                }
85 76
            }
......
91 82
                if (nsarray[i] == null) {
92 83
                    return null;
93 84
                } else if (prefix.equals(nsarray[i].getPrefix())) {
94
                    NamespaceNode nn = new NamespaceNode(parent, nsarray[i], i + 1);
85
                    NamespaceNode nn = new NamespaceNode(element, nsarray[i], i + 1);
95 86
                    return NodeOverNodeInfo.wrap(nn);
96 87
                }
97 88
            }
98 89
            return null;
99 90
        } else {
100
            AxisIterator atts = parent.iterateAxis(AxisInfo.ATTRIBUTE, att -> att.getDisplayName().equals(name));
91
            AxisIterator atts = element.iterateAxis(AxisInfo.ATTRIBUTE, att -> att.getDisplayName().equals(name));
101 92
            NodeInfo att = atts.next();
102 93
            return att == null ? null : NodeOverNodeInfo.wrap(att);
103 94
        }
......
118 109

  
119 110
        if (index < namespaces.length) {
120 111
            NamespaceBinding ns = namespaces[index];
121
            NamespaceNode nn = new NamespaceNode(parent, ns, index);
112
            NamespaceNode nn = new NamespaceNode(element, ns, index);
122 113
            return NodeOverNodeInfo.wrap(nn);
123 114
        }
124 115
        int pos = 0;
125 116
        int attNr = index - namespaces.length;
126
        AxisIterator atts = parent.iterateAxis(AxisInfo.ATTRIBUTE);
117
        AxisIterator atts = element.iterateAxis(AxisInfo.ATTRIBUTE);
127 118
        NodeInfo att;
128 119
        while ((att = atts.next()) != null) {
129 120
            if (pos == attNr) {
......
161 152
    }
162 153

  
163 154
    private NamespaceBinding[] getNamespaceBindings() {
164
        if (namespaceBindings == null) {
165
            namespaceBindings = removeUndeclarations(parent.getDeclaredNamespaces(null));
155
        if (namespaceDeltas == null) {
156
            namespaceDeltas = getNamespaceDeltas();
166 157
        }
167
        return namespaceBindings;
158
        return namespaceDeltas;
168 159
    }
169 160

  
170 161
    /**
......
173 164

  
174 165
    public int getLength() {
175 166
        int length = 0;
176
        AxisIterator atts = parent.iterateAxis(AxisInfo.ATTRIBUTE);
167
        AxisIterator atts = element.iterateAxis(AxisInfo.ATTRIBUTE);
177 168
        while (atts.next() != null) {
178 169
            length++;
179 170
        }
......
194 185
        if (uri.equals("") && localName.equals("xmlns")) {
195 186
            return getNamedItem("xmlns");
196 187
        }
197
        AxisIterator atts = parent.iterateAxis(AxisInfo.ATTRIBUTE);
188
        AxisIterator atts = element.iterateAxis(AxisInfo.ATTRIBUTE);
198 189
        while (true) {
199 190
            NodeInfo att = atts.next();
200 191
            if (att == null) {
latest10/hej/net/sf/saxon/dom/DOMWriter.java
148 148

  
149 149
            NamespaceMap parentNamespaces = nsStack.peek();
150 150
            if (namespaces != parentNamespaces) {
151
                NamespaceBinding[] declarations = namespaces.getDifferences(parentNamespaces);
151
                NamespaceBinding[] declarations = namespaces.getDifferences(parentNamespaces, false);
152 152
                for (NamespaceBinding ns : declarations) {
153 153
                    String prefix = ns.getPrefix();
154 154
                    String nsuri = ns.getURI();
latest10/hej/net/sf/saxon/dom/ElementOverNodeInfo.java
7 7

  
8 8
package net.sf.saxon.dom;
9 9

  
10
import net.sf.saxon.lib.NamespaceConstant;
10 11
import net.sf.saxon.om.AxisInfo;
11 12
import net.sf.saxon.om.NamePool;
12 13
import net.sf.saxon.om.NodeInfo;
......
29 30

  
30 31
public class ElementOverNodeInfo extends NodeOverNodeInfo implements Element {
31 32

  
33
    private DOMAttributeMap attributeMap = null;
34

  
32 35
    /**
33 36
     * The name of the element (DOM interface).
34 37
     */
......
69 72
        return DocumentOverNodeInfo.getElementsByTagNameNS(node, namespaceURI, localName);
70 73
    }
71 74

  
75
    /**
76
     * Return a <code>NamedNodeMap</code> containing the attributes of this node (if
77
     * it is an <code>Element</code>) or <code>null</code> otherwise. Note that
78
     * namespace declarations are treated as attributes.
79
     */
80

  
81
    public NamedNodeMap getAttributes() {
82
        if (attributeMap == null) {
83
            attributeMap = new DOMAttributeMap(node);
84
        }
85
        return attributeMap;
86
    }
87

  
72 88
    /**
73 89
     * Retrieves an attribute value by name.
74
     * This implementation does not expose namespace nodes as attributes.
75 90
     *
76 91
     * @param name The QName of the attribute to retrieve.
77 92
     * @return The <code>Attr</code> value as a string, or the empty string if
......
79 94
     */
80 95

  
81 96
    public String getAttribute(String name) {
97
        if (name.startsWith("xmlns")) {
98
            Node node = getAttributes().getNamedItem(name);
99
            return node == null ? "" : node.getNodeValue();
100
        }
82 101
        AxisIterator atts = node.iterateAxis(AxisInfo.ATTRIBUTE);
83 102
        while (true) {
84 103
            NodeInfo att = atts.next();
......
97 116

  
98 117
    /**
99 118
     * Retrieves an attribute node by name.
100
     * This implementation does not expose namespace nodes as attributes.
101 119
     * <br> To retrieve an attribute node by qualified name and namespace URI,
102 120
     * use the <code>getAttributeNodeNS</code> method.
103 121
     *
......
166 184
     */
167 185

  
168 186
    public String getAttributeNS(String namespaceURI, String localName) {
187
        if (NamespaceConstant.XMLNS.equals(namespaceURI)) {
188
            Node node = getAttributes().getNamedItemNS(namespaceURI, localName);
189
            return node == null ? "" : node.getNodeValue();
190
        }
169 191
        String uri = namespaceURI == null ? "" : namespaceURI;
170 192
        String val = node.getAttributeValue(uri, localName);
171 193
        if (val == null) {
......
260 282
     * Returns <code>true</code> when an attribute with a given name is
261 283
     * specified on this element or has a default value, <code>false</code>
262 284
     * otherwise.
263
     * This implementation does not expose namespace nodes as attributes.
264 285
     *
265 286
     * @param name The name of the attribute to look for.
266 287
     * @return <code>true</code> if an attribute with the given name is
......
270 291
     */
271 292

  
272 293
    public boolean hasAttribute(String name) {
294
        if (name.startsWith("xmlns")) {
295
            Node node = getAttributes().getNamedItem(name);
296
            return node != null;
297
        }
273 298
        AxisIterator atts = node.iterateAxis(AxisInfo.ATTRIBUTE);
274 299
        while (true) {
275 300
            NodeInfo att = atts.next();
......
286 311
     * Returns <code>true</code> when an attribute with a given local name
287 312
     * and namespace URI is specified on this element or has a default value,
288 313
     * <code>false</code> otherwise.
289
     * This implementation does not expose namespace nodes as attributes.
290 314
     *
291 315
     * @param namespaceURI The  namespace URI of the attribute to look for.
292 316
     * @param localName    The  local name of the attribute to look for.
......
297 321
     */
298 322

  
299 323
    public boolean hasAttributeNS(String namespaceURI, String localName) {
324
        if (NamespaceConstant.XMLNS.equals(namespaceURI)) {
325
            Node node = getAttributes().getNamedItemNS(namespaceURI, localName);
326
            return node != null;
327
        }
300 328
        String uri = namespaceURI == null ? "" : namespaceURI;
301 329
        return node.getAttributeValue(uri, localName) != null;
302 330
    }
latest10/hej/net/sf/saxon/dom/NodeOverNodeInfo.java
342 342

  
343 343
    /**
344 344
     * Return a <code>NamedNodeMap</code> containing the attributes of this node (if
345
     * it is an <code>Element</code>) or <code>null</code> otherwise. Note that this
346
     * implementation changed in Saxon 8.8 to treat namespace declarations as attributes.
345
     * it is an <code>Element</code>) or <code>null</code> otherwise.
347 346
     */
348 347

  
349 348
    public NamedNodeMap getAttributes() {
350
        if (node.getNodeKind() == Type.ELEMENT) {
351
            return new DOMAttributeMap(node);
352
        } else {
353
            return null;
354
        }
349
        return null;
355 350
    }
356 351

  
357 352
    /**
latest10/hej/net/sf/saxon/event/Builder.java
58 58
    protected NamePool namePool;
59 59
    protected String systemId;
60 60
    protected String baseURI;
61
    protected boolean uniformBaseURI = true;
61 62
    protected NodeInfo currentRoot;
62 63
    protected boolean lineNumbering = false;
63 64
    protected boolean useEventLocation = true;
latest10/hej/net/sf/saxon/event/ComplexContentOutputter.java
463 463
     * by further calls on {@link #attribute(NodeName, SimpleType, CharSequence, Location, int)} or
464 464
     * {@link #namespace} to define further attributes and namespaces.
465 465
     *
466
     * <p>This version of the method does not perform namespace fixup for prefixes used in the element
467
     * name or attribute names; it is assumed that these prefixes are declared within the namespace map,
468
     * and that there are no conflicts. The method does, however, perform namespace inheritance: that is,
469
     * unless {@code properties} includes {@link ReceiverOption#DISINHERIT_NAMESPACES}, namespaces
470
     * declared on the parent element and not overridden are implicitly added to the namespace map.</p>
471
     *
466 472
     * @param elemName   the name of the element.
467 473
     * @param type       the type annotation of the element.
468 474
     * @param attributes the attributes of this element
latest10/hej/net/sf/saxon/event/RegularSequenceChecker.java
78 78

  
79 79
    private Stack<Short> stack = new Stack<>();
80 80

  
81
    public enum State {Initial, Open, StartTag, Content, Final}
81
    public enum State {Initial, Open, StartTag, Content, Final, Failed}
82 82
    // StartTag is used only in an incremental Receiver where attributes and namespaces are notified separately
83 83
    private enum Transition {
84 84
        OPEN, APPEND, TEXT, COMMENT, PI, START_DOCUMENT,
......
108 108
        edge(State.Content, Transition.END_ELEMENT, State.Content); // or Open if the stack is empty
109 109
        edge(State.Content, Transition.END_DOCUMENT, State.Open);
110 110
        edge(State.Open, Transition.CLOSE, State.Final);
111
        edge(State.Failed, Transition.CLOSE, State.Failed);
111 112
        //edge(State.Final, "close", State.Final);  // This was a concession to poor practice, but apparently no longer needed
112 113
    }
113 114

  
......
149 150
     */
150 151

  
151 152
    public void append(Item item, Location locationId, int copyNamespaces) throws XPathException {
152
        transition(Transition.APPEND);
153
        nextReceiver.append(item, locationId, copyNamespaces);
153
        try {
154
            transition(Transition.APPEND);
155
            nextReceiver.append(item, locationId, copyNamespaces);
156
        } catch (XPathException e) {
157
            state = State.Failed;
158
            throw e;
159
        }
154 160
    }
155 161

  
156 162
    /**
......
164 170
        if (chars.length() == 0 && !stack.isEmpty()) {
165 171
            throw new IllegalStateException("Zero-length text nodes not allowed within document/element content");
166 172
        }
167
        nextReceiver.characters(chars, locationId, properties);
173
        try {
174
            nextReceiver.characters(chars, locationId, properties);
175
        } catch (XPathException e) {
176
            state = State.Failed;
177
            throw e;
178
        }
168 179
    }
169 180

  
170 181
    /**
......
172 183
     */
173 184

  
174 185
    public void close() throws XPathException {
175
        if (state != State.Final) {
186
        if (state != State.Final && state != State.Failed) {
187
            if (!stack.isEmpty()) {
188
                throw new IllegalStateException("Unclosed element or document nodes at end of stream");
189
            }
176 190
            nextReceiver.close();
177 191
            state = State.Final;
178 192
        }
......
184 198

  
185 199
    public void comment(CharSequence chars, Location locationId, int properties) throws XPathException {
186 200
        transition(Transition.COMMENT);
187
        nextReceiver.comment(chars, locationId, properties);
201
        try {
202
            nextReceiver.comment(chars, locationId, properties);
203
        } catch (XPathException e) {
204
            state = State.Failed;
205
            throw e;
206
        }
188 207
    }
189 208

  
190 209
    /**
......
196 215
        if (stack.isEmpty() || stack.pop() != Type.DOCUMENT) {
197 216
            throw new IllegalStateException("Unmatched endDocument() call");
198 217
        }
199
        nextReceiver.endDocument();
218
        try {
219
            nextReceiver.endDocument();
220
        } catch (XPathException e) {
221
            state = State.Failed;
222
            throw e;
223
        }
200 224
    }
201 225

  
202 226
    /**
......
211 235
        if (stack.isEmpty()) {
212 236
            state = State.Open;
213 237
        }
214
        nextReceiver.endElement();
238
        try {
239
            nextReceiver.endElement();
240
        } catch (XPathException e) {
241
            state = State.Failed;
242
            throw e;
243
        }
215 244
    }
216 245

  
217 246
    /**
......
220 249

  
221 250
    public void open() throws XPathException {
222 251
        transition(Transition.OPEN);
223
        nextReceiver.open();
252
        try {
253
            nextReceiver.open();
254
        } catch (XPathException e) {
255
            state = State.Failed;
256
            throw e;
257
        }
224 258
    }
225 259

  
226 260
    /**
......
229 263

  
230 264
    public void processingInstruction(String target, CharSequence data, Location locationId, int properties) throws XPathException {
231 265
        transition(Transition.PI);
232
        nextReceiver.processingInstruction(target, data, locationId, properties);
266
        try {
267
            nextReceiver.processingInstruction(target, data, locationId, properties);
268
        } catch (XPathException e) {
269
            state = State.Failed;
270
            throw e;
271
        }
233 272
    }
234 273

  
235 274
    /**
......
240 279
    public void startDocument(int properties) throws XPathException {
241 280
        transition(Transition.START_DOCUMENT);
242 281
        stack.push(Type.DOCUMENT);
243
        nextReceiver.startDocument(properties);
282
        try {
283
            nextReceiver.startDocument(properties);
284
        } catch (XPathException e) {
285
            state = State.Failed;
286
            throw e;
287
        }
244 288
    }
245 289

  
246 290
    /**
......
316 360
                }
317 361
            }
318 362
        }
319
        nextReceiver.startElement(elemName, type, attributes, namespaces, location, properties);
363
        try {
364
            nextReceiver.startElement(elemName, type, attributes, namespaces, location, properties);
365
        } catch (XPathException e) {
366
            state = State.Failed;
367
            throw e;
368
        }
320 369

  
321 370

  
322 371
    }
latest10/hej/net/sf/saxon/event/WherePopulatedOutputter.java
8 8
package net.sf.saxon.event;
9 9

  
10 10
import net.sf.saxon.expr.instruct.WherePopulated;
11
import net.sf.saxon.expr.parser.Loc;
11 12
import net.sf.saxon.om.*;
12 13
import net.sf.saxon.s9api.Location;
13 14
import net.sf.saxon.trans.XPathException;
......
255 256
        } else if (level == 1 && pendingStartTag) {
256 257
            if (item instanceof NodeInfo) {
257 258
                NodeInfo node = (NodeInfo) item;
258
                // ignore empty text nodes
259
                if (node.getNodeKind() == Type.TEXT && node.getStringValueCS().length() == 0) {
260
                    return;
261
                }
262
                // ignore empty document nodes
263
                if (node.getNodeKind() == Type.DOCUMENT && !node.hasChildNodes()) {
264
                    return;
259
                switch (node.getNodeKind()) {
260
                    case Type.TEXT:
261
                        // ignore empty text nodes
262
                        if (node.getNodeKind() == Type.TEXT && node.getStringValueCS().length() == 0) {
263
                            return;
264
                        }
265
                        break;
266
                    case Type.DOCUMENT:
267
                        // ignore empty document nodes
268
                        if (node.getNodeKind() == Type.DOCUMENT && !node.hasChildNodes()) {
269
                            return;
270
                        }
271
                        break;
272
                    case Type.ATTRIBUTE:
273
                        attribute(NameOfNode.makeName(node), (SimpleType) node.getSchemaType(), node.getStringValue(), Loc.NONE, 0);
274
                        return;
275

  
276
                    case Type.NAMESPACE:
277
                        namespace(node.getLocalPart(), node.getStringValue(), 0);
278
                        return;
279

  
280
                    default:
281
                        break;
265 282
                }
283

  
266 284
            }
267 285
            releaseStartTag();
268 286
            getNextOutputter().append(item);
......
280 298
        } else if (level == 1 && pendingStartTag) {
281 299
            if (item instanceof NodeInfo) {
282 300
                NodeInfo node = (NodeInfo)item;
283
                // ignore empty text nodes
284
                if (node.getNodeKind() == Type.TEXT && node.getStringValueCS().length() == 0) {
285
                    return;
286
                }
287
                // ignore empty document nodes
288
                if (node.getNodeKind() == Type.DOCUMENT && !node.hasChildNodes()) {
289
                    return;
301
                switch (node.getNodeKind()) {
302
                    case Type.TEXT:
303
                        // ignore empty text nodes
304
                        if (node.getNodeKind() == Type.TEXT && node.getStringValueCS().length() == 0) {
305
                            return;
306
                        }
307
                        break;
308
                    case Type.DOCUMENT:
309
                        // ignore empty document nodes
310
                        if (node.getNodeKind() == Type.DOCUMENT && !node.hasChildNodes()) {
311
                            return;
312
                        }
313
                        break;
314
                    case Type.ATTRIBUTE:
315
                        attribute(NameOfNode.makeName(node), (SimpleType)node.getSchemaType(), node.getStringValue(), locationId, 0);
316
                        return;
317

  
318
                    case Type.NAMESPACE:
319
                        namespace(node.getLocalPart(), node.getStringValue(), 0);
320
                        return;
321

  
322
                    default:
323
                        break;
290 324
                }
291 325
            }
292 326
            releaseStartTag();
latest10/hej/net/sf/saxon/expr/AxisExpression.java
203 203
            return Literal.makeEmptySequence();
204 204
        }
205 205

  
206
        if (contextInfo.isParentless() && (axis == AxisInfo.PARENT || axis == AxisInfo.ANCESTOR)) {
207
            if (warnings) {
208
                visitor.issueWarning("The " + AxisInfo.axisName[axis] + " axis will never select anything because the context item is parentless",
209
                                     getLocation());
210
            }
211
            return Literal.makeEmptySequence();
212
        }
213

  
206 214
        // Test whether the axis ever selects a node of the right kind, when starting at this context node
207 215
        if (!targetUType.overlaps(testUType)) {
208 216
            if (warnings) {
latest10/hej/net/sf/saxon/expr/RootExpression.java
33 33

  
34 34

  
35 35
    private boolean contextMaybeUndefined = true;
36
    private boolean doneWarnings = false;
36 37

  
37 38
    public RootExpression() {
38 39
    }
......
43 44

  
44 45
    /*@NotNull*/
45 46
    public Expression typeCheck(ExpressionVisitor visitor, /*@Nullable*/ ContextItemStaticInfo contextInfo) throws XPathException {
47
        TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
46 48
        if (contextInfo == null || contextInfo.getItemType() == null || contextInfo.getItemType().equals(ErrorType.getInstance())) {
47 49
            XPathException err = new XPathException(noContextMessage() + ": the context item is absent");
48 50
            err.setErrorCode("XPDY0002");
49 51
            err.setIsTypeError(true);
50 52
            err.setLocation(getLocation());
51 53
            throw err;
52
        } else {
53
            contextMaybeUndefined = contextInfo.isPossiblyAbsent();
54
        } else if (!doneWarnings && contextInfo.isParentless()
55
                && th.relationship(contextInfo.getItemType(),NodeKindTest.DOCUMENT) == Affinity.DISJOINT) {
56
            visitor.issueWarning(noContextMessage() + ": the context item is parentless and is not a document node", getLocation());
57
            doneWarnings = true;
54 58
        }
55
        TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
59
        contextMaybeUndefined = contextInfo.isPossiblyAbsent();
56 60
        if (th.isSubType(contextInfo.getItemType(), NodeKindTest.DOCUMENT)) {
57 61
            // this rewrite is important for streamability analysis
58 62
            ContextItemExpression cie = new ContextItemExpression();
latest10/hej/net/sf/saxon/expr/StaticContext.java
8 8
package net.sf.saxon.expr;
9 9

  
10 10
import net.sf.saxon.Configuration;
11
import net.sf.saxon.s9api.Location;
12 11
import net.sf.saxon.expr.parser.OptimizerOptions;
13 12
import net.sf.saxon.expr.parser.RetainedStaticContext;
14 13
import net.sf.saxon.functions.FunctionLibrary;
15 14
import net.sf.saxon.lib.NamespaceConstant;
16 15
import net.sf.saxon.om.NamespaceResolver;
17 16
import net.sf.saxon.om.StructuredQName;
17
import net.sf.saxon.s9api.Location;
18 18
import net.sf.saxon.s9api.UnprefixedElementMatchingPolicy;
19 19
import net.sf.saxon.trans.DecimalFormatManager;
20 20
import net.sf.saxon.trans.KeyManager;
latest10/hej/net/sf/saxon/expr/instruct/Message.java
242 242
            rec = new MessageAdapter(new TreeReceiver(emitter), errorCode.getEQName(), getLocation());
243 243
        }
244 244

  
245
        rec.startDocument(abort ? ReceiverOption.TERMINATE : ReceiverOption.NONE);
245
        ComplexContentOutputter cco = new ComplexContentOutputter(rec);
246
        cco.startDocument(abort ? ReceiverOption.TERMINATE : ReceiverOption.NONE);
246 247

  
247 248
        try {
248
            SequenceIterator iter = getSelect().iterate(context);
249
            Item item;
250
            while ((item = iter.next()) != null) {
251
                rec.append(item, getLocation(), ReceiverOption.ALL_NAMESPACES);
252
            }
249
            getSelect().process(cco, context);
250
//            SequenceIterator iter = getSelect().iterate(context);
251
//            Item item;
252
//            while ((item = iter.next()) != null) {
253
//                rec.append(item, getLocation(), ReceiverOption.ALL_NAMESPACES);
254
//            }
253 255
        } catch (XPathException e) {
254
            rec.append(new StringValue("Error " + e.getErrorCodeLocalPart() +
256
            cco.append(new StringValue("Error " + e.getErrorCodeLocalPart() +
255 257
                                               " while evaluating xsl:message at line "
256 258
                                               + getLocation().getLineNumber() + " of " + getLocation().getSystemId() +
257 259
                                               ": " + e.getMessage()));
258 260
        }
259 261

  
260
        rec.endDocument();
261
        rec.close();
262
        cco.endDocument();
263
        cco.close();
262 264
        if (abort) {
263 265
            builder.close();
264 266
            NodeInfo content = builder.getCurrentRoot();
latest10/hej/net/sf/saxon/expr/parser/ContextItemStaticInfo.java
26 26
    private ItemType itemType;
27 27
    private boolean contextMaybeUndefined;
28 28
    private Expression contextSettingExpression;
29
    private boolean parentless;
29 30

  
30 31
    /**
31 32
     * Create a ContextItemStaticInfo
......
93 94
        return false;
94 95
    }
95 96

  
97
    public void setParentless(boolean parentless) {
98
        this.parentless = parentless;
99
    }
100

  
101
    public boolean isParentless() {
102
        return parentless;
103
    }
104

  
96 105
    /**
97 106
     * Default information when nothing else is known
98 107
     */
latest10/hej/net/sf/saxon/expr/parser/Evaluator.java
443 443
                    return new IntegerRange(start, end);
444 444
                }
445 445
            }
446
            if (base instanceof SequenceExtent) {
447
                SequenceExtent baseSeq = (SequenceExtent)base;
448
                if (tail.getStart() > ((SequenceExtent) base).getLength()) {
449
                    return EmptySequence.getInstance();
450
                } else {
451
                    return new SequenceExtent(
452
                            baseSeq,
453
                            tail.getStart() - 1,
454
                            baseSeq.getLength() - tail.getStart() + 1).reduce();
455
                }
446
            if (base instanceof GroundedValue) {
447
                GroundedValue baseSeq = (GroundedValue)base;
448
                return baseSeq.subsequence(tail.getStart() - 1, baseSeq.getLength() - tail.getStart() + 1);
456 449
            }
457 450

  
458 451
            return new MemoClosure(tail, context);
latest10/hej/net/sf/saxon/expr/parser/XPathParser.java
488 488

  
489 489
        if (exp == null) {
490 490

  
491
            qNameParser = new QNameParser(env.getNamespaceResolver());
492
            qNameParser.setAcceptEQName(allowXPath30Syntax);
493
            qNameParser.setErrorOnBadSyntax(language == ParsedLanguage.XSLT_PATTERN ? "XTSE0340" : "XPST0003");
494
            qNameParser.setErrorOnUnresolvedPrefix("XPST0081");
491
            qNameParser = new QNameParser(env.getNamespaceResolver())
492
                .withAcceptEQName(allowXPath30Syntax)
493
                .withErrorOnBadSyntax(language == ParsedLanguage.XSLT_PATTERN ? "XTSE0340" : "XPST0003")
494
                .withErrorOnUnresolvedPrefix("XPST0081");
495 495

  
496 496
            charChecker = env.getConfiguration().getValidCharacterChecker();
497 497
            t = new Tokenizer();
......
557 557
        if (qNameParser == null) {
558 558
            qNameParser = new QNameParser(env.getNamespaceResolver());
559 559
            if (languageVersion >= 30) {
560
                qNameParser.setAcceptEQName(true);
560
                qNameParser = qNameParser.withAcceptEQName(true);
561 561
            }
562 562
        }
563 563
        language = ParsedLanguage.SEQUENCE_TYPE;
latest10/hej/net/sf/saxon/functions/ElementAvailable.java
113 113
                return false;
114 114
        }
115 115
    }
116

  
117
    public static boolean isSaxonJSElement(int fp) {
118
        switch (fp) {
119
            //case StandardNames.XSL_ACCEPT:
120
            case StandardNames.XSL_ACCUMULATOR:
121
            case StandardNames.XSL_ACCUMULATOR_RULE:
122
            case StandardNames.XSL_ANALYZE_STRING:
123
            case StandardNames.XSL_APPLY_IMPORTS:
124
            case StandardNames.XSL_APPLY_TEMPLATES:
125
            case StandardNames.XSL_ASSERT:
126
            case StandardNames.XSL_ATTRIBUTE:
127
            case StandardNames.XSL_ATTRIBUTE_SET:
128
            case StandardNames.XSL_BREAK:
129
            case StandardNames.XSL_CALL_TEMPLATE:
130
            case StandardNames.XSL_CATCH:
131
            case StandardNames.XSL_CHARACTER_MAP:
132
            case StandardNames.XSL_CHOOSE:
133
            case StandardNames.XSL_COMMENT:
134
            case StandardNames.XSL_CONTEXT_ITEM:
135
            case StandardNames.XSL_COPY:
136
            case StandardNames.XSL_COPY_OF:
137
            case StandardNames.XSL_DECIMAL_FORMAT:
138
            case StandardNames.XSL_DOCUMENT:
139
            case StandardNames.XSL_ELEMENT:
140
            case StandardNames.XSL_EVALUATE:
141
            //case StandardNames.XSL_EXPOSE:
142
            case StandardNames.XSL_FALLBACK:
143
            case StandardNames.XSL_FOR_EACH:
144
            case StandardNames.XSL_FOR_EACH_GROUP:
145
            case StandardNames.XSL_FORK:
146
            case StandardNames.XSL_FUNCTION:
147
            case StandardNames.XSL_GLOBAL_CONTEXT_ITEM:
148
            case StandardNames.XSL_IF:
149
            case StandardNames.XSL_IMPORT:
150
            //case StandardNames.XSL_IMPORT_SCHEMA:
151
            case StandardNames.XSL_INCLUDE:
152
            case StandardNames.XSL_ITERATE:
153
            case StandardNames.XSL_KEY:
154
            case StandardNames.XSL_MAP:
155
            case StandardNames.XSL_MAP_ENTRY:
156
            case StandardNames.XSL_MATCHING_SUBSTRING:
157
            case StandardNames.XSL_MERGE:
158
            case StandardNames.XSL_MERGE_ACTION:
159
            case StandardNames.XSL_MERGE_KEY:
160
            case StandardNames.XSL_MERGE_SOURCE:
161
            case StandardNames.XSL_MESSAGE:
162
            case StandardNames.XSL_MODE:
163
            case StandardNames.XSL_NAMESPACE:
164
            case StandardNames.XSL_NAMESPACE_ALIAS:
165
            case StandardNames.XSL_NEXT_ITERATION:
166
            case StandardNames.XSL_NEXT_MATCH:
167
            case StandardNames.XSL_NON_MATCHING_SUBSTRING:
168
            case StandardNames.XSL_NUMBER:
169
            case StandardNames.XSL_ON_COMPLETION:
170
            case StandardNames.XSL_ON_EMPTY:
171
            case StandardNames.XSL_ON_NON_EMPTY:
172
            case StandardNames.XSL_OTHERWISE:
173
            case StandardNames.XSL_OUTPUT:
174
            case StandardNames.XSL_OUTPUT_CHARACTER:
175
            //case StandardNames.XSL_OVERRIDE:
176
            //case StandardNames.XSL_PACKAGE:
177
            case StandardNames.XSL_PARAM:
178
            case StandardNames.XSL_PERFORM_SORT:
179
            case StandardNames.XSL_PRESERVE_SPACE:
180
            case StandardNames.XSL_PROCESSING_INSTRUCTION:
181
            case StandardNames.XSL_RESULT_DOCUMENT:
182
            case StandardNames.XSL_SEQUENCE:
183
            case StandardNames.XSL_SORT:
184
            case StandardNames.XSL_SOURCE_DOCUMENT:
185
            case StandardNames.XSL_STRIP_SPACE:
186
            case StandardNames.XSL_STYLESHEET:
187
            case StandardNames.XSL_TEMPLATE:
188
            case StandardNames.XSL_TEXT:
189
            case StandardNames.XSL_TRANSFORM:
190
            case StandardNames.XSL_TRY:
191
            //case StandardNames.XSL_USE_PACKAGE:
192
            case StandardNames.XSL_VALUE_OF:
193
            case StandardNames.XSL_VARIABLE:
194
            case StandardNames.XSL_WHEN:
195
            case StandardNames.XSL_WHERE_POPULATED:
196
            case StandardNames.XSL_WITH_PARAM:
197
                return true;
198
            default:
199
                return false;
200
        }
201
    }
202

  
116
    
203 117
    /**
204 118
     * Special-case for element-available('xsl:evaluate') which may be dynamically-disabled,
205 119
     * and the spec says that this should be assessed at run-time.  By indicating that the
......
244 158
        if (qName.hasURI(NamespaceConstant.XSLT)) {
245 159
            int fp = context.getConfiguration().getNamePool().getFingerprint(NamespaceConstant.XSLT, qName.getLocalPart());
246 160
            boolean known = isXslt30Element(fp);
247
            if ("JS".equals(edition)) {
248
                known = known && isSaxonJSElement(fp);
249
            }
250 161
            if (fp == StandardNames.XSL_EVALUATE) {
251 162
                known = known && !context.getConfiguration().getBooleanProperty(Feature.DISABLE_XSL_EVALUATE);
252 163
            }
253 164
            return known;
254
        } else {
255
            return context.getConfiguration().isExtensionElementAvailable(qName);
165
        } else if (qName.hasURI(NamespaceConstant.IXSL) && !edition.equals("JS")) {
166
            return false;
256 167
        }
168
        return context.getConfiguration().isExtensionElementAvailable(qName);
257 169
    }
258 170

  
259 171
    private StructuredQName getElementName(String lexicalName) throws XPathException {
latest10/hej/net/sf/saxon/functions/FunctionAvailable.java
58 58
            StaticContext env = visitor.getStaticContext();
59 59
            boolean b = false;
60 60

  
61
            QNameParser qp = new QNameParser(getRetainedStaticContext());
62
            qp.setAcceptEQName(true);
63
            qp.setErrorOnBadSyntax("XTDE1400");
64
            qp.setErrorOnUnresolvedPrefix("XTDE1400");
61
            QNameParser qp = new QNameParser(getRetainedStaticContext())
62
                    .withAcceptEQName(true)
63
                    .withErrorOnBadSyntax("XTDE1400")
64
                    .withErrorOnUnresolvedPrefix("XTDE1400");
65 65

  
66 66
            StructuredQName functionName = qp.parse(lexicalQName, env.getDefaultFunctionNamespace());
67 67

  
latest10/hej/net/sf/saxon/functions/URIQueryParameters.java
40 40
    Integer onError = null;
41 41
    Maker<XMLReader> parserMaker = null;
42 42
    Boolean xinclude = null;
43
    boolean unparsed;
44 43
    Boolean stable = null;
45 44
    Boolean metadata = null;
45
    String contentType = null;
46 46

  
47 47
    public static final int ON_ERROR_FAIL = 1;
48 48
    public static final int ON_ERROR_WARNING = 2;
......
113 113
            } else if (value.equals("no")) {
114 114
                xinclude = Boolean.FALSE;
115 115
            }
116
        } else if (keyword.equals("unparsed")) {
117
            if (value.equals("yes")) {
118
                unparsed = true;
119
            } else if (value.equals("no")) {
120
                unparsed = false;
121
            }
116
        } else if (keyword.equals("content-type")) {
117
            contentType = value;
122 118
        } else if (keyword.equals("on-error")) {
123 119
            switch (value) {
124 120
                case "warning":
......
222 218
    }
223 219

  
224 220
    /**
225
     * Get the value of unparsed=yes|no, or false if unspecified
221
     * Get the value of media-type, or null if absent
226 222
     */
227 223

  
228
    public boolean isUnparsed() {
229
        return unparsed;
224
    public String getContentType() {
225
        return contentType;
230 226
    }
231 227

  
232 228
    /**
latest10/hej/net/sf/saxon/gizmo/JLine2Talker.java
67 67
        }
68 68
    }
69 69

  
70
    private static class XPathCompleter extends StringsCompleter {
70
    public static class XPathCompleter extends StringsCompleter {
71 71

  
72 72
        public XPathCompleter(List<String> candidates) {
73 73
            super(candidates);
......
103 103
                                translated = homeDir.getPath() + translated.substring(1);
104 104
                            } else if (translated.startsWith("~")) {
105 105
                                translated = homeDir.getParentFile().getAbsolutePath();
106
                            } else if (!translated.contains(separator())) {
107
                                String cwd = getUserDir().getAbsolutePath();
108
                                translated = cwd + separator() + translated;
106 109
                            } else if (!(new File(translated).isAbsolute())) {
107 110
                                String cwd = getUserDir().getAbsolutePath();
108 111
                                translated = cwd + separator() + translated;
......
119 122

  
120 123
                            File[] entries = dir == null ? new File[0] : dir.listFiles();
121 124

  
122
                            return matchFiles(buffer, translated, entries, candidates);
125
                            int index = matchFiles(buffer, translated, entries, candidates);
126
                            return index==0 ? space+1 : index;
123 127
                        }
124 128
                    };
125 129
                    return fnc.complete(buffer, cursor, candidates);
latest10/hej/net/sf/saxon/lib/Feature.java
126 126

  
127 127

  
128 128
    /**
129
    *            <p>This flag must be set to enable use of extensions to XPath, XQuery and XSLT
129
    *            <p>This flag must be set to enable use of extensions to XPath (and potentially XQuery and XSLT)
130 130
    *                syntax that go beyond what is allowed by the extensibility mechanisms in the spec.
131 131
    *                In some cases these extensions are experimental and may not be carried forward to future
132 132
    *            Saxon releases.</p>
133
    *            <p>Syntax extensions in Saxon 10 include the use of type aliases (<code>type(...)</code> where
133
    *            <p>Syntax extensions in Saxon 9.8 include the use of type aliases (<code>~aliasName</code> where
134 134
    *                an item type is expected, and <code>declare type NAME = item-type</code> in the XQuery Prolog); 
135
    *                and simple inline functions (for example <code>.{. + 1}</code>).</p>
135
    *                and simple inline functions (for example <code>fn{. + 1}</code>).</p>
136 136
    *        
137 137
    **/
138 138

  
......
1010 1010

  
1011 1011

  
1012 1012
    /**
1013
    *            <p>An integer, one of {@link net.sf.saxon.trans.RecoveryPolicy#RECOVER_SILENTLY},
1014
    *                {@link net.sf.saxon.trans.RecoveryPolicy#RECOVER_WITH_WARNINGS}, or
1015
    *                {@link net.sf.saxon.trans.RecoveryPolicy#DO_NOT_RECOVER}. Indicates the policy for
1013
    *            <p>An integer, one of {@link RecoveryPolicy#RECOVER_SILENTLY},
1014
    *                {@link RecoveryPolicy#RECOVER_WITH_WARNINGS}, or
1015
    *                {@link RecoveryPolicy#DO_NOT_RECOVER}. Indicates the policy for
1016 1016
    *                handling dynamic errors that the XSLT specification defines as recoverable.</p>
1017 1017
    *            <p>0 means recover silently; 1 means recover after signalling a warning to the
1018 1018
    *                    <code>ErrorListener</code>; 2 means treat the error as fatal. An example of a
latest10/hej/net/sf/saxon/lib/FeatureKeys.java
99 99

  
100 100

  
101 101
    /**
102
    *            <p>This flag must be set to enable use of extensions to XPath, XQuery and XSLT
102
    *            <p>This flag must be set to enable use of extensions to XPath (and potentially XQuery and XSLT)
103 103
    *                syntax that go beyond what is allowed by the extensibility mechanisms in the spec.
104 104
    *                In some cases these extensions are experimental and may not be carried forward to future
105 105
    *            Saxon releases.</p>
106
    *            <p>Syntax extensions in Saxon 10 include the use of type aliases (<code>type(...)</code> where
106
    *            <p>Syntax extensions in Saxon 9.8 include the use of type aliases (<code>~aliasName</code> where
107 107
    *                an item type is expected, and <code>declare type NAME = item-type</code> in the XQuery Prolog); 
108
    *                and simple inline functions (for example <code>.{. + 1}</code>).</p>
108
    *                and simple inline functions (for example <code>fn{. + 1}</code>).</p>
109 109
    *        
110 110
    **/
111 111

  
......
983 983

  
984 984

  
985 985
    /**
986
    *            <p>An integer, one of {@link net.sf.saxon.trans.RecoveryPolicy#RECOVER_SILENTLY},
987
    *                {@link net.sf.saxon.trans.RecoveryPolicy#RECOVER_WITH_WARNINGS}, or
988
    *                {@link net.sf.saxon.trans.RecoveryPolicy#DO_NOT_RECOVER}. Indicates the policy for
986
    *            <p>An integer, one of {@link RecoveryPolicy#RECOVER_SILENTLY},
987
    *                {@link RecoveryPolicy#RECOVER_WITH_WARNINGS}, or
988
    *                {@link RecoveryPolicy#DO_NOT_RECOVER}. Indicates the policy for
989 989
    *                handling dynamic errors that the XSLT specification defines as recoverable.</p>
990 990
    *            <p>0 means recover silently; 1 means recover after signalling a warning to the
991 991
    *                    <code>ErrorListener</code>; 2 means treat the error as fatal. An example of a
latest10/hej/net/sf/saxon/ma/parray/ImmList2.java
111 111
        } else if (start >= left.size() && end >= left.size()) {
112 112
            return right.subList(start - left.size(), end - left.size());
113 113
        } else {
114
            return new ImmList2<>(left.subList(start, left.size()), right.subList(0, end - start)).rebalance();
114
            return new ImmList2<>(left.subList(start, left.size()), right.subList(0, end - left.size())).rebalance();
115 115
        }
116 116
    }
117 117

  
latest10/hej/net/sf/saxon/om/EmptyAttributeMap.java
14 14
import java.util.Iterator;
15 15

  
16 16
/**
17
 * An implementation of AttributeMap suitable for small collections of attributes (say, up to four or five).
18
 * Searching for a particular attribute involves a sequential search, and adding a new attribute constructs
19
 * a full copy.
17
 * An implementation of AttributeMap representing an empty AttributeMap
20 18
 */
21 19

  
22 20
public class EmptyAttributeMap implements AttributeMap {
latest10/hej/net/sf/saxon/om/LargeAttributeMap.java
9 9

  
10 10

  
11 11
import net.sf.saxon.ma.trie.ImmutableHashTrieMap;
12
import net.sf.saxon.ma.trie.Tuple2;
12
import net.sf.saxon.tree.util.FastStringBuffer;
13 13

  
14 14
import java.util.ArrayList;
15 15
import java.util.Iterator;
16 16
import java.util.List;
17 17

  
18 18
/**
19
 * An implementation of AttributeMap suitable for small collections of attributes (say, up to four or five).
20
 * Searching for a particular attribute involves a sequential search, and adding a new attribute constructs
21
 * a full copy.
19
 * An implementation of AttributeMap suitable for larger collections of attributes (say, more than five).
20
 * This provides direct access to an attribute by name, avoiding the cost of a sequential search. The
21
 * map preserves the order of insertion of attributes: this is done by maintaining a doubly-linked list
22
 * of attributes in insertion order (when an attribute is replaced by another with the same name, it
23
 * currently occupies the position of the original; but this is not guaranteed).
22 24
 */
23 25

  
24 26
public class LargeAttributeMap implements AttributeMap {
25 27

  
26
    private ImmutableHashTrieMap<NodeName, AttributeInfo> attributes;
28
    private static class AttributeInfoLink {
29
        AttributeInfo payload;
30
        NodeName prior;
31
        NodeName next;
32
    }
33

  
34
    private ImmutableHashTrieMap<NodeName, AttributeInfoLink> attributes;
35
    private NodeName first = null;
36
    private NodeName last = null;
27 37
    private int size;
28
    private List<AttributeInfo> attributeList = null;
29 38

  
30
    public static LargeAttributeMap EMPTY = new LargeAttributeMap(new ArrayList<>(0));
39
    private LargeAttributeMap() {}
31 40

  
32 41
    public LargeAttributeMap(List<AttributeInfo> atts) {
33
        this.attributeList = atts;
42
        assert !atts.isEmpty();
34 43
        this.attributes = ImmutableHashTrieMap.empty();
35 44
        this.size = atts.size();
45
        AttributeInfoLink current = null;
36 46
        for (AttributeInfo att : atts) {
37 47
            if (attributes.get(att.getNodeName()) != null) {
38 48
                throw new IllegalArgumentException("Attribute map contains duplicates");
39 49
            }
40
            attributes = attributes.put(att.getNodeName(), att);
50
            AttributeInfoLink link = new AttributeInfoLink();
51
            link.payload = att;
52
            if (current == null) {
53
                first = att.getNodeName();
54
            } else {
55
                current.next = att.getNodeName();
56
                link.prior = current.payload.getNodeName();
57
            }
58
            current = link;
59
            attributes = attributes.put(att.getNodeName(), link);
41 60
        }
61
        last = current.payload.getNodeName();
42 62
    }
43 63

  
44
    private LargeAttributeMap(ImmutableHashTrieMap<NodeName, AttributeInfo> attributes, int size) {
64
    private LargeAttributeMap(ImmutableHashTrieMap<NodeName, AttributeInfoLink> attributes, int size, NodeName first, NodeName last) {
45 65
        this.attributes = attributes;
46 66
        this.size = size;
67
        this.first = first;
68
        this.last = last;
47 69
    }
48 70

  
49 71
    /**
......
58 80

  
59 81
    @Override
60 82
    public AttributeInfo get(NodeName name) {
61
        return attributes.get(name);
83
        AttributeInfoLink link = attributes.get(name);
84
        return link == null ? null : link.payload;
62 85
    }
63 86

  
64 87
    @Override
65 88
    public AttributeInfo get(String uri, String local) {
66 89
        NodeName name = new FingerprintedQName("", uri, local);
67
        return attributes.get(name);
90
        return get(name);
68 91
    }
69 92

  
70 93
    public AttributeInfo getByFingerprint(int fingerprint, NamePool namePool) {
71 94
        NodeName name = new FingerprintedQName(namePool.getStructuredQName(fingerprint), fingerprint);
72
        return attributes.get(name);
95
        return get(name);
73 96
    }
74 97

  
75 98
    @Override
76 99
    public AttributeMap put(AttributeInfo att) {
77
        ImmutableHashTrieMap<NodeName, AttributeInfo> att2 = attributes.put(att.getNodeName(), att);
78
        int size2 = attributes.get(att.getNodeName()) == null ? size + 1 : size;
79
        return new LargeAttributeMap(att2, size2);
100
        AttributeInfoLink existing = attributes.get(att.getNodeName());
101
        AttributeInfoLink link = new AttributeInfoLink();
102
        NodeName last2 = last;
103
        link.payload = att;
104
        if (existing == null) {
105
            link.prior = last;
106
            last2 = att.getNodeName();
107
            AttributeInfoLink oldLast = attributes.get(last);
108
            AttributeInfoLink penult = new AttributeInfoLink();
109
            penult.payload = oldLast.payload;
110
            penult.next = att.getNodeName();
111
            penult.prior = oldLast.prior;
112
            attributes = attributes.put(last, penult);
113
        } else {
114
            link.prior = existing.prior;
115
            link.next = existing.next;
116
        }
117
        ImmutableHashTrieMap<NodeName, AttributeInfoLink> att2 = attributes.put(att.getNodeName(), link);
118
        int size2 = existing == null ? size + 1 : size;
119
        return new LargeAttributeMap(att2, size2, first, last2);
80 120
    }
81 121

  
82 122
    @Override
83 123
    public AttributeMap remove(NodeName name) {
124
        // Not actually used (or tested)
84 125
        if (attributes.get(name) == null) {
85 126
            return this;
86 127
        } else {
87
            ImmutableHashTrieMap<NodeName, AttributeInfo> att2 = attributes.remove(name);
88
            return new LargeAttributeMap(att2, size - 1);
128
            NodeName first2 = first;
129
            NodeName last2 = last;
130
            ImmutableHashTrieMap<NodeName, AttributeInfoLink> att2 = attributes.remove(name);
131
            AttributeInfoLink existing = attributes.get(name);
132
            if (existing.prior != null) {
133
                AttributeInfoLink priorLink = attributes.get(existing.prior);
134
                AttributeInfoLink priorLink2 = new AttributeInfoLink();
135
                priorLink2.payload = priorLink.payload;
136
                priorLink2.prior = priorLink.prior;
137
                priorLink2.next = existing.next;
138
                att2.put(existing.prior, priorLink2);
139
            } else {
140
                first2 = existing.next;
141
            }
142
            if (existing.next != null) {
143
                AttributeInfoLink nextLink = attributes.get(existing.next);
144
                AttributeInfoLink nextLink2 = new AttributeInfoLink();
145
                nextLink2.payload = nextLink.payload;
146
                nextLink2.next = nextLink.next;
147
                nextLink2.prior = existing.prior;
148
                att2.put(existing.next, nextLink2);
149
            } else {
150
                last2 = existing.prior;
151
            }
152
            return new LargeAttributeMap(att2, size - 1, first2, last2);
89 153
        }
90 154
    }
91 155

  
92 156
    @Override
93 157
    public Iterator<AttributeInfo> iterator() {
94
        if (attributeList != null) {
95
            return attributeList.iterator();
96
        } else {
97
            Iterator<Tuple2<NodeName, AttributeInfo>> tuples = attributes.iterator();
98
            return new Iterator<AttributeInfo>() {
99
                @Override
100
                public boolean hasNext() {
101
                    return tuples.hasNext();
102
                }
103

  
104
                @Override
105
                public AttributeInfo next() {
106
                    return tuples.next()._2;
107
                }
108
            };
109
        }
158
        return new Iterator<AttributeInfo>() {
159

  
160
            NodeName current = first;
161
            @Override
162
            public boolean hasNext() {
163
                return current != null;
164
            }
165

  
166
            @Override
167
            public AttributeInfo next() {
168
                AttributeInfoLink link = attributes.get(current);
169
                current = link.next;
170
                return link.payload;
171
            }
172
        };
173

  
110 174
    }
111 175

  
112 176
    @Override
113 177
    public synchronized List<AttributeInfo> asList() {
114
        // Memo function
115
        if (attributeList == null) {
116
            List<AttributeInfo> list = new ArrayList<>(size);
117
            forEach(list::add);
118
            attributeList = list;
178
        List<AttributeInfo> result = new ArrayList<>(size);
179
        iterator().forEachRemaining(result::add);
180
        return result;
181
    }
182

  
183
    @Override
184
    public String toString() {
185
        FastStringBuffer sb = new FastStringBuffer(256);
186
        for (AttributeInfo att : this) {
187
            sb.cat(att.getNodeName().getDisplayName())
188
                    .cat("=\"")
189
                    .cat(att.getValue())
190
                    .cat("\" ");
119 191
        }
120
        return new ArrayList<>(attributeList);
192
        return sb.toString().trim();
121 193
    }
122 194

  
123 195
}
latest10/hej/net/sf/saxon/om/NamePool.java
62 62

  
63 63
    // A map from QNames to fingerprints
64 64

  
65
    private final ConcurrentHashMap<StructuredQName, Integer> qNameToInteger = new ConcurrentHashMap<StructuredQName, Integer>(1000);
65
    private final ConcurrentHashMap<StructuredQName, Integer> qNameToInteger = new ConcurrentHashMap<>(1000);
66 66

  
67 67
    // A map from fingerprints to QNames
68 68

  
69
    private final ConcurrentHashMap<Integer, StructuredQName> integerToQName = new ConcurrentHashMap<Integer, StructuredQName>(1000);
69
    private final ConcurrentHashMap<Integer, StructuredQName> integerToQName = new ConcurrentHashMap<>(1000);
70 70

  
71 71
    // Next fingerprint available to be allocated. Starts at 1024 as low-end fingerprints are statically allocated to system-defined
72 72
    // names
......
75 75

  
76 76
    // A map containing suggested prefixes for particular URIs
77 77

  
78
    private ConcurrentHashMap<String, String> suggestedPrefixes = new ConcurrentHashMap<String, String>();
78
    private ConcurrentHashMap<String, String> suggestedPrefixes = new ConcurrentHashMap<>();
79 79

  
80 80

  
81 81

  
......
174 174
        if (existing != null) {
175 175
            return existing;
176 176
        }
177
        Integer next = unique.getAndIncrement();
177
        int next = unique.getAndIncrement();
178 178
        if (next > MAX_FINGERPRINT) {
179 179
            throw new NamePoolLimitException("Too many distinct names in NamePool");
180 180
        }
latest10/hej/net/sf/saxon/om/NamespaceMap.java
469 469
    /**
470 470
     * Get the differences between this NamespaceMap and another NamespaceMap, as an array
471 471
     * of namespace declarations and undeclarations
472
     * @param other typically the namespaces on the parent element, in which case the method
473
     *              returns the namespace declarations and undeclarations corresponding to the
474
     *              difference between this child element and its parent.
475
     * @param addUndeclarations if true, then when a namespace is declared in the {@code other}
476
     *                          map but not in {@code this} map, a namespace undeclaration
477
     *                          (binding the prefix to the dummy URI "") will be included
478
     *                          in the result. If false, namespace undeclarations are included
479
     *                          in the result only for the default namespace (prefix = "").
472 480
     */
473 481

  
474
    public NamespaceBinding[] getDifferences(NamespaceMap other) {
482
    public NamespaceBinding[] getDifferences(NamespaceMap other, boolean addUndeclarations) {
475 483
        List<NamespaceBinding> result = new ArrayList<>();
476 484
        int i = 0, j = 0;
477 485
        while (true) {
......
483 491
                    result.add(new NamespaceBinding(prefixes[i], uris[i]));
484 492
                    i++;
485 493
                } else if (c == 0) {
486
                    // prefix present in both maps; use the URI in this one
487
                    result.add(new NamespaceBinding(prefixes[i], uris[i]));
494
                    // prefix present in both maps
495
                    if (uris[i].equals(other.uris[j])) {
496
                        // URI is the same; this declaration is redundant, so omit it from the result
497
                    } else {
498
                        // URI is different; use the URI appearing in this map in preference
499
                        result.add(new NamespaceBinding(prefixes[i], uris[i]));
500
                    }
488 501
                    i++;
489 502
                    j++;
490 503
                } else {
491
                    // prefix present in other map, absent from this: add an undeclaration
492
                    result.add(new NamespaceBinding(other.prefixes[j], ""));
504
                    // prefix present in other map, absent from this: maybe add an undeclaration
505
                    if (addUndeclarations || prefixes[i].isEmpty()) {
506
                        result.add(new NamespaceBinding(other.prefixes[j], ""));
507
                    }
493 508
                    j++;
494 509
                }
495 510
            } else if (i < prefixes.length) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff