1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ch.elca.el4j.services.xmlmerge.action;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.Reader;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Hashtable;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.jdom.Element;
34 import org.xml.sax.EntityResolver;
35 import org.xml.sax.InputSource;
36 import org.xml.sax.SAXException;
37
38 import com.wutka.dtd.DTD;
39 import com.wutka.dtd.DTDAny;
40 import com.wutka.dtd.DTDContainer;
41 import com.wutka.dtd.DTDElement;
42 import com.wutka.dtd.DTDItem;
43 import com.wutka.dtd.DTDName;
44 import com.wutka.dtd.DTDParser;
45
46 import ch.elca.el4j.services.xmlmerge.AbstractXmlMergeException;
47 import ch.elca.el4j.services.xmlmerge.Action;
48 import ch.elca.el4j.services.xmlmerge.DocumentException;
49 import ch.elca.el4j.services.xmlmerge.ElementException;
50 import ch.elca.el4j.services.xmlmerge.XmlMergeContext;
51
52
53
54
55
56
57
58
59
60
61 public class DtdInsertAction implements Action {
62
63
64
65
66
67 static Map s_dtdMap = new Hashtable();
68
69
70
71
72 private static Logger s_logger
73 = LoggerFactory.getLogger(DtdInsertAction.class);
74
75
76
77
78 public void perform(Element originalElement, Element patchElement,
79 Element outputParentElement) throws AbstractXmlMergeException {
80
81 Element element;
82
83 if (originalElement != null) {
84 element = (Element) originalElement.clone();
85 } else {
86 element = (Element) patchElement.clone();
87 }
88
89 DTD dtd = getDTD(outputParentElement);
90
91 List dtdElements = dtd.getItemsByType(DTDElement.class);
92
93
94 DTDElement parentDtdElement = null;
95 for (Iterator it = dtdElements.iterator(); it.hasNext();) {
96 DTDElement dtdElement = (DTDElement) it.next();
97
98 if (dtdElement.getName().equals(outputParentElement.getName())) {
99 parentDtdElement = dtdElement;
100 }
101 }
102
103 if (parentDtdElement == null) {
104 throw new ElementException(element, "Element "
105 + outputParentElement.getName() + " not defined in DTD");
106 } else {
107
108 DTDItem item = parentDtdElement.getContent();
109
110 if (item instanceof DTDAny) {
111
112 outputParentElement.addContent(element);
113 } else if (item instanceof DTDContainer) {
114
115
116 List existingChildren = outputParentElement.getChildren();
117
118 if (existingChildren.size() == 0) {
119
120 outputParentElement.addContent(element);
121 } else {
122
123 List orderedDtdElements = getOrderedDtdElements(
124 (DTDContainer) item);
125
126 int indexOfNewElementInDtd = orderedDtdElements
127 .indexOf(element.getName());
128 s_logger.debug("index of element " + element.getName()
129 + ": " + indexOfNewElementInDtd);
130
131 int pos = existingChildren.size();
132
133
134
135 for (int i = 0; i < existingChildren.size(); i++) {
136 String elementName = ((Element) existingChildren.get(i))
137 .getName();
138 s_logger.debug("index of child " + elementName + ": "
139 + orderedDtdElements.indexOf(elementName));
140 if (orderedDtdElements.indexOf(elementName)
141 > indexOfNewElementInDtd) {
142 pos = i;
143 break;
144 }
145 }
146
147 s_logger.debug("adding element " + element.getName()
148 + " add in pos " + pos);
149 outputParentElement.addContent(pos, element);
150
151 }
152
153 }
154
155 }
156
157 }
158
159
160
161
162
163
164
165
166
167
168 public DTD getDTD(Element element) throws DocumentException {
169
170 if (element.getDocument().getDocType() != null) {
171
172 String systemId = element.getDocument().getDocType().getSystemID();
173
174 DTD dtd = (DTD) s_dtdMap.get(systemId);
175
176
177 if (dtd == null) {
178 Reader reader =null;
179
180
181 EntityResolver er= XmlMergeContext.getEntityResolver();
182 if (er != null) {
183 InputSource is = null;
184 try {
185 is = er.resolveEntity("", systemId);
186 } catch (SAXException e) {
187
188 } catch (IOException e) {
189
190 }
191 if (is != null) {
192
193
194 reader = is.getCharacterStream();
195 if (reader == null) {
196 InputStream inputstream = is.getByteStream();
197 if (inputstream != null) {
198 reader = new InputStreamReader(inputstream);
199 }
200 }
201 }
202 }
203
204 if (reader == null) {
205
206 URL url;
207 try {
208 url = new URL(systemId);
209 reader = new InputStreamReader(url.openStream());
210 } catch (MalformedURLException e) {
211 throw new DocumentException(element.getDocument(), e);
212 } catch (IOException ioe) {
213 throw new DocumentException(element.getDocument(), ioe);
214 }
215 }
216
217 try {
218 dtd = new DTDParser(reader).parse();
219 } catch (IOException ioe) {
220 throw new DocumentException(element.getDocument(), ioe);
221 }
222
223 s_dtdMap.put(systemId, dtd);
224 }
225
226 return dtd;
227
228 } else {
229 throw new DocumentException(element.getDocument(),
230 "No DTD specified in document " + element.getDocument());
231 }
232 }
233
234
235
236
237
238
239 public List getOrderedDtdElements(DTDContainer container) {
240 List result = new ArrayList();
241
242 DTDItem[] items = container.getItems();
243
244 for (int i = 0; i < items.length; i++) {
245 if (items[i] instanceof DTDContainer) {
246
247 result.addAll(getOrderedDtdElements((DTDContainer) items[i]));
248 } else if (items[i] instanceof DTDName) {
249 result.add(((DTDName) items[i]).getValue());
250 }
251 }
252
253 return result;
254
255 }
256
257 }