1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.dom;
23
24import java.util.StringTokenizer;
25import java.util.Vector;
26import org.w3c.dom.DOMImplementationList;
27import org.w3c.dom.DOMImplementationSource;
28import org.w3c.dom.DOMImplementation;
29import com.sun.org.apache.xerces.internal.dom.DOMImplementationListImpl;
30
31/**
32 * Supply one the right implementation, based upon requested features. Each
33 * implemented <code>DOMImplementationSource</code> object is listed in the
34 * binding-specific list of available sources so that its
35 * <code>DOMImplementation</code> objects are made available.
36 *
37 * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#DOMImplementationSource'>Document Object Model (DOM) Level 3 Core Specification</a>.
38 *
39 * @xerces.internal
40 *
41 */
42public class DOMImplementationSourceImpl
43    implements DOMImplementationSource {
44
45    /**
46     * A method to request a DOM implementation.
47     * @param features A string that specifies which features are required.
48     *   This is a space separated list in which each feature is specified
49     *   by its name optionally followed by a space and a version number.
50     *   This is something like: "XML 1.0 Traversal Events 2.0"
51     * @return An implementation that has the desired features, or
52     *   <code>null</code> if this source has none.
53     */
54    public DOMImplementation getDOMImplementation(String features) {
55        // first check whether the CoreDOMImplementation would do
56        DOMImplementation impl =
57            CoreDOMImplementationImpl.getDOMImplementation();
58        if (testImpl(impl, features)) {
59            return impl;
60        }
61        // if not try the DOMImplementation
62        impl = DOMImplementationImpl.getDOMImplementation();
63        if (testImpl(impl, features)) {
64            return impl;
65        }
66
67        return null;
68    }
69
70    /**
71     * A method to request a list of DOM implementations that support the
72     * specified features and versions, as specified in .
73     * @param features A string that specifies which features and versions
74     *   are required. This is a space separated list in which each feature
75     *   is specified by its name optionally followed by a space and a
76     *   version number. This is something like: "XML 3.0 Traversal +Events
77     *   2.0"
78     * @return A list of DOM implementations that support the desired
79     *   features.
80     */
81    public DOMImplementationList getDOMImplementationList(String features) {
82        // first check whether the CoreDOMImplementation would do
83        DOMImplementation impl = CoreDOMImplementationImpl.getDOMImplementation();
84                final Vector implementations = new Vector();
85        if (testImpl(impl, features)) {
86                        implementations.addElement(impl);
87        }
88        impl = DOMImplementationImpl.getDOMImplementation();
89        if (testImpl(impl, features)) {
90                        implementations.addElement(impl);
91        }
92
93        return new DOMImplementationListImpl(implementations);
94    }
95
96    boolean testImpl(DOMImplementation impl, String features) {
97
98        StringTokenizer st = new StringTokenizer(features);
99        String feature = null;
100        String version = null;
101
102        if (st.hasMoreTokens()) {
103           feature = st.nextToken();
104        }
105        while (feature != null) {
106           boolean isVersion = false;
107           if (st.hasMoreTokens()) {
108               char c;
109               version = st.nextToken();
110               c = version.charAt(0);
111               switch (c) {
112               case '0': case '1': case '2': case '3': case '4':
113               case '5': case '6': case '7': case '8': case '9':
114                   isVersion = true;
115               }
116           } else {
117               version = null;
118           }
119           if (isVersion) {
120               if (!impl.hasFeature(feature, version)) {
121                   return false;
122               }
123               if (st.hasMoreTokens()) {
124                   feature = st.nextToken();
125               } else {
126                   feature = null;
127               }
128           } else {
129               if (!impl.hasFeature(feature, null)) {
130                   return false;
131               }
132               feature = version;
133           }
134        }
135        return true;
136    }
137}
138