001: /*
002: Copyright (C) 2003 Know Gate S.L. All rights reserved.
003: C/Oņa, 107 1š2 28050 Madrid (Spain)
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions
007: are met:
008:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011:
012: 2. The end-user documentation included with the redistribution,
013: if any, must include the following acknowledgment:
014: "This product includes software parts from hipergate
015: (http://www.hipergate.org/)."
016: Alternately, this acknowledgment may appear in the software itself,
017: if and wherever such third-party acknowledgments normally appear.
018:
019: 3. The name hipergate must not be used to endorse or promote products
020: derived from this software without prior written permission.
021: Products derived from this software may not be called hipergate,
022: nor may hipergate appear in their name, without prior written
023: permission.
024:
025: This library is distributed in the hope that it will be useful,
026: but WITHOUT ANY WARRANTY; without even the implied warranty of
027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
028:
029: You should have received a copy of hipergate License with this code;
030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
031: */
032:
033: package com.knowgate.dataxslt;
034:
035: import java.util.Vector;
036: import java.util.SortedMap;
037: import java.util.TreeMap;
038: import java.util.Iterator;
039:
040: import com.knowgate.debug.DebugFile;
041: import com.knowgate.misc.Gadgets;
042:
043: import org.w3c.dom.Element;
044: import org.w3c.dom.Node;
045: import org.w3c.dom.NodeList;
046: import org.w3c.dom.DOMException;
047:
048: import dom.DOMSubDocument;
049:
050: /**
051: * <p>PageSet Page</p>
052: * <p>This class represents a <page></page> section of a PageSet XML definition file.
053: * @author Sergio Montoro Ten
054: * @version 1.1
055: */
056:
057: public class Page extends DOMSubDocument {
058: private String sPhysicalFile;
059: private PageSet oOwnerPageSet;
060:
061: // ----------------------------------------------------------
062:
063: /**
064: * @param oRefNode DOMDocument Node holding <page> element.
065: * @param oPagSet Reference to PageSet object that contains this page
066: */
067: public Page(Node oRefNode, PageSet oPagSet) {
068: super (oRefNode);
069:
070: sPhysicalFile = null;
071: oOwnerPageSet = oPagSet;
072: }
073:
074: // ----------------------------------------------------------
075:
076: /**
077: * Reference to PageSet object that contains this Page
078: */
079: public PageSet getPaseSet() {
080: return oOwnerPageSet;
081: }
082:
083: // ----------------------------------------------------------
084:
085: /**
086: * Reference to Container object that describes this Page structure
087: */
088: public Container getContainer() {
089: return oOwnerPageSet.microsite().container(container());
090: }
091:
092: // ----------------------------------------------------------
093:
094: /**
095: * Get XSL transformer stylesheet name for this Page
096: * @return <template> value for Container of this Page
097: * @throws DOMException
098: */
099: public String template() throws DOMException {
100: Microsite oMSite = oOwnerPageSet.microsite();
101:
102: Node oTopNode = oMSite.getRootNode().getFirstChild();
103:
104: if (oTopNode.getNodeName().equalsIgnoreCase("xml-stylesheet"))
105: oTopNode = oTopNode.getNextSibling();
106:
107: Node oContainers = oMSite.seekChildByName(oTopNode,
108: "containers");
109:
110: Node oContainer = (Node) oMSite.seekChildByAttr(oContainers,
111: "guid", this .container());
112:
113: if (oContainer == null) {
114: if (DebugFile.trace)
115: DebugFile
116: .writeln("ERROR: guid attribute for container "
117: + this .container() + " not found.");
118:
119: throw new DOMException(DOMException.NOT_FOUND_ERR,
120: "guid attribute for container " + this .container()
121: + " not found");
122: } // fi
123:
124: Element oTemplate = oMSite.seekChildByName(oContainer,
125: "template");
126:
127: if (oTemplate == null) {
128: if (DebugFile.trace)
129: DebugFile.writeln("ERROR: <template> node for page "
130: + this .getTitle() + " not found.");
131:
132: throw new DOMException(DOMException.NOT_FOUND_ERR,
133: "<template> node for page " + this .getTitle()
134: + " not found");
135: }
136:
137: return oMSite.getTextValue(oTemplate);
138: } // template
139:
140: // ----------------------------------------------------------
141:
142: /**
143: * @return Path to final document generated after XSL transformation of Page.
144: * This property is not part of the Page XML file but it is set at runtime and
145: * stored appart.
146: */
147: public String filePath() {
148: return sPhysicalFile;
149: }
150:
151: // ----------------------------------------------------------
152:
153: /**
154: * Set path to final document generated after XSL transformation of Page.
155: * This property is not part of the Page XML file but it is set at runtime and
156: * stored appart.
157: * @param sPath Path to generated XHTML (or other) final file.
158: */
159: public void filePath(String sPath) {
160: sPhysicalFile = sPath;
161: }
162:
163: // ----------------------------------------------------------
164:
165: /**
166: * Value of attribute guid for this Page at PageSet XML file
167: * @return GUID of this Page
168: */
169: public String guid() {
170: Node oItem = oNode.getAttributes().getNamedItem("guid");
171:
172: if (null == oItem)
173: return null;
174: else
175: return oItem.getNodeValue();
176: } // guid()
177:
178: // ----------------------------------------------------------
179:
180: /**
181: * GUID of Container that describes this Page structure
182: * @return String representing the Container GUID
183: */
184: public String container() {
185: return getElement("container");
186: } // container
187:
188: // ----------------------------------------------------------
189:
190: /**
191: * @return <title>element contents.
192: */
193: public String getTitle() {
194: return getElement("title");
195: } // getTitle
196:
197: // ----------------------------------------------------------
198:
199: /**
200: * Set <title>element contents.
201: * @param sTitle
202: */
203: public void setTitle(String sTitle) {
204: Node oCurrentNode = null;
205:
206: for (oCurrentNode = oNode.getFirstChild(); oCurrentNode != null; oCurrentNode = oCurrentNode
207: .getNextSibling())
208: if (Node.ELEMENT_NODE == oCurrentNode.getNodeType())
209: if (oCurrentNode.getNodeName().equals("title"))
210: break;
211:
212: oCurrentNode.setNodeValue(sTitle);
213: } // setTitle
214:
215: // ----------------------------------------------------------
216:
217: /**
218: * Get Page blocks.
219: * @return Vector containing objects of class Block for this Page.<br>
220: * Returned blocks are always sorted by their metablock id attribute and their
221: * block id attribute. The metablock id and the block id are concatenated
222: * @throws DOMException If <blocks> node is not found
223: */
224: public Vector blocks() throws DOMException {
225:
226: if (DebugFile.trace) {
227: DebugFile.writeln("Begin Page.blocks()");
228: DebugFile.incIdent();
229: }
230:
231: String sPaddedID;
232: Node oBlksNode = null;
233: NodeList oNodeList = null;
234: int iNodeListLen = 0;
235: Vector oLinkVctr = null;
236: SortedMap oSortedMap = new TreeMap();
237:
238: if (DebugFile.trace) {
239: if (null == oNode.getFirstChild())
240: DebugFile.writeln("Node.getFirstChild() returned null");
241: }
242:
243: for (oBlksNode = oNode.getFirstChild(); oBlksNode != null; oBlksNode = oBlksNode
244: .getNextSibling())
245: if (Node.ELEMENT_NODE == oBlksNode.getNodeType())
246: if (oBlksNode.getNodeName().equals("blocks"))
247: break;
248:
249: if (DebugFile.trace)
250: if (null == oBlksNode)
251: DebugFile.writeln("ERROR: blocks node not found");
252:
253: if (null == oBlksNode)
254: throw new DOMException(DOMException.NOT_FOUND_ERR,
255: "<blocks> node not found");
256:
257: oNodeList = ((Element) oBlksNode).getElementsByTagName("block");
258: iNodeListLen = oNodeList.getLength();
259:
260: if (DebugFile.trace)
261: DebugFile.writeln(String.valueOf(iNodeListLen)
262: + " blocks found.");
263:
264: oLinkVctr = new Vector(iNodeListLen);
265:
266: for (int i = 0; i < iNodeListLen; i++) {
267:
268: if (DebugFile.trace) {
269: if (null == oNodeList.item(i).getAttributes()
270: .getNamedItem("id"))
271: DebugFile
272: .writeln("ERROR: Block "
273: + String.valueOf(i)
274: + " does not have the required id attribute.");
275: else if (null == oNodeList.item(i).getAttributes()
276: .getNamedItem("id").getNodeValue())
277: DebugFile.writeln("ERROR: Block "
278: + String.valueOf(i)
279: + " id attribute is null.");
280: else if (oNodeList.item(i).getAttributes()
281: .getNamedItem("id").getNodeValue().length() == 0)
282: DebugFile.writeln("ERROR: Block "
283: + String.valueOf(i)
284: + " id attribute is empty.");
285: }
286:
287: sPaddedID = "-"
288: + Gadgets.leftPad(oNodeList.item(i).getAttributes()
289: .getNamedItem("id").getNodeValue(), '0', 3);
290:
291: if (DebugFile.trace)
292: DebugFile.writeln("padded id = " + sPaddedID);
293:
294: if (DebugFile.trace) {
295: if (((Element) oNodeList.item(i)).getElementsByTagName(
296: "metablock").getLength() == 0)
297: DebugFile.writeln("ERROR: No MetaBlocks found");
298: else if (null == ((Element) oNodeList.item(i))
299: .getElementsByTagName("metablock").item(0)
300: .getFirstChild())
301: DebugFile
302: .writeln("ERROR: MetaBlock for Block "
303: + String.valueOf(i)
304: + " does not have the requiered id attribute");
305: else if (((Element) oNodeList.item(i))
306: .getElementsByTagName("metablock").item(0)
307: .getFirstChild().getNodeValue().length() == 0)
308: DebugFile.writeln("ERROR: MetaBlock for Block "
309: + String.valueOf(i)
310: + " id attribute is empty.");
311: else
312: DebugFile.writeln("SortedMap.put("
313: + ((Element) oNodeList.item(i))
314: .getElementsByTagName("metablock")
315: .item(0).getFirstChild()
316: .getNodeValue() + sPaddedID + ", "
317: + oNodeList.item(i).toString());
318: }
319:
320: oSortedMap.put(((Element) oNodeList.item(i))
321: .getElementsByTagName("metablock").item(0)
322: .getFirstChild().getNodeValue()
323: + sPaddedID, oNodeList.item(i));
324: } // next (i)
325:
326: Iterator oIterator = oSortedMap.keySet().iterator();
327: while (oIterator.hasNext()) {
328: Node oAux = (Node) oSortedMap.get(oIterator.next());
329: oLinkVctr.add(new Block(oAux));
330: if (DebugFile.trace)
331: DebugFile.writeln("Inserted "
332: + ((Element) oAux).getElementsByTagName(
333: "metablock").item(0).getFirstChild()
334: .getNodeValue()
335: + (new Integer(oAux.getAttributes()
336: .getNamedItem("id").getNodeValue()))
337: .intValue());
338: } // wend
339:
340: oNodeList = null;
341: oBlksNode = null;
342: oSortedMap = null;
343:
344: if (DebugFile.trace) {
345: DebugFile.decIdent();
346: DebugFile.writeln("End Page.blocks()");
347: }
348:
349: return oLinkVctr;
350: } // blocks()
351:
352: // ----------------------------------------------------------
353:
354: private boolean eqnull(String s1, String s2) {
355: if (DebugFile.trace)
356: DebugFile.writeln("eqnull(" + s1 + "," + s2 + ")");
357:
358: if (s1 == null)
359: return true;
360: else
361: return s1.equals(s2);
362: } // eqnull
363:
364: /**
365: * Get Page blocks matching a given criteria.
366: * @param sMetaBlockId Identifier of metablock to match
367: * @param sTag
368: * @param sZone
369: * @return Vector containing objects of class Block for this Page.<br>
370: * Blocks are returned in source order. Independently of theit id attribute value.
371: * @throws DOMException If <blocks> node is not found
372: */
373: public Vector blocks(String sMetaBlockId, String sTag, String sZone)
374: throws DOMException {
375:
376: if (DebugFile.trace) {
377: DebugFile.writeln("Begin Page.blocks(" + sMetaBlockId + ","
378: + sTag + "," + sZone + ")");
379: DebugFile.incIdent();
380: }
381:
382: Block oBlk;
383: Node oAux;
384: Node oBlksNode = null;
385: NodeList oNodeList = null;
386: int iNodeListLen = 0;
387: Vector oLinkVctr = null;
388:
389: if (DebugFile.trace) {
390: if (null == oNode.getFirstChild())
391: DebugFile.writeln("Node.getFirstChild() returned null");
392: }
393:
394: for (oBlksNode = oNode.getFirstChild(); oBlksNode != null; oBlksNode = oBlksNode
395: .getNextSibling())
396: if (Node.ELEMENT_NODE == oBlksNode.getNodeType())
397: if (oBlksNode.getNodeName().equals("blocks"))
398: break;
399:
400: if (DebugFile.trace)
401: if (null == oBlksNode)
402: DebugFile.writeln("ERROR: blocks node not found");
403:
404: if (null == oBlksNode)
405: throw new DOMException(DOMException.NOT_FOUND_ERR,
406: "<blocks> node not found");
407:
408: oNodeList = ((Element) oBlksNode).getElementsByTagName("block");
409: iNodeListLen = oNodeList.getLength();
410:
411: if (DebugFile.trace)
412: DebugFile.writeln(String.valueOf(iNodeListLen)
413: + " total blocks found.");
414:
415: oLinkVctr = new Vector();
416:
417: for (int i = 0; i < iNodeListLen; i++) {
418: oAux = oNodeList.item(i);
419:
420: if (DebugFile.trace) {
421: DebugFile.writeln("scanning " + oAux);
422:
423: if (null == oAux.getAttributes().getNamedItem("id"))
424: DebugFile
425: .writeln("ERROR: Block "
426: + String.valueOf(i)
427: + " does not have the required id attribute.");
428: else if (null == oAux.getAttributes()
429: .getNamedItem("id").getNodeValue())
430: DebugFile.writeln("ERROR: Block "
431: + String.valueOf(i)
432: + " id attribute is null.");
433: else if (oAux.getAttributes().getNamedItem("id")
434: .getNodeValue().length() == 0)
435: DebugFile.writeln("ERROR: Block "
436: + String.valueOf(i)
437: + " id attribute is empty.");
438:
439: if (((Element) oAux).getElementsByTagName("metablock")
440: .getLength() == 0)
441: DebugFile.writeln("ERROR: No MetaBlocks found");
442: else if (null == ((Element) oAux).getElementsByTagName(
443: "metablock").item(0).getFirstChild())
444: DebugFile
445: .writeln("ERROR: MetaBlock for Block "
446: + String.valueOf(i)
447: + " does not have the requiered id attribute");
448: else if (((Element) oAux).getElementsByTagName(
449: "metablock").item(0).getFirstChild()
450: .getNodeValue().length() == 0)
451: DebugFile.writeln("ERROR: MetaBlock for Block "
452: + String.valueOf(i)
453: + " id attribute is empty.");
454:
455: DebugFile.writeln("new Block(" + oAux + ")");
456:
457: } // fi (DebugFile.trace)
458:
459: oBlk = new Block(oAux);
460:
461: if (eqnull(sMetaBlockId, oBlk.metablock())
462: && eqnull(sTag, oBlk.tag())
463: && eqnull(sZone, oBlk.zone())) {
464:
465: if (DebugFile.trace)
466: DebugFile.writeln("Vector.add(" + oBlk.id() + ")");
467:
468: oLinkVctr.add(oBlk);
469: }
470: } // next (i)
471:
472: oNodeList = null;
473: oBlksNode = null;
474:
475: if (DebugFile.trace) {
476: DebugFile.decIdent();
477: DebugFile.writeln("End Page.blocks()");
478: }
479:
480: return oLinkVctr;
481: } // blocks(...)
482:
483: // ----------------------------------------------------------
484:
485: /**
486: * <p>Get a list of Block identifiers in source order<p>
487: * @return Array of Block Identifiers in the same order as thay appear in source document.
488: * @throws NumberFormatException If any Block Id. is not an integer
489: */
490: public int[] blockIds() throws NumberFormatException {
491: Node oBlksNode = null;
492: NodeList oNodeList = null;
493: int iNodeListLen = 0;
494:
495: for (oBlksNode = oNode.getFirstChild(); oBlksNode != null; oBlksNode = oBlksNode
496: .getNextSibling())
497: if (Node.ELEMENT_NODE == oBlksNode.getNodeType())
498: if (oBlksNode.getNodeName().equals("blocks"))
499: break;
500:
501: oNodeList = ((Element) oBlksNode).getElementsByTagName("block");
502: iNodeListLen = oNodeList.getLength();
503:
504: int[] aIds = new int[iNodeListLen];
505:
506: for (int i = 0; i < iNodeListLen; i++)
507: aIds[i] = Integer.parseInt(oNodeList.item(i)
508: .getAttributes().getNamedItem("id").getNodeValue());
509:
510: return aIds;
511: } // blockIds
512:
513: // ----------------------------------------------------------
514:
515: /**
516: * Get next free block integer identifier.
517: * @return Left padded next free block identifier (3 characters)
518: * @throws NumberFormatException If any of the previous block identifiers is not an integer.
519: */
520: public String nextBlockId() throws NumberFormatException {
521:
522: if (DebugFile.trace) {
523: DebugFile.writeln("Begin Page.nextBlockId()");
524: DebugFile.incIdent();
525: }
526:
527: int iBlk = 0;
528: int iMax = 0;
529: String sNext;
530: Node oBlksNode = null;
531: NodeList oNodeList = null;
532: int iNodeListLen = 0;
533:
534: for (oBlksNode = oNode.getFirstChild(); oBlksNode != null; oBlksNode = oBlksNode
535: .getNextSibling())
536: if (Node.ELEMENT_NODE == oBlksNode.getNodeType())
537: if (oBlksNode.getNodeName().equals("blocks"))
538: break;
539:
540: if (DebugFile.trace)
541: if (null == oBlksNode)
542: DebugFile.writeln("ERROR: blocks node not found");
543:
544: oNodeList = ((Element) oBlksNode).getElementsByTagName("block");
545: iNodeListLen = oNodeList.getLength();
546:
547: int[] aBlocks = new int[iNodeListLen];
548:
549: for (int i = 0; i < iNodeListLen; i++)
550: aBlocks[i] = Integer.parseInt(oNodeList.item(i)
551: .getAttributes().getNamedItem("id").getNodeValue());
552:
553: for (int b = 0; b < iNodeListLen; b++) {
554: iBlk = aBlocks[b];
555: if (iBlk > iMax)
556: iMax = iBlk;
557: } // next (b)
558:
559: // left pad with zeros
560: sNext = String.valueOf(iMax + 1);
561: if (sNext.length() == 1)
562: sNext = "00" + sNext;
563: else if (sNext.length() == 2)
564: sNext = "0" + sNext;
565:
566: if (DebugFile.trace) {
567: DebugFile.decIdent();
568: DebugFile.writeln("End Page.nextBlockId() : " + sNext);
569: }
570:
571: return sNext;
572: } // nextBlockId
573:
574: // ----------------------------------------------------------
575:
576: /**
577: * <p>Permute Blocks</p>
578: * This method is used for reordering blocks.
579: * @param aNewBlcksPerm New order for blocks.
580: * @throws ArrayIndexOutOfBoundsException
581: */
582: public void permute(int[] aNewBlcksPerm)
583: throws ArrayIndexOutOfBoundsException {
584:
585: if (DebugFile.trace) {
586: DebugFile.writeln("Begin Page.permute()");
587: DebugFile.incIdent();
588: }
589:
590: int iCurrent;
591: int[] aOldBlcksPerm = blockIds();
592:
593: // Check that existing and new block permutations have same count of blocks
594: if (aOldBlcksPerm.length != aNewBlcksPerm.length)
595: throw new ArrayIndexOutOfBoundsException(
596: "Length of Blocks array does not match Block count for already loaded Document");
597:
598: Vector vOldPerm = blocks();
599: int iBlckCount = vOldPerm.size();
600:
601: if (iBlckCount > 0) {
602: Vector vNewPerm = new Vector(iBlckCount);
603:
604: // Create a Vector with Blocks cloned from the existing ones but in the new order
605: for (int blck = 0; blck < iBlckCount; blck++) {
606: iCurrent = aNewBlcksPerm[blck];
607:
608: for (int oldpos = 0; oldpos < iBlckCount; oldpos++) {
609:
610: if (aOldBlcksPerm[oldpos] == iCurrent) {
611: vNewPerm
612: .add(new Block(((Block) vOldPerm
613: .get(oldpos)).getNode()
614: .cloneNode(true)));
615: break;
616: }
617: } // next (oldpos)
618: } // next (blck)
619:
620: // Search for <blocks> Node
621: if (DebugFile.trace) {
622: if (null == oNode.getFirstChild())
623: DebugFile
624: .writeln("Node.getFirstChild() returned null");
625: }
626:
627: Node oBlksNode = null;
628:
629: for (oBlksNode = oNode.getFirstChild(); oBlksNode != null; oBlksNode = oBlksNode
630: .getNextSibling())
631: if (Node.ELEMENT_NODE == oBlksNode.getNodeType())
632: if (oBlksNode.getNodeName().equals("blocks"))
633: break;
634:
635: if (DebugFile.trace)
636: if (null == oBlksNode)
637: DebugFile.writeln("ERROR: blocks node not found");
638:
639: // Remove all old Blocks
640: for (int chld = 0; chld < iBlckCount; chld++)
641: oBlksNode.removeChild(((Block) vOldPerm.get(chld))
642: .getNode());
643:
644: // Re-insert previously cloned Blocks
645: Block oClon;
646: for (int chld = 0; chld < iBlckCount; chld++) {
647: oClon = ((Block) vNewPerm.get(chld));
648:
649: // Assign next block identifier for mantining consistency between
650: // source order and id attributes
651: oClon.id(Gadgets.leftPad(String.valueOf(chld + 1), '0',
652: 3));
653:
654: oBlksNode.appendChild(oClon.getNode());
655: } // next
656: } // fi (iBlckCount>0)
657:
658: if (DebugFile.trace) {
659: DebugFile.decIdent();
660: DebugFile.writeln("End Page.permute()");
661: }
662: } // permute
663: }
|