1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.utils.lexical;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.Reader;
22 import java.util.Map;
23
24 import javax.xml.parsers.ParserConfigurationException;
25 import javax.xml.parsers.SAXParser;
26 import javax.xml.parsers.SAXParserFactory;
27
28 import org.hipparchus.exception.DummyLocalizable;
29 import org.orekit.data.DataSource;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.files.ccsds.utils.FileFormat;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.InputSource;
35 import org.xml.sax.Locator;
36 import org.xml.sax.SAXException;
37 import org.xml.sax.helpers.DefaultHandler;
38
39
40
41
42
43
44 public class XmlLexicalAnalyzer implements LexicalAnalyzer {
45
46
47 private final DataSource source;
48
49
50
51
52 public XmlLexicalAnalyzer(final DataSource source) {
53 this.source = source;
54 }
55
56
57 @Override
58 public <T> T accept(final MessageParser<T> messageParser) {
59 try {
60
61 final DefaultHandler handler = new XMLHandler(messageParser);
62
63
64 final SAXParserFactory factory = SAXParserFactory.newInstance();
65
66
67 final SAXParser saxParser = factory.newSAXParser();
68
69
70 messageParser.reset(FileFormat.XML);
71 final DataSource.Opener opener = source.getOpener();
72 if (opener.rawDataIsBinary()) {
73 try (InputStream is = opener.openStreamOnce()) {
74 if (is == null) {
75 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, source.getName());
76 }
77 saxParser.parse(new InputSource(is), handler);
78 }
79 } else {
80 try (Reader reader = opener.openReaderOnce()) {
81 if (reader == null) {
82 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, source.getName());
83 }
84 saxParser.parse(new InputSource(reader), handler);
85 }
86 }
87
88
89 return messageParser.build();
90
91 } catch (SAXException | ParserConfigurationException | IOException e) {
92
93 throw new OrekitException(e, new DummyLocalizable(e.getMessage()));
94 }
95 }
96
97
98
99 private class XMLHandler extends DefaultHandler {
100
101
102 private final MessageParser<?> messageParser;
103
104
105 private final XmlTokenBuilder regularBuilder;
106
107
108 private Map<String, XmlTokenBuilder> specialElements;
109
110
111 private Locator locator;
112
113
114 private String currentElementName;
115
116
117 private int currentLineNumber;
118
119
120 private String currentContent;
121
122
123 private Attributes currentAttributes;
124
125
126
127
128 XMLHandler(final MessageParser<?> messageParser) {
129 this.messageParser = messageParser;
130 this.regularBuilder = new RegularXmlTokenBuilder();
131 this.specialElements = messageParser.getSpecialXmlElementsBuilders();
132 }
133
134
135
136
137
138 private XmlTokenBuilder getBuilder(final String qName) {
139 final XmlTokenBuilder specialBuilder = specialElements.get(qName);
140 return (specialBuilder != null) ? specialBuilder : regularBuilder;
141 }
142
143
144 @Override
145 public void setDocumentLocator(final Locator documentLocator) {
146 this.locator = documentLocator;
147 }
148
149
150 @Override
151 public void characters(final char[] ch, final int start, final int length) throws SAXException {
152
153
154
155
156
157
158
159
160
161 if (currentElementName != null) {
162
163
164
165
166 currentLineNumber = locator.getLineNumber();
167 currentContent = new String(ch, start, length);
168 }
169 }
170
171
172 @Override
173 public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
174
175 currentElementName = qName;
176 currentAttributes = attributes;
177 currentLineNumber = locator.getLineNumber();
178 currentContent = null;
179
180 for (final ParseToken token : getBuilder(qName).
181 buildTokens(true, qName, currentContent, currentAttributes,
182 currentLineNumber, source.getName())) {
183 messageParser.process(token);
184 }
185
186 }
187
188
189 @Override
190 public void endElement(final String uri, final String localName, final String qName) {
191
192 if (currentContent == null) {
193
194 currentLineNumber = locator.getLineNumber();
195 }
196
197 for (final ParseToken token : getBuilder(qName).
198 buildTokens(false, qName, currentContent, currentAttributes,
199 currentLineNumber, source.getName())) {
200 messageParser.process(token);
201 }
202
203 currentElementName = null;
204 currentLineNumber = -1;
205 currentContent = null;
206
207 }
208
209
210 @Override
211 public InputSource resolveEntity(final String publicId, final String systemId) {
212
213 return new InputSource();
214 }
215
216 }
217
218 }