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

Last change on this file since 30728 was 30728, checked in by kjdon, 8 years ago

use root_assocfilepath instead of assocfilepath in case we are at a seciton level

  • 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 import, include,
54 * 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 {
198 main.appendChild(main_xsl.importNode(node, true));
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 for " + 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 Document currentDoc = converter.getDOM(stylesheets.get(i), "UTF-8");
361 if (currentDoc == null)
362 {
363 return null;
364 }
365
366 if (debug)
367 {
368 GSXSLT.mergeStylesheetsDebug(finalDoc, currentDoc.getDocumentElement(), true, true, stylesheets.get(stylesheets.size() - 1).getAbsolutePath(), stylesheets.get(i).getAbsolutePath());
369 }
370 else
371 {
372 GSXSLT.mergeStylesheets(finalDoc, currentDoc.getDocumentElement(), true);
373 }
374 }
375
376 if (stylesheets.size() == 1 && debug)
377 {
378 insertDebugElements(finalDoc, stylesheets.get(0).getAbsolutePath());
379 }
380
381 return finalDoc;
382 }
383
384 /**
385 * takes any import or include nodes, and creates absolute path names for
386 * the files
387 */
388 public static void absoluteIncludePaths(Document stylesheet, String gsdl3_home, String site_name, String collection, String interface_name, ArrayList<String> base_interfaces)
389 {
390 Element base_node = stylesheet.getDocumentElement();
391 if (base_node == null)
392 {
393 return;
394 }
395 Node child = base_node.getFirstChild();
396 while (child != null)
397 {
398 String name = child.getNodeName();
399 if (name.equals("xsl:import") || name.equals("xsl:include"))
400 {
401 ((Element) child).setAttribute("href", GSFile.stylesheetFile(gsdl3_home, site_name, collection, interface_name, base_interfaces, ((Element) child).getAttribute("href")));
402 }
403 child = child.getNextSibling();
404 }
405 }
406
407
408 public static void findExtraMetadataNames(Element xsl_elem, HashSet<String> meta_names) {
409
410 // gsf:metadata and gsf:foreach-metadata
411 NodeList metadata_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "metadata");
412 NodeList foreach_metadata_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "foreach-metadata");
413 int num_meta_nodes = metadata_nodes.getLength();
414 int total_nodes = num_meta_nodes +foreach_metadata_nodes.getLength();
415 for (int i = 0; i < total_nodes; i++) {
416 Element current;
417 if (i<num_meta_nodes) {
418 current = (Element) metadata_nodes.item(i);
419 } else {
420 current = (Element) foreach_metadata_nodes.item(i-num_meta_nodes);
421 }
422 String full_name = current.getAttribute("name");
423 String select = current.getAttribute("select");
424
425 String [] names = full_name.split(",");
426 for(int j=0; j<names.length; j++) {
427
428 String name = names[j];
429 if (!name.equals("")) {
430 if (!select.equals("")) {
431 name = select + GSConstants.META_RELATION_SEP + name;
432 }
433 meta_names.add(name);
434 }
435 }
436 }
437
438 // gsf:link
439 boolean getEquivLinkMeta = false;
440 NodeList link_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "link");
441 for (int i = 0; i < link_nodes.getLength(); i++) {
442
443 Element elem = (Element) link_nodes.item(i);
444 String type = elem.getAttribute("type");
445 if (type.equals("source"))
446 {
447 meta_names.add("root_assocfilepath");
448 meta_names.add("srclinkFile");
449 }
450 else if (type.equals("web"))
451 {
452 meta_names.add("weblink");
453 meta_names.add("webicon");
454 meta_names.add("/weblink");
455 }
456 else if (type.equals("equivdoc"))
457 {
458 getEquivLinkMeta = true; // equivalent to gsf:equivlinkgs3
459 }
460 }
461 // gsf:equivlinkgs3
462 link_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "equivlinkgs3");
463 if (getEquivLinkMeta || link_nodes.getLength() > 0) {
464
465 String[] equivlink_metanames = { "equivDocIcon", "equivDocLink", "/equivDocLink" };
466
467 for (int i = 0; i < equivlink_metanames.length; i++)
468 {
469 StringBuffer metadata = new StringBuffer();
470 metadata.append("all"); // this means the attr multiple = true;
471 metadata.append(GSConstants.META_RELATION_SEP);
472
473 metadata.append(GSConstants.META_SEPARATOR_SEP);
474 metadata.append(','); // attr separator = ","
475 metadata.append(GSConstants.META_SEPARATOR_SEP);
476 metadata.append(GSConstants.META_RELATION_SEP);
477
478 // the name of the metadata we're retrieving
479 metadata.append(equivlink_metanames[i]);
480 meta_names.add(metadata.toString());
481 }
482 }
483
484 // gsf:icon
485 NodeList icon_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "icon");
486 for (int i = 0; i < icon_nodes.getLength(); i++) {
487 Element current = (Element) icon_nodes.item(i);
488 String type = current.getAttribute(GSXML.TYPE_ATT);
489 if (type == null || type.length() == 0) {
490 continue;
491 }
492 if (type.equals("web")) {
493 meta_names.add("webicon");
494 break; // this is the only one we are looking for at the moment
495 }
496 }
497
498 // gsf:image
499 NodeList image_nodes = xsl_elem.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "image");
500 for (int i = 0; i < image_nodes.getLength(); i++) {
501 Element current = (Element) image_nodes.item(i);
502 String type = current.getAttribute(GSXML.TYPE_ATT);
503 if (type == null || type.length() == 0) {
504 continue;
505 }
506
507 if (type.equals("source")) {
508
509 String[] standardSourceMeta = new String[] { "SourceFile", "ImageHeight", "ImageWidth", "ImageType", "srcicon" };
510 for (String meta : standardSourceMeta) {
511 meta_names.add(meta);
512 }
513
514 }
515 else if (type.equals("screen")) {
516
517 String[] standardScreenMeta = new String[] { "Screen", "ScreenHeight", "ScreenWidth", "ScreenType", "screenicon" };
518 for (String meta : standardScreenMeta) {
519 meta_names.add(meta);
520 }
521 }
522 else if (type.equals("thumb")) {
523 String[] standardThumbMeta = new String[] { "Thumb", "ThumbHeight", "ThumbWidth", "ThumbType", "thumbicon" };
524 for (String meta : standardThumbMeta) {
525 meta_names.add(meta);
526 }
527 }
528 else if (type.equals("cover")) {
529 meta_names.add("hascover");
530 logger.error("adding hascover");
531 }
532 }
533 }
534
535 /**
536 * looks through a stylesheet for <xxx:template match='template_name'>
537 * inside this template it looks for any <xxx:value-of
538 * select='metadataList/metadata[@name=yyy]> elements, and extracts the
539 * metadata names into a Vector
540 */
541 public static Vector<String> extractWantedMetadata(Document stylesheet, String template_name)
542 {
543
544 Vector<String> metadata = new Vector<String>();
545 Element base_node = stylesheet.getDocumentElement();
546 NodeList templates = base_node.getElementsByTagNameNS("*", "template");
547 for (int i = 0; i < templates.getLength(); i++)
548 {
549 Element template = (Element) templates.item(i);
550 String match_name = template.getAttribute("match");
551 if (!match_name.equals(template_name))
552 {
553 continue; // we're only looking for specific templates
554 }
555 String mode = template.getAttribute("mode");
556 if (!mode.equals(""))
557 {
558 continue; // we only want ones without modes - these are processing ones, not display ones
559 }
560 // we have one that we want to look through
561 NodeList values = template.getElementsByTagNameNS("*", "value-of");
562 for (int v = 0; v < values.getLength(); v++)
563 {
564 String select = ((Element) values.item(v)).getAttribute("select");
565 if (select.startsWith("metadataList/metadata[@name="))
566 {
567 String[] bits = select.split("'|\"");
568 // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
569 String name = bits[1];
570 metadata.add(name);
571 }
572 }
573 }
574 return metadata;
575 }
576
577 public static void mergeFormatElements(Element mainFormat, Element secondaryFormat, boolean overwrite)
578 {
579 NodeList xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "variable");
580 NodeList gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "variable");
581 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
582 {
583 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
584 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)
585 {
586 mainFormat.appendChild(node);
587 }
588 }
589
590 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "param");
591 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "param");
592 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
593 {
594 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
595 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)
596 {
597 mainFormat.appendChild(node);
598 }
599 }
600
601 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "template");
602 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "template");
603 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
604 {
605 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
606 // remove any previous occurrences of xsl:template with the same value for name or match
607 String template_match = node.getAttribute("match");
608 String template_name = node.getAttribute("name");
609 String template_mode = node.getAttribute("mode");
610
611 String[] attributeNames = new String[] { "name", "match", "mode" };
612 String[] attributeValues = new String[] { template_name, template_match, template_mode };
613
614 if (overwrite)
615 {
616 // if we have a name attribute, remove any other similarly named template
617 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.XSL_NAMESPACE, "template", attributeNames, attributeValues);
618 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.GSF_NAMESPACE, "template", attributeNames, attributeValues);
619
620 // now add our good template in
621 mainFormat.appendChild(node);
622 }
623 else
624 {
625 // if overwrite is false, then we only add in templates if they don't match something else.
626 // In this case (eg from expanding imported stylesheets)
627 // there can't be any duplicate named templates, so just look for matches
628 // we already have the one with highest import precedence (from the top most level) so don't add any more in
629 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)
630 {
631 mainFormat.appendChild(node);
632 }
633 }
634 }
635
636 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "option");
637 for (int i = 0; i < gsfChildren.getLength(); i++)
638 {
639 Element node = (Element) gsfChildren.item(i);
640 if (GSXML.getNamedElementNS(mainFormat, GSXML.GSF_NAMESPACE, "option", "name", node.getAttribute("name")) == null)
641 {
642 mainFormat.appendChild(node);
643 }
644 }
645 }
646
647 public static void fixTables(Document doc)
648 {
649 NodeList debugElements = doc.getElementsByTagName("debug");
650
651 HashMap<Element, ArrayList<Element>> tracker = new HashMap<Element, ArrayList<Element>>();
652 for (int i = 0; i < debugElements.getLength(); i++)
653 {
654 Element currentElement = (Element) debugElements.item(i);
655
656 boolean hasChildElements = false;
657 NodeList children = currentElement.getChildNodes();
658 for (int j = 0; j < children.getLength(); j++)
659 {
660 Node current = children.item(j);
661 if (current instanceof Element)
662 {
663 hasChildElements = true;
664 }
665 }
666
667 if (hasChildElements && currentElement.getParentNode() != null && currentElement.getParentNode() instanceof Element)
668 {
669 Element parent = findNonDebugParent(currentElement);
670 if (parent == null)
671 {
672 continue;
673 }
674
675 if (parent.getNodeName().toLowerCase().equals("table") || parent.getNodeName().toLowerCase().equals("tr"))
676 {
677 if (tracker.get(parent) == null)
678 {
679 ArrayList<Element> debugElems = new ArrayList<Element>();
680 debugElems.add(currentElement);
681 tracker.put(parent, debugElems);
682 }
683 else
684 {
685 ArrayList<Element> debugElems = tracker.get(parent);
686 debugElems.add(currentElement);
687 }
688 }
689 }
690 }
691
692 for (Element tableElem : tracker.keySet())
693 {
694 ArrayList<Element> debugElems = tracker.get(tableElem);
695 ArrayList<String> attrNames = new ArrayList<String>();
696
697 for (Element debugElem : debugElems)
698 {
699 NamedNodeMap attributes = debugElem.getAttributes();
700 for (int i = 0; i < attributes.getLength(); i++)
701 {
702 attrNames.add(attributes.item(i).getNodeName());
703 }
704 }
705
706 for (String name : attrNames)
707 {
708 String attrValueString = "[";
709 for (int i = debugElems.size() - 1; i >= 0; i--)
710 {
711 Element current = debugElems.get(i);
712 attrValueString += "\'" + current.getAttribute(name).replace("\\", "\\\\").replace("'", "\\'") + "\'";
713 if (i != 0)
714 {
715 attrValueString += ",";
716 }
717 }
718 attrValueString += "]";
719
720 tableElem.setAttribute(name, attrValueString);
721 }
722 tableElem.setAttribute("debug", "true");
723 tableElem.setAttribute("debugSize", "" + debugElems.size());
724 }
725 }
726
727 private static Element findNonDebugParent(Element elem)
728 {
729 Node parent = elem.getParentNode();
730 while (parent instanceof Element && parent.getNodeName().equals("debug"))
731 {
732 parent = parent.getParentNode();
733 }
734
735 if (parent instanceof Element)
736 {
737 return (Element) parent;
738 }
739 return null;
740 }
741
742 public static void modifyCollectionConfigForDebug(Element coll_config_xml)
743 {
744 NodeList xslTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "template");
745 NodeList gsfTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "template");
746
747 for (int i = 0; i < xslTemplates.getLength() + gsfTemplates.getLength(); i++)
748 {
749 Element currentTemplate = (Element) ((i < xslTemplates.getLength()) ? xslTemplates.item(i) : gsfTemplates.item(i - xslTemplates.getLength()));
750 Element temp = currentTemplate;
751 String xPath = "";
752 while (!temp.getNodeName().toLowerCase().equals("collectionconfig"))
753 {
754 temp = (Element) temp.getParentNode();
755 String nodeName = temp.getNodeName();
756
757 int count = 1;
758 Node counter = temp.getPreviousSibling();
759 while (counter != null)
760 {
761 if (counter.getNodeType() == Node.ELEMENT_NODE && ((Element) counter).getNodeName().equals(nodeName))
762 {
763 count++;
764 }
765 counter = counter.getPreviousSibling();
766 }
767 xPath = nodeName + ((count > 1) ? ("[" + count + "]") : "") + "/" + xPath;
768 }
769
770 xPath = xPath.substring(0, xPath.length() - 1);
771 currentTemplate.setUserData("xpath", xPath, new DataTransferHandler());
772 }
773 }
774
775 static class DataTransferHandler implements UserDataHandler
776 {
777 public void handle(short operation, String key, Object data, Node src, Node dst)
778 {
779 if (operation == NODE_IMPORTED || operation == NODE_CLONED)
780 {
781 //Thread.dumpStack();
782 dst.setUserData(key, data, new DataTransferHandler());
783 }
784 }
785 }
786}
Note: See TracBrowser for help on using the repository browser.