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

Last change on this file was 37022, checked in by davidb, 17 months ago

Monitoring for metadata for the new <gsf:image @image> version of gsf:image

  • Property svn:keywords set to Author Date Id Revision
File size: 28.8 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 if (type.equals("image")) {
520
521 String[] standardImageMeta = new String[] { "Image", "ImageHeight", "ImageWidth", "ImageType", "srcicon" };
522 for (String meta : standardImageMeta) {
523 meta_names.add(meta);
524 }
525
526 }
527 else if (type.equals("screen")) {
528
529 String[] standardScreenMeta = new String[] { "Screen", "ScreenHeight", "ScreenWidth", "ScreenType", "screenicon" };
530 for (String meta : standardScreenMeta) {
531 meta_names.add(meta);
532 }
533 }
534 else if (type.equals("thumb")) {
535 String[] standardThumbMeta = new String[] { "Thumb", "ThumbHeight", "ThumbWidth", "ThumbType", "thumbicon" };
536 for (String meta : standardThumbMeta) {
537 meta_names.add(meta);
538 }
539 }
540 else if (type.equals("cover")) {
541 meta_names.add("hascover");
542 meta_names.add("root_hascover"); // in case we are at a section level
543 }
544 }
545 }
546
547 /**
548 * looks through a stylesheet for <xxx:template match='template_name'>
549 * inside this template it looks for any <xxx:value-of
550 * select='metadataList/metadata[@name=yyy]> elements, and extracts the
551 * metadata names into a Vector
552 */
553 public static Vector<String> extractWantedMetadata(Document stylesheet, String template_name)
554 {
555
556 Vector<String> metadata = new Vector<String>();
557 Element base_node = stylesheet.getDocumentElement();
558 NodeList templates = base_node.getElementsByTagNameNS("*", "template");
559 for (int i = 0; i < templates.getLength(); i++)
560 {
561 Element template = (Element) templates.item(i);
562 String match_name = template.getAttribute("match");
563 if (!match_name.equals(template_name))
564 {
565 continue; // we're only looking for specific templates
566 }
567 String mode = template.getAttribute("mode");
568 if (!mode.equals(""))
569 {
570 continue; // we only want ones without modes - these are processing ones, not display ones
571 }
572 // we have one that we want to look through
573 NodeList values = template.getElementsByTagNameNS("*", "value-of");
574 for (int v = 0; v < values.getLength(); v++)
575 {
576 String select = ((Element) values.item(v)).getAttribute("select");
577 if (select.startsWith("metadataList/metadata[@name="))
578 {
579 String[] bits = select.split("'|\"");
580 // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
581 String name = bits[1];
582 metadata.add(name);
583 }
584 }
585 }
586 return metadata;
587 }
588
589 public static void mergeFormatElements(Element mainFormat, Element secondaryFormat, boolean overwrite)
590 {
591 NodeList xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "variable");
592 NodeList gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "variable");
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", "variable", "name", node.getAttribute("name")) == null && GSXML.getNamedElementNS(mainFormat, "http://www.greenstone.org/greenstone3/schema/ConfigFormat", "variable", "name", node.getAttribute("name")) == null)
597 {
598 mainFormat.appendChild(node);
599 }
600 }
601
602 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "param");
603 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "param");
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 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)
608 {
609 mainFormat.appendChild(node);
610 }
611 }
612
613 xslChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.XSL_NAMESPACE, "template");
614 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "template");
615 for (int i = 0; i < xslChildren.getLength() + gsfChildren.getLength(); i++)
616 {
617 Element node = (Element) ((i < xslChildren.getLength()) ? xslChildren.item(i) : gsfChildren.item(i - xslChildren.getLength()));
618 // remove any previous occurrences of xsl:template with the same value for name or match
619 String template_match = node.getAttribute("match");
620 String template_name = node.getAttribute("name");
621 String template_mode = node.getAttribute("mode");
622
623 String[] attributeNames = new String[] { "name", "match", "mode" };
624 String[] attributeValues = new String[] { template_name, template_match, template_mode };
625
626 if (overwrite)
627 {
628 // if we have a name attribute, remove any other similarly named template
629 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.XSL_NAMESPACE, "template", attributeNames, attributeValues);
630 GSXML.removeElementsWithAttributesNS(mainFormat, GSXML.GSF_NAMESPACE, "template", attributeNames, attributeValues);
631
632 // now add our good template in
633 mainFormat.appendChild(node);
634 }
635 else
636 {
637 // if overwrite is false, then we only add in templates if they don't match something else.
638 // In this case (eg from expanding imported stylesheets)
639 // there can't be any duplicate named templates, so just look for matches
640 // we already have the one with highest import precedence (from the top most level) so don't add any more in
641 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)
642 {
643 mainFormat.appendChild(node);
644 }
645 }
646 }
647
648 gsfChildren = GSXML.getChildrenByTagNameNS(secondaryFormat, GSXML.GSF_NAMESPACE, "option");
649 for (int i = 0; i < gsfChildren.getLength(); i++)
650 {
651 Element node = (Element) gsfChildren.item(i);
652 if (GSXML.getNamedElementNS(mainFormat, GSXML.GSF_NAMESPACE, "option", "name", node.getAttribute("name")) == null)
653 {
654 mainFormat.appendChild(node);
655 }
656 }
657 }
658
659 public static void fixTables(Document doc)
660 {
661 NodeList debugElements = doc.getElementsByTagName("debug");
662
663 HashMap<Element, ArrayList<Element>> tracker = new HashMap<Element, ArrayList<Element>>();
664 for (int i = 0; i < debugElements.getLength(); i++)
665 {
666 Element currentElement = (Element) debugElements.item(i);
667
668 boolean hasChildElements = false;
669 NodeList children = currentElement.getChildNodes();
670 for (int j = 0; j < children.getLength(); j++)
671 {
672 Node current = children.item(j);
673 if (current instanceof Element)
674 {
675 hasChildElements = true;
676 }
677 }
678
679 if (hasChildElements && currentElement.getParentNode() != null && currentElement.getParentNode() instanceof Element)
680 {
681 Element parent = findNonDebugParent(currentElement);
682 if (parent == null)
683 {
684 continue;
685 }
686
687 if (parent.getNodeName().toLowerCase().equals("table") || parent.getNodeName().toLowerCase().equals("tr"))
688 {
689 if (tracker.get(parent) == null)
690 {
691 ArrayList<Element> debugElems = new ArrayList<Element>();
692 debugElems.add(currentElement);
693 tracker.put(parent, debugElems);
694 }
695 else
696 {
697 ArrayList<Element> debugElems = tracker.get(parent);
698 debugElems.add(currentElement);
699 }
700 }
701 }
702 }
703
704 for (Element tableElem : tracker.keySet())
705 {
706 ArrayList<Element> debugElems = tracker.get(tableElem);
707 ArrayList<String> attrNames = new ArrayList<String>();
708
709 for (Element debugElem : debugElems)
710 {
711 NamedNodeMap attributes = debugElem.getAttributes();
712 for (int i = 0; i < attributes.getLength(); i++)
713 {
714 attrNames.add(attributes.item(i).getNodeName());
715 }
716 }
717
718 for (String name : attrNames)
719 {
720 String attrValueString = "[";
721 for (int i = debugElems.size() - 1; i >= 0; i--)
722 {
723 Element current = debugElems.get(i);
724 attrValueString += "\'" + current.getAttribute(name).replace("\\", "\\\\").replace("'", "\\'") + "\'";
725 if (i != 0)
726 {
727 attrValueString += ",";
728 }
729 }
730 attrValueString += "]";
731
732 tableElem.setAttribute(name, attrValueString);
733 }
734 tableElem.setAttribute("debug", "true");
735 tableElem.setAttribute("debugSize", "" + debugElems.size());
736 }
737 }
738
739 private static Element findNonDebugParent(Element elem)
740 {
741 Node parent = elem.getParentNode();
742 while (parent instanceof Element && parent.getNodeName().equals("debug"))
743 {
744 parent = parent.getParentNode();
745 }
746
747 if (parent instanceof Element)
748 {
749 return (Element) parent;
750 }
751 return null;
752 }
753
754 public static void modifyCollectionConfigForDebug(Element coll_config_xml)
755 {
756 NodeList xslTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "template");
757 NodeList gsfTemplates = coll_config_xml.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "template");
758
759 for (int i = 0; i < xslTemplates.getLength() + gsfTemplates.getLength(); i++)
760 {
761 Element currentTemplate = (Element) ((i < xslTemplates.getLength()) ? xslTemplates.item(i) : gsfTemplates.item(i - xslTemplates.getLength()));
762 Element temp = currentTemplate;
763 String xPath = "";
764 while (!temp.getNodeName().toLowerCase().equals("collectionconfig"))
765 {
766 temp = (Element) temp.getParentNode();
767 String nodeName = temp.getNodeName();
768
769 int count = 1;
770 Node counter = temp.getPreviousSibling();
771 while (counter != null)
772 {
773 if (counter.getNodeType() == Node.ELEMENT_NODE && ((Element) counter).getNodeName().equals(nodeName))
774 {
775 count++;
776 }
777 counter = counter.getPreviousSibling();
778 }
779 xPath = nodeName + ((count > 1) ? ("[" + count + "]") : "") + "/" + xPath;
780 }
781
782 xPath = xPath.substring(0, xPath.length() - 1);
783 currentTemplate.setUserData("xpath", xPath, new DataTransferHandler());
784 }
785 }
786
787 static class DataTransferHandler implements UserDataHandler
788 {
789 public void handle(short operation, String key, Object data, Node src, Node dst)
790 {
791 if (operation == NODE_IMPORTED || operation == NODE_CLONED)
792 {
793 //Thread.dumpStack();
794 dst.setUserData(key, data, new DataTransferHandler());
795 }
796 }
797 }
798}
Note: See TracBrowser for help on using the repository browser.