source: josm/trunk/src/org/openstreetmap/josm/data/imagery/GetCapabilitiesParseHelper.java@ 12128

Last change on this file since 12128 was 11921, checked in by Don-vip, 7 years ago

improve unit test coverage of utilities classes thanks to https://trajano.github.io/commons-testing

File size: 8.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import java.io.InputStream;
5import java.net.MalformedURLException;
6import java.net.URL;
7
8import javax.xml.namespace.QName;
9import javax.xml.stream.XMLInputFactory;
10import javax.xml.stream.XMLStreamException;
11import javax.xml.stream.XMLStreamReader;
12
13import org.openstreetmap.josm.tools.Utils;
14
15/**
16 * Helper class for handling OGC GetCapabilities documents
17 * @since 10993
18 */
19public final class GetCapabilitiesParseHelper {
20 enum TransferMode {
21 KVP("KVP"),
22 REST("RESTful");
23
24 private final String typeString;
25
26 TransferMode(String urlString) {
27 this.typeString = urlString;
28 }
29
30 private String getTypeString() {
31 return typeString;
32 }
33
34 static TransferMode fromString(String s) {
35 for (TransferMode type : TransferMode.values()) {
36 if (type.getTypeString().equals(s)) {
37 return type;
38 }
39 }
40 return null;
41 }
42 }
43
44 /**
45 * OWS namespace address
46 */
47 public static final String OWS_NS_URL = "http://www.opengis.net/ows/1.1";
48 /**
49 * XML xlink namespace address
50 */
51 public static final String XLINK_NS_URL = "http://www.w3.org/1999/xlink";
52
53 /**
54 * QNames in OWS namespace
55 */
56 // CHECKSTYLE.OFF: SingleSpaceSeparator
57 static final QName QN_OWS_ALLOWED_VALUES = new QName(OWS_NS_URL, "AllowedValues");
58 static final QName QN_OWS_CONSTRAINT = new QName(OWS_NS_URL, "Constraint");
59 static final QName QN_OWS_DCP = new QName(OWS_NS_URL, "DCP");
60 static final QName QN_OWS_GET = new QName(OWS_NS_URL, "Get");
61 static final QName QN_OWS_HTTP = new QName(OWS_NS_URL, "HTTP");
62 static final QName QN_OWS_IDENTIFIER = new QName(OWS_NS_URL, "Identifier");
63 static final QName QN_OWS_OPERATION = new QName(OWS_NS_URL, "Operation");
64 static final QName QN_OWS_OPERATIONS_METADATA = new QName(OWS_NS_URL, "OperationsMetadata");
65 static final QName QN_OWS_SUPPORTED_CRS = new QName(OWS_NS_URL, "SupportedCRS");
66 static final QName QN_OWS_TITLE = new QName(OWS_NS_URL, "Title");
67 static final QName QN_OWS_VALUE = new QName(OWS_NS_URL, "Value");
68 // CHECKSTYLE.ON: SingleSpaceSeparator
69
70 private GetCapabilitiesParseHelper() {
71 // Hide default constructor for utilities classes
72 }
73
74 /**
75 * @param in InputStream with pointing to GetCapabilities XML stream
76 * @return safe XMLStreamReader, that is not validating external entities, nor loads DTD's
77 * @throws XMLStreamException if any XML stream error occurs
78 */
79 public static XMLStreamReader getReader(InputStream in) throws XMLStreamException {
80 XMLInputFactory factory = XMLInputFactory.newFactory();
81 // do not try to load external entities, nor validate the XML
82 factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
83 factory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
84 factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
85 return factory.createXMLStreamReader(in);
86 }
87
88 /**
89 * Moves the reader to the closing tag of current tag.
90 * @param reader XMLStreamReader which should be moved
91 * @throws XMLStreamException when parse exception occurs
92 */
93 public static void moveReaderToEndCurrentTag(XMLStreamReader reader) throws XMLStreamException {
94 int level = 0;
95 QName tag = reader.getName();
96 for (int event = reader.getEventType(); reader.hasNext(); event = reader.next()) {
97 if (XMLStreamReader.START_ELEMENT == event) {
98 level += 1;
99 } else if (XMLStreamReader.END_ELEMENT == event) {
100 level -= 1;
101 if (level == 0 && tag.equals(reader.getName())) {
102 return;
103 }
104 }
105 if (level < 0) {
106 throw new IllegalStateException("WMTS Parser error - moveReaderToEndCurrentTag failed to find closing tag");
107 }
108 }
109 throw new IllegalStateException("WMTS Parser error - moveReaderToEndCurrentTag failed to find closing tag");
110 }
111
112 /**
113 * Moves reader to first occurrence of the structure equivalent of Xpath tags[0]/tags[1]../tags[n]. If fails to find
114 * moves the reader to the closing tag of current tag
115 *
116 * @param tags array of tags
117 * @param reader XMLStreamReader which should be moved
118 * @return true if tag was found, false otherwise
119 * @throws XMLStreamException See {@link XMLStreamReader}
120 */
121 public static boolean moveReaderToTag(XMLStreamReader reader, QName... tags) throws XMLStreamException {
122 QName stopTag = reader.getName();
123 int currentLevel = 0;
124 QName searchTag = tags[currentLevel];
125 QName parentTag = null;
126 QName skipTag = null;
127
128 for (int event = 0; //skip current element, so we will not skip it as a whole
129 reader.hasNext() && !(event == XMLStreamReader.END_ELEMENT && stopTag.equals(reader.getName()));
130 event = reader.next()) {
131 if (event == XMLStreamReader.END_ELEMENT && skipTag != null && skipTag.equals(reader.getName())) {
132 skipTag = null;
133 }
134 if (skipTag == null) {
135 if (event == XMLStreamReader.START_ELEMENT) {
136 if (searchTag.equals(reader.getName())) {
137 currentLevel += 1;
138 if (currentLevel >= tags.length) {
139 return true; // found!
140 }
141 parentTag = searchTag;
142 searchTag = tags[currentLevel];
143 } else {
144 skipTag = reader.getName();
145 }
146 }
147
148 if (event == XMLStreamReader.END_ELEMENT && parentTag != null && parentTag.equals(reader.getName())) {
149 currentLevel -= 1;
150 searchTag = parentTag;
151 if (currentLevel >= 0) {
152 parentTag = tags[currentLevel];
153 } else {
154 parentTag = null;
155 }
156 }
157 }
158 }
159 return false;
160 }
161
162 /**
163 * Parses Operation[@name='GetTile']/DCP/HTTP/Get section. Returns when reader is on Get closing tag.
164 * @param reader StAX reader instance
165 * @return TransferMode coded in this section
166 * @throws XMLStreamException See {@link XMLStreamReader}
167 */
168 public static TransferMode getTransferMode(XMLStreamReader reader) throws XMLStreamException {
169 QName getQname = QN_OWS_GET;
170
171 Utils.ensure(getQname.equals(reader.getName()), "WMTS Parser state invalid. Expected element %s, got %s",
172 getQname, reader.getName());
173 for (int event = reader.getEventType();
174 reader.hasNext() && !(event == XMLStreamReader.END_ELEMENT && getQname.equals(reader.getName()));
175 event = reader.next()) {
176 if (event == XMLStreamReader.START_ELEMENT && QN_OWS_CONSTRAINT.equals(reader.getName())
177 && "GetEncoding".equals(reader.getAttributeValue("", "name"))) {
178 moveReaderToTag(reader, new QName[]{
179 QN_OWS_ALLOWED_VALUES,
180 QN_OWS_VALUE
181 });
182 return TransferMode.fromString(reader.getElementText());
183 }
184 }
185 return null;
186 }
187
188 /**
189 * @param url URL
190 * @return normalized URL
191 * @throws MalformedURLException in case of malformed URL
192 * @since 10993
193 */
194 public static String normalizeCapabilitiesUrl(String url) throws MalformedURLException {
195 URL inUrl = new URL(url);
196 URL ret = new URL(inUrl.getProtocol(), inUrl.getHost(), inUrl.getPort(), inUrl.getFile());
197 return ret.toExternalForm();
198 }
199
200 /**
201 * Convert CRS identifier to plain code
202 * @param crsIdentifier CRS identifier
203 * @return CRS Identifier as it is used within JOSM (without prefix)
204 */
205 public static String crsToCode(String crsIdentifier) {
206 if (crsIdentifier.startsWith("urn:ogc:def:crs:")) {
207 return crsIdentifier.replaceFirst("urn:ogc:def:crs:([^:]*):.*:(.*)$", "$1:$2");
208 }
209 return crsIdentifier;
210 }
211
212}
Note: See TracBrowser for help on using the repository browser.