source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXSLT.java@ 33630

Last change on this file since 33630 was 33630, checked in by kjdon, 4 years ago

minor comment changes

  • Property svn:keywords set to Author Date Id Revision
File size: 28.4 KB
Line 
1/*
2 * GSXSLT.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.HashMap;
24import java.util.HashSet;
25import java.util.Vector;
26
27import org.apache.log4j.Logger;
28import org.greenstone.util.GlobalProperties;
29import org.w3c.dom.Document;
30import org.w3c.dom.Element;
31import org.w3c.dom.NamedNodeMap;
32import org.w3c.dom.Node;
33import org.w3c.dom.NodeList;
34import org.w3c.dom.UserDataHandler;
35
36/** various functions for manipulating Greenstone xslt */
37public class GSXSLT
38{
39
40 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXSLT.class.getName());
41
42 public static void mergeStylesheets(Document main_xsl, Element extra_xsl, boolean overwrite)
43 {
44 mergeStylesheetsDebug(main_xsl, extra_xsl, overwrite, false, null, null);
45 }
46
47 /**
48 * takes a stylesheet Document, and adds in any child nodes from extra_xsl
49 * named templates overwrite any existing one, while match templates are
50 * just added to the end of the stylesheet
51 *
52 * elements are added in following order, and added to preserve original
53 * order with imported ones coming after existing ones:
54 * import, include, output, variable, template
55 */
56 public static void mergeStylesheetsDebug(Document main_xsl, Element extra_xsl, boolean overwrite, boolean debug, String firstDocFileName, String secondDocFileName)
57 {
58 if (debug)
59 {
60 insertDebugElements(main_xsl, firstDocFileName);
61 }
62
63 Element main = main_xsl.getDocumentElement();
64 Node insertion_point = null;
65 Element last_import = GSXML.getLastElementByTagNameNS(main, GSXML.XSL_NAMESPACE, "import");
66 if (last_import != null)
67 {
68 insertion_point = last_import.getNextSibling();
69 }
70 else
71 {
72 insertion_point = main.getFirstChild();
73 }
74
75 // imports
76 NodeList children = extra_xsl.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "import");
77 for (int i = 0; i < children.getLength(); i++)
78 {
79 Element node = (Element) children.item(i);
80 // If the new xsl:import element is identical (in terms of href attr value)
81 // to any in the merged document, don't copy it over
82 if (GSXML.getNamedElementNS(main, GSXML.XSL_NAMESPACE, "import", "href", node.getAttribute("href")) == null)
83 {
84 // Import statements should be the first children of an xsl:stylesheet element
85 // If firstchild is null, then this xsl:import element will be inserted at the "end"
86 // Although Node.insertBefore() will first remove identical nodes before inserting, we check
87 // only the href attribute to see if they're "identical" to any pre-existing <xsl:import>
88 //main.insertBefore(main_xsl.importNode(node, true), main.getFirstChild());
89 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
90 }
91 }
92
93 // do we have a new insertion point??
94 Element last_include = GSXML.getLastElementByTagNameNS(main, GSXML.XSL_NAMESPACE, "include");
95 if (last_include != null)
96 {
97 insertion_point = last_include.getNextSibling();
98 }
99
100 // includes
101 children = extra_xsl.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "include");
102 for (int i = 0; i < children.getLength(); i++)
103 {
104 Element node = (Element) children.item(i);
105 // If the new xsl:include element is identical (in terms of href attr value)
106 // to any in the merged document, don't copy it over
107 // Although Node.appendChild() will first remove identical nodes before appending, we check
108 // only the href attribute to see if they're "identical" to any pre-existing <xsl:include>
109 if (GSXML.getNamedElementNS(main, GSXML.XSL_NAMESPACE, "include", "href", node.getAttribute("href")) == null)
110 {
111 //main.appendChild(main_xsl.importNode(node, true));
112 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
113 }
114 } // for each include
115
116 if (main.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "output").getLength() == 0)
117 {
118 // outputs
119 children = extra_xsl.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "output");
120 for (int i = 0; i < children.getLength(); i++)
121 {
122 Element node = (Element) children.item(i);
123 // If the new xsl:output element is identical (in terms of the value for the method attr)
124 // to any in the merged document, don't copy it over
125
126 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
127 }
128 }
129
130 // variables - only top level ones!!
131 // append to end of document
132 children = GSXML.getChildrenByTagNameNS(extra_xsl, GSXML.XSL_NAMESPACE, "variable");
133 for (int i = 0; i < children.getLength(); i++)
134 {
135 Element node = (Element) children.item(i);
136 // If the new xsl:import element is identical (in terms of href attr value)
137 // to any in the merged document, don't copy it over
138 if (GSXML.getNamedElementNS(main, GSXML.XSL_NAMESPACE, "variable", "name", node.getAttribute("name")) == null)
139 {
140 main.appendChild(main_xsl.importNode(node, true));
141 }
142 }
143
144 // params - only top level ones!!
145 // append to end of document
146 children = GSXML.getChildrenByTagNameNS(extra_xsl, GSXML.XSL_NAMESPACE, "param");
147 for (int i = 0; i < children.getLength(); i++)
148 {
149 Element node = (Element) children.item(i);
150 // If the new xsl:import element is identical (in terms of href attr value)
151 // to any in the merged document, don't copy it over
152 if (GSXML.getNamedElementNS(main, GSXML.XSL_NAMESPACE, "param", "name", node.getAttribute("name")) == null)
153 {
154 main.appendChild(main_xsl.importNode(node, true));
155 }
156 }
157
158 // key -- xsl:key elements need to be defined at the top level
159 children = GSXML.getChildrenByTagNameNS(extra_xsl, GSXML.XSL_NAMESPACE, "key");
160 for (int i = 0; i < children.getLength(); i++)
161 {
162 Element node = (Element) children.item(i);
163 // If the new xsl:key element is identical (in terms of name attr value)
164 // to any in the merged document, don't copy it over
165 if (GSXML.getNamedElementNS(main, GSXML.XSL_NAMESPACE, "key", "name", node.getAttribute("name")) == null)
166 {
167 main.appendChild(main_xsl.importNode(node, true));
168 }
169 }
170
171 // templates
172 // append to end of document
173 children = extra_xsl.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "template");
174 for (int i = 0; i < children.getLength(); i++)
175 {
176 Element node = (Element) children.item(i);
177 // remove any previous occurrences of xsl:template with the same value for name or match
178 String template_match = node.getAttribute("match");
179 String template_name = node.getAttribute("name");
180 String template_mode = node.getAttribute("mode");
181
182 if (overwrite)
183 {
184 // if we have a name attribute, remove any other similarly named template
185 GSXML.removeElementsWithAttributesNS(main, GSXML.XSL_NAMESPACE, "template", new String[] { "name", "match", "mode" }, new String[] { template_name, template_match, template_mode });
186
187 // now add our good template in
188 main.appendChild(main_xsl.importNode(node, true));
189 }
190 else
191 {
192 // if overwrite is false, then we only add in templates if they don't match something else.
193 // In this case (eg from expanding imported stylesheets)
194 // there can't be any duplicate named templates, so just look for matches
195 // we already have the one with highest import precedence (from the top most level) so don't add any more in
196 if (GSXML.getElementsWithAttributesNS(main, GSXML.XSL_NAMESPACE, "template", new String[] { "name", "match", "mode" }, new String[] { template_name, template_match, template_mode }).getLength() == 0) {
197 main.appendChild(main_xsl.importNode(node, true));
198 }
199 }
200
201 }
202
203 if (debug)
204 {
205 insertDebugElements(main_xsl, secondDocFileName);
206 }
207 }
208
209 public static void insertDebugElements(Document doc, String filename)
210 {
211 NodeList xslTemplates = doc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "template");
212 NodeList gsfTemplates = doc.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "template");
213
214 for (int i = 0; i < xslTemplates.getLength() + gsfTemplates.getLength(); i++)
215 {
216 boolean gsf = (i >= xslTemplates.getLength());
217 Element currentTemplate = (Element) (!gsf ? xslTemplates.item(i) : gsfTemplates.item(i - xslTemplates.getLength()));
218
219 NodeList childNodes = currentTemplate.getChildNodes();
220 boolean debugInformationAlreadyExists = false;
221 for (int j = 0; j < childNodes.getLength(); j++)
222 {
223 Node current = childNodes.item(j);
224 if (current instanceof Element && ((Element) current).getNodeName().equals("debug") && (!((Element) current).getAttribute("nodename").startsWith("gsf:") || ((Element) current).getAttribute("nodename").equals("gsf:template")))
225 {
226 debugInformationAlreadyExists = true;
227 break;
228 }
229 }
230
231 if (debugInformationAlreadyExists)
232 {
233 continue;
234 }
235
236 Element debugElement = doc.createElement("debug");
237 debugElement.setAttribute("filename", filename);
238 debugElement.setAttribute("nodename", gsf ? "gsf:template" : "xsl:template");
239
240 if (currentTemplate.getAttribute("match").length() > 0)
241 {
242 debugElement.setAttribute("match", currentTemplate.getAttribute("match"));
243 }
244 if (currentTemplate.getAttribute("name").length() > 0)
245 {
246 debugElement.setAttribute("name", currentTemplate.getAttribute("name"));
247 }
248
249 if (currentTemplate.getUserData("xpath") != null)
250 {
251 debugElement.setAttribute("xpath", (String) currentTemplate.getUserData("xpath"));
252 }
253
254 if (childNodes.getLength() > 0)
255 {
256 int paramCount = 0;
257 while (childNodes.getLength() > paramCount)
258 {
259 Node currentNode = childNodes.item(paramCount);
260 if (currentNode instanceof Element)
261 {
262 if (((Element) currentNode).getNodeName().equals("xsl:param") || ((Element) currentNode).getNodeName().equals("xslt:param") || (((Element) currentNode).getNodeName().equals("param") && ((Element) currentNode).getNamespaceURI().equals(GSXML.XSL_NAMESPACE)))
263 {
264 paramCount++;
265 }
266 else
267 {
268 debugElement.appendChild(currentNode);
269 }
270 }
271 else
272 {
273 debugElement.appendChild(currentNode);
274 }
275 }
276 currentTemplate.appendChild(debugElement);
277 }
278 else
279 {
280 currentTemplate.appendChild(debugElement);
281 }
282
283 Element textElement = doc.createElementNS(GSXML.XSL_NAMESPACE, "text");
284 textElement.appendChild(doc.createTextNode(" "));
285 debugElement.appendChild(textElement);
286 }
287 }
288
289 public static void inlineImportAndIncludeFiles(Document doc, String pathExtra, String site, String collection, String interface_name, ArrayList<String> base_interfaces)
290 {
291 inlineImportAndIncludeFilesDebug(doc, pathExtra, false, null, site, collection, interface_name, base_interfaces);
292 }
293
294 public static void inlineImportAndIncludeFilesDebug(Document doc, String pathExtra, boolean debug, String docFileName, String site, String collection, String interface_name, ArrayList<String> base_interfaces)
295 {
296 String path = (pathExtra == null) ? "" : pathExtra;
297
298 NodeList importList = doc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "import");
299 NodeList includeList = doc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "include");
300
301 for (int i = 0; i < importList.getLength() + includeList.getLength(); i++)
302 {
303 Element current = (Element) ((i < importList.getLength()) ? importList.item(i) : includeList.item(i - importList.getLength()));
304 String href = current.getAttribute("href");
305
306 try
307 {
308 //Document inlineDoc = converter.getDOM(new File(filePath), "UTF-8");
309 Document inlineDoc = mergedXSLTDocumentCascade(path + href, site, collection, interface_name, base_interfaces, debug);
310 String newPath = path;
311 int lastSepIndex = href.lastIndexOf("/");
312 if (lastSepIndex != -1)
313 {
314 newPath += href.substring(0, lastSepIndex + 1);
315 }
316
317 //Do this recursively
318 inlineImportAndIncludeFilesDebug(inlineDoc, newPath, debug, "merged " + href/* filePath */, site, collection, interface_name, base_interfaces);
319 GSXSLT.mergeStylesheetsDebug(doc, inlineDoc.getDocumentElement(), false, debug, docFileName, /* filePath */"merged " + href);
320 }
321 catch (Exception ex)
322 {
323 ex.printStackTrace();
324 return;
325 }
326 }
327
328 while (importList.getLength() > 0)
329 {
330 Element importElem = (Element) importList.item(0);
331 importElem.getParentNode().removeChild(importElem);
332 }
333 while (includeList.getLength() > 0)
334 {
335 Element includeElem = (Element) includeList.item(0);
336 includeElem.getParentNode().removeChild(includeElem);
337 }
338 }
339
340 public static Document mergedXSLTDocumentCascade(String xslt_filename, String site, String collection, String this_interface, ArrayList<String> base_interfaces, boolean debug)
341 {
342 XMLConverter converter = new XMLConverter();
343 // find the list of stylesheets with this name
344 ArrayList<File> stylesheets = GSFile.getStylesheetFiles(GlobalProperties.getGSDL3Home(), site, collection, this_interface, base_interfaces, xslt_filename);
345 if (stylesheets.size() == 0)
346 {
347 logger.error(" Can't find stylesheet " + xslt_filename);
348 return null;
349 }
350 logger.debug("Stylesheet: " + xslt_filename);
351
352 Document finalDoc = converter.getDOM(stylesheets.get(stylesheets.size() - 1), "UTF-8");
353 if (finalDoc == null)
354 {
355 return null;
356 }
357
358 for (int i = stylesheets.size() - 2; i >= 0; i--)
359 {
360
361 Document currentDoc = converter.getDOM(stylesheets.get(i), "UTF-8");
362 if (currentDoc == null)
363 {
364 return null;
365 }
366
367 if (debug)
368 {
369 GSXSLT.mergeStylesheetsDebug(finalDoc, currentDoc.getDocumentElement(), true, true, stylesheets.get(stylesheets.size() - 1).getAbsolutePath(), stylesheets.get(i).getAbsolutePath());
370 }
371 else
372 {
373 GSXSLT.mergeStylesheets(finalDoc, currentDoc.getDocumentElement(), true);
374 }
375 }
376
377 if (stylesheets.size() == 1 && debug)
378 {
379 insertDebugElements(finalDoc, stylesheets.get(0).getAbsolutePath());
380 }
381
382 return finalDoc;
383 }
384
385 /**
386 * takes any import or include nodes, and creates absolute path names for
387 * the files
388 */
389 public static void absoluteIncludePaths(Document stylesheet, String gsdl3_home, String site_name, String collection, String interface_name, ArrayList<String> base_interfaces)
390 {
391 Element base_node = stylesheet.getDocumentElement();
392 if (base_node == null)
393 {
394 return;
395 }
396 Node child = base_node.getFirstChild();
397 while (child != null)
398 {
399 String name = child.getNodeName();
400 if (name.equals("xsl:import") || name.equals("xsl:include"))
401 {
402 ((Element) child).setAttribute("href", GSFile.stylesheetFile(gsdl3_home, site_name, collection, interface_name, base_interfaces, ((Element) child).getAttribute("href")));
403 }
404 child = child.getNextSibling();
405 }
406 }
407
408
409 public static void findExtraMetadataNames(Element xsl_elem, HashSet<String> meta_names) {
410
411 // gsf:metadata and gsf:foreach-metadata
412 NodeList metadata_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "metadata");
413 NodeList foreach_metadata_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "foreach-metadata");
414 int num_meta_nodes = metadata_nodes.getLength();
415 int total_nodes = num_meta_nodes +foreach_metadata_nodes.getLength();
416 for (int i = 0; i < total_nodes; i++) {
417 Element current;
418 if (i<num_meta_nodes) {
419 current = (Element) metadata_nodes.item(i);
420 } else {
421 current = (Element) foreach_metadata_nodes.item(i-num_meta_nodes);
422 }
423 String full_name = current.getAttribute("name");
424 String select = current.getAttribute("select");
425
426 String [] names = full_name.split(",");
427 for(int j=0; j<names.length; j++) {
428
429 String name = names[j];
430 if (!name.equals("")) {
431 if (!select.equals("")) {
432 name = select + GSConstants.META_RELATION_SEP + name;
433 }
434 meta_names.add(name);
435 }
436 }
437 }
438
439 // gsf:link
440 boolean getEquivLinkMeta = false;
441 NodeList link_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "link");
442 for (int i = 0; i < link_nodes.getLength(); i++) {
443
444 Element elem = (Element) link_nodes.item(i);
445 String type = elem.getAttribute("type");
446 if (type.equals("source"))
447 {
448 meta_names.add("root_assocfilepath");
449 meta_names.add("srclinkFile");
450 }
451 else if (type.equals("web"))
452 {
453 meta_names.add("weblink");
454 meta_names.add("webicon");
455 meta_names.add("/weblink");
456 }
457 else if (type.equals("equivdoc"))
458 {
459 getEquivLinkMeta = true; // equivalent to gsf:equivlinkgs3
460 }
461 }
462 // gsf:equivlinkgs3
463 link_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "equivlinkgs3");
464 if (getEquivLinkMeta || link_nodes.getLength() > 0) {
465
466 String[] equivlink_metanames = { "equivDocIcon", "equivDocLink", "/equivDocLink" };
467
468 for (int i = 0; i < equivlink_metanames.length; i++)
469 {
470 StringBuffer metadata = new StringBuffer();
471 metadata.append("all"); // this means the attr multiple = true;
472 metadata.append(GSConstants.META_RELATION_SEP);
473
474 metadata.append(GSConstants.META_SEPARATOR_SEP);
475 metadata.append(','); // attr separator = ","
476 metadata.append(GSConstants.META_SEPARATOR_SEP);
477 metadata.append(GSConstants.META_RELATION_SEP);
478
479 // the name of the metadata we're retrieving
480 metadata.append(equivlink_metanames[i]);
481 meta_names.add(metadata.toString());
482 }
483 }
484
485 // gsf:icon
486 NodeList icon_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "icon");
487 for (int i = 0; i < icon_nodes.getLength(); i++) {
488 Element current = (Element) icon_nodes.item(i);
489 String type = current.getAttribute(GSXML.TYPE_ATT);
490 if (type == null || type.length() == 0) {
491 continue;
492 }
493 if (type.equals("web")) {
494 meta_names.add("webicon");
495 break; // this is the only one we are looking for at the moment
496 }
497 }
498
499 // gsf:image
500 NodeList image_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "image");
501 for (int i = 0; i < image_nodes.getLength(); i++) {
502 Element current = (Element) image_nodes.item(i);
503 String type = current.getAttribute(GSXML.TYPE_ATT);
504 if (type == null || type.length() == 0) {
505 continue;
506 }
507
508 if (type.equals("source")) {
509
510 String[] standardSourceMeta = new String[] { "SourceFile", "ImageHeight", "ImageWidth", "ImageType", "srcicon" };
511 for (String meta : standardSourceMeta) {
512 meta_names.add(meta);
513 }
514
515 }
516 else if (type.equals("screen")) {
517
518 String[] standardScreenMeta = new String[] { "Screen", "ScreenHeight", "ScreenWidth", "ScreenType", "screenicon" };
519 for (String meta : standardScreenMeta) {
520 meta_names.add(meta);
521 }
522 }
523 else if (type.equals("thumb")) {
524 String[] standardThumbMeta = new String[] { "Thumb", "ThumbHeight", "ThumbWidth", "ThumbType", "thumbicon" };
525 for (String meta : standardThumbMeta) {
526 meta_names.add(meta);
527 }
528 }
529 else if (type.equals("cover")) {
530 meta_names.add("hascover");
531 meta_names.add("root_hascover"); // in case we are at a section level
532 }
533 }
534 }
535
536 /**
537 * looks through a stylesheet for <xxx:template match='template_name'>
538 * inside this template it looks for any <xxx:value-of
539 * select='metadataList/metadata[@name=yyy]> elements, and extracts the
540 * metadata names into a Vector
541 */
542 public static Vector<String> extractWantedMetadata(Document stylesheet, String template_name)
543 {
544
545 Vector<String> metadata = new Vector<String>();
546 Element base_node = stylesheet.getDocumentElement();
547 NodeList templates = base_node.getElementsByTagNameNS("*", "template");
548 for (int i = 0; i < templates.getLength(); i++)
549 {
550 Element template = (Element) templates.item(i);
551 String match_name = template.getAttribute("match");
552 if (!match_name.equals(template_name))
553 {
554 continue; // we're only looking for specific templates
555 }
556 String mode = template.getAttribute("mode");
557 if (!mode.equals(""))
558 {
559 continue; // we only want ones without modes - these are processing ones, not display ones
560 }
561 // we have one that we want to look through
562 NodeList values = template.getElementsByTagNameNS("*", "value-of");
563 for (int v = 0; v < values.getLength(); v++)
564 {
565 String select = ((Element) values.item(v)).getAttribute("select");
566 if (select.startsWith("metadataList/metadata[@name="))
567 {
568 String[] bits = select.split("'|\"");
569 // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
570 String name = bits[1];
571 metadata.add(name);
572 }
573 }
574 }
575 return metadata;
576 }
577
578 public static void mergeFormatElements(Element mainFormat, Element secondaryFormat, boolean overwrite)
579 {
580 NodeList xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "variable");
581 NodeList gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "variable");
582 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
583 {
584 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
585 if (GSXML.getNamedElementNS(mainFormat, "http://www.w3.org/1999/XSL/Transform", "variable", "name", node.getAttribute("name")) == null && GSXML.getNamedElementNS(mainFormat, "http://www.greenstone.org/greenstone3/schema/ConfigFormat", "variable", "name", node.getAttribute("name")) == null)
586 {
587 mainFormat.appendChild(node);
588 }
589 }
590
591 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "param");
592 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "param");
593 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
594 {
595 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
596 if (GSXML.getNamedElementNS(mainFormat, "http://www.w3.org/1999/XSL/Transform", "param", "name", node.getAttribute("name")) == null && GSXML.getNamedElementNS(mainFormat, "http://www.greenstone.org/greenstone3/schema/ConfigFormat", "param", "name", node.getAttribute("name")) == null)
597 {
598 mainFormat.appendChild(node);
599 }
600 }
601
602 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "template");
603 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "template");
604 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
605 {
606 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
607 // remove any previous occurrences of xsl:template with the same value for name or match
608 String template_match = node.getAttribute("match");
609 String template_name = node.getAttribute("name");
610 String template_mode = node.getAttribute("mode");
611
612 String[] attributeNames = new String[] { "name", "match", "mode" };
613 String[] attributeValues = new String[] { template_name, template_match, template_mode };
614
615 if (overwrite)
616 {
617 // if we have a name attribute, remove any other similarly named template
618 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.XSL_NAMESPACE, "template", attributeNames, attributeValues);
619 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.GSF_NAMESPACE, "template", attributeNames, attributeValues);
620
621 // now add our good template in
622 mainFormat.appendChild(node);
623 }
624 else
625 {
626 // if overwrite is false, then we only add in templates if they don't match something else.
627 // In this case (eg from expanding imported stylesheets)
628 // there can't be any duplicate named templates, so just look for matches
629 // we already have the one with highest import precedence (from the top most level) so don't add any more in
630 if (GSXML.getElementsWithAttributesNS(mainFormat, "http://www.w3.org/1999/XSL/Transform", "template", attributeNames, attributeValues).getLength() == 0 && GSXML.getElementsWithAttributesNS(mainFormat, "http://www.greenstone.org/greenstone3/schema/ConfigFormat", "template", attributeNames, attributeValues).getLength() == 0)
631 {
632 mainFormat.appendChild(node);
633 }
634 }
635 }
636
637 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "option");
638 for (int i = 0; i < gsfChildren.getLength(); i++)
639 {
640 Element node = (Element) gsfChildren.item(i);
641 if (GSXML.getNamedElementNS(mainFormat, GSXML.GSF_NAMESPACE, "option", "name", node.getAttribute("name")) == null)
642 {
643 mainFormat.appendChild(node);
644 }
645 }
646 }
647
648 public static void fixTables(Document doc)
649 {
650 NodeList debugElements = doc.getElementsByTagName("debug");
651
652 HashMap<Element, ArrayList<Element>> tracker = new HashMap<Element, ArrayList<Element>>();
653 for (int i = 0; i < debugElements.getLength(); i++)
654 {
655 Element currentElement = (Element) debugElements.item(i);
656
657 boolean hasChildElements = false;
658 NodeList children = currentElement.getChildNodes();
659 for (int j = 0; j < children.getLength(); j++)
660 {
661 Node current = children.item(j);
662 if (current instanceof Element)
663 {
664 hasChildElements = true;
665 }
666 }
667
668 if (hasChildElements && currentElement.getParentNode() != null && currentElement.getParentNode() instanceof Element)
669 {
670 Element parent = findNonDebugParent(currentElement);
671 if (parent == null)
672 {
673 continue;
674 }
675
676 if (parent.getNodeName().toLowerCase().equals("table") || parent.getNodeName().toLowerCase().equals("tr"))
677 {
678 if (tracker.get(parent) == null)
679 {
680 ArrayList<Element> debugElems = new ArrayList<Element>();
681 debugElems.add(currentElement);
682 tracker.put(parent, debugElems);
683 }
684 else
685 {
686 ArrayList<Element> debugElems = tracker.get(parent);
687 debugElems.add(currentElement);
688 }
689 }
690 }
691 }
692
693 for (Element tableElem : tracker.keySet())
694 {
695 ArrayList<Element> debugElems = tracker.get(tableElem);
696 ArrayList<String> attrNames = new ArrayList<String>();
697
698 for (Element debugElem : debugElems)
699 {
700 NamedNodeMap attributes = debugElem.getAttributes();
701 for (int i = 0; i < attributes.getLength(); i++)
702 {
703 attrNames.add(attributes.item(i).getNodeName());
704 }
705 }
706
707 for (String name : attrNames)
708 {
709 String attrValueString = "[";
710 for (int i = debugElems.size() - 1; i >= 0; i--)
711 {
712 Element current = debugElems.get(i);
713 attrValueString += "\'" + current.getAttribute(name).replace("\\", "\\\\").replace("'", "\\'") + "\'";
714 if (i != 0)
715 {
716 attrValueString += ",";
717 }
718 }
719 attrValueString += "]";
720
721 tableElem.setAttribute(name, attrValueString);
722 }
723 tableElem.setAttribute("debug", "true");
724 tableElem.setAttribute("debugSize", "" + debugElems.size());
725 }
726 }
727
728 private static Element findNonDebugParent(Element elem)
729 {
730 Node parent = elem.getParentNode();
731 while (parent instanceof Element && parent.getNodeName().equals("debug"))
732 {
733 parent = parent.getParentNode();
734 }
735
736 if (parent instanceof Element)
737 {
738 return (Element) parent;
739 }
740 return null;
741 }
742
743 public static void modifyCollectionConfigForDebug(Element coll_config_xml)
744 {
745 NodeList xslTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "template");
746 NodeList gsfTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "template");
747
748 for (int i = 0; i < xslTemplates.getLength() + gsfTemplates.getLength(); i++)
749 {
750 Element currentTemplate = (Element) ((i < xslTemplates.getLength()) ? xslTemplates.item(i) : gsfTemplates.item(i - xslTemplates.getLength()));
751 Element temp = currentTemplate;
752 String xPath = "";
753 while (!temp.getNodeName().toLowerCase().equals("collectionconfig"))
754 {
755 temp = (Element) temp.getParentNode();
756 String nodeName = temp.getNodeName();
757
758 int count = 1;
759 Node counter = temp.getPreviousSibling();
760 while (counter != null)
761 {
762 if (counter.getNodeType() == Node.ELEMENT_NODE && ((Element) counter).getNodeName().equals(nodeName))
763 {
764 count++;
765 }
766 counter = counter.getPreviousSibling();
767 }
768 xPath = nodeName + ((count > 1) ? ("[" + count + "]") : "") + "/" + xPath;
769 }
770
771 xPath = xPath.substring(0, xPath.length() - 1);
772 currentTemplate.setUserData("xpath", xPath, new DataTransferHandler());
773 }
774 }
775
776 static class DataTransferHandler implements UserDataHandler
777 {
778 public void handle(short operation, String key, Object data, Node src, Node dst)
779 {
780 if (operation == NODE_IMPORTED || operation == NODE_CLONED)
781 {
782 //Thread.dumpStack();
783 dst.setUserData(key, data, new DataTransferHandler());
784 }
785 }
786 }
787}
Note: See TracBrowser for help on using the repository browser.