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

Last change on this file since 35295 was 35295, checked in by kjdon, 3 years ago

if we want to add new namespaces into collection's xsl files, we need to make sure they are added into the main xsl, and then also into expand_gslib xsl, otherwise they will be ignored and left off the page

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