KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > intro > impl > model > AbstractIntroPage


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.intro.impl.model;
12
13 import java.util.Hashtable JavaDoc;
14 import java.util.Vector JavaDoc;
15
16 import org.eclipse.core.runtime.IPath;
17 import org.eclipse.core.runtime.Path;
18 import org.eclipse.core.runtime.Platform;
19 import org.eclipse.help.internal.UAElement;
20 import org.eclipse.help.internal.UAElementFactory;
21 import org.eclipse.help.internal.dynamic.DocumentProcessor;
22 import org.eclipse.help.internal.dynamic.FilterHandler;
23 import org.eclipse.help.internal.dynamic.ProcessorHandler;
24 import org.eclipse.ui.internal.intro.impl.IIntroConstants;
25 import org.eclipse.ui.internal.intro.impl.model.loader.ExtensionPointManager;
26 import org.eclipse.ui.internal.intro.impl.model.loader.IntroContentParser;
27 import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
28 import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
29 import org.eclipse.ui.internal.intro.impl.model.util.ModelUtil;
30 import org.eclipse.ui.internal.intro.impl.util.IntroEvaluationContext;
31 import org.eclipse.ui.internal.intro.impl.util.Log;
32 import org.eclipse.ui.internal.intro.impl.util.StringUtil;
33 import org.osgi.framework.Bundle;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.Element JavaDoc;
36 import org.w3c.dom.Node JavaDoc;
37 import org.w3c.dom.NodeList JavaDoc;
38
39 /**
40  * Base class for all Intro pages, inlcuding HomePage. Adds page specific
41  * support:
42  * <ul>
43  * <li>support for page styles, and style inheritance</li>
44  * <li>support for XHTML via a DOM instance var. Resolving the page is also
45  * handled here.</li>
46  * <li>a pge has the concept of being an IFramePage. This is indicated by the
47  * isIFrame flag. A page is an IFramePage when it is not defined in any content
48  * file, but instead is actually created at runtime. This is done to display a
49  * Help System topic embedded in any given div. The current page is cloned, its
50  * id is mangled with "_embedDivId", the content of the div pointed to by
51  * embedDivId is replaced with an IFrame that loads the Help System topic.</li>
52  * </ul>
53  */

54 public abstract class AbstractIntroPage extends AbstractIntroContainer {
55
56     protected static final String JavaDoc TAG_PAGE = "page"; //$NON-NLS-1$
57
private static final String JavaDoc ATT_STYLE = "style"; //$NON-NLS-1$
58
private static final String JavaDoc ATT_ALT_STYLE = "alt-style"; //$NON-NLS-1$
59
private static final String JavaDoc ATT_CONTENT = "content"; //$NON-NLS-1$
60
private static final String JavaDoc ATT_SHARED_STYLE = "shared-style"; //$NON-NLS-1$
61
private static final String JavaDoc INVALID_CONTENT = "invalidPage/invalidPage.xhtml"; //$NON-NLS-1$
62
private static final String JavaDoc INVALID_CONTENT_BASE = "invalidPage"; //$NON-NLS-1$
63

64     private String JavaDoc style;
65     private String JavaDoc altStyle;
66     private String JavaDoc sharedStyle;
67     private IntroPageTitle title;
68     private String JavaDoc content;
69
70     // if iframe is not null, this indicates that this page was cloned at
71
// runtime from another page whose id was "originalId".
72
private IntroInjectedIFrame iframe;
73
74     // id of page from which this page was cloned.
75
private String JavaDoc originalId;
76
77     // DOM representing XHTML content. DOM is only cached in the case of XHTML
78
// content.
79
private Document JavaDoc dom;
80     
81     private DocumentProcessor domProcessor;
82
83     // set when the content file is loaded (ie: loadChildren is called)
84
private boolean isXHTMLPage;
85
86     // Model base attribute is stored in parent class. This base attribute here
87
// is to cache the initial location of the content file. When content
88
// attribute is defined, the base in the model becomes relative to
89
// new xml file. However, in the case of XHTML content, and when
90
// presentation is UI forms, we need to reuse initial content file location.
91
private String JavaDoc initialBase;
92
93     /**
94      * The vectors to hold all inhertied styles and alt styles from included
95      * elements. They are lazily created when children are resolved (ie:
96      * includes are resolved) OR when extensions are resolved and styles need to
97      * be added to the target page.
98      * <p>
99      * Style Rules:
100      * <ul>
101      * <li>For includes, merge-style controls wether or not the enclosing page
102      * inherits the styles of the target.
103      * <li>If a page is including a shared div, merging target styles into this
104      * page is ignored. Shared divs do not have styles.</li>
105      * <li>For extensions, if the style or alt-style is not defined, that means
106      * that no style inheritence is needed, and the style of the target page are
107      * not updated.
108      * <li>If an extension is extending a shared div, merging the styles of
109      * this extension into the target is ignored. Shared divs do not have
110      * styles.</li>
111      * <li>Shared hashtable has alt-styles as keys and bundles as values.</li>
112      * </ul>
113      */

114     private Vector JavaDoc styles;
115     private Hashtable JavaDoc altStyles;
116
117     /**
118      * Parent class for all pages. Make sure to set the bundle to where the
119      * pages are loaded from. This means that the bundle for root may be
120      * different from the bundle for all the other pages. Only pages do this
121      * logic and so other model objects might have the wrong bundle cached if
122      * the resource was loaded from an nl directory.
123      *
124      * @param element
125      */

126     AbstractIntroPage(Element element, Bundle bundle, String JavaDoc base) {
127         super(element, bundle, base);
128         this.initialBase = base;
129         content = getAttribute(element, ATT_CONTENT);
130         if (content == null) {
131             //Delaying init until we have the model
132
// so that we can resolve theme
133
//init(element, bundle, base);
134
}
135         else {
136             // Content is not null. Resolve it. Other page attributes (style,
137
// alt-style...) will be loaded when xml content file is loaded
138
// since we need to pick them up from external xml content file. In
139
// the case where this external content file is XHTML and we have
140
// HTML presentation, page attributes are simply not loaded. In the
141
// case where we have XHTML in a UI forms presentation, we will need
142
// to load initial page attributes.
143
// BASE: since content is being loaded from another xml file, point
144
// the base of this page to be relative to the new xml file
145
// location.
146
IPath subBase = ModelUtil.getParentFolderPath(content);
147             this.base = new Path(base).append(subBase).toString();
148             content = BundleUtil.getResolvedResourceLocation(base, content,
149                 bundle);
150         }
151         // load shared-style attribure. This is needed in the XML and in the
152
// XHTML cases. Default is to include shared style.
153
this.sharedStyle = getAttribute(element, ATT_SHARED_STYLE);
154         if (sharedStyle == null)
155             sharedStyle = "true"; //$NON-NLS-1$
156

157     }
158     
159     public void setParent(AbstractIntroElement parent) {
160         super.setParent(parent);
161         if (content == null)
162             init(element, getBundle(), initialBase);
163     }
164     
165     /**
166      * Returns unresolved content value as found in the source file.
167      * the source file.
168      * @return the unresolved content value
169      */

170     
171     public String JavaDoc getRawContent() {
172         return getAttribute(element, ATT_CONTENT);
173     }
174
175     /**
176      * Initialize styles. Take first style in style attribute and make it the
177      * page style. Then put other styles in styles vectors. Make sure to resolve
178      * each style.
179      *
180      * @param element
181      * @param bundle
182      */

183     private void init(Element element, Bundle bundle, String JavaDoc base) {
184         String JavaDoc[] styleValues = getAttributeList(element, ATT_STYLE);
185         if (styleValues != null && styleValues.length > 0) {
186             style = styleValues[0];
187             style = BundleUtil.getResolvedResourceLocation(base, style, bundle);
188             for (int i = 1; i < styleValues.length; i++) {
189                 String JavaDoc style = styleValues[i];
190                 style = BundleUtil.getResolvedResourceLocation(base, style,
191                     bundle);
192                 addStyle(style);
193             }
194         }
195
196         String JavaDoc[] altStyleValues = getAttributeList(element, ATT_ALT_STYLE);
197         if (altStyleValues != null && altStyleValues.length > 0) {
198             altStyle = altStyleValues[0];
199             altStyle = BundleUtil.getResolvedResourceLocation(base, altStyle,
200                 bundle);
201             for (int i = 1; i < altStyleValues.length; i++) {
202                 String JavaDoc style = altStyleValues[i];
203                 style = BundleUtil.getResolvedResourceLocation(base, style,
204                     bundle);
205                 addAltStyle(style, bundle);
206             }
207         }
208     }
209
210
211
212
213     /**
214      * The page's title. Each page can have one title.
215      *
216      * @return Returns the title of this page.
217      */

218     public String JavaDoc getTitle() {
219         // title is a child of the page, and so we have to load children first.
220
// We also have to resolve children because someone might be including a
221
// title. Update title instance after all includes and extensions have
222
// been resolved.
223
getChildren();
224         if (title == null) {
225             // there should only be one title child per page. safe to cast.
226
IntroPageTitle[] titles = (IntroPageTitle[]) getChildrenOfType(AbstractIntroElement.PAGE_TITLE);
227             if (titles.length > 0)
228                 title = titles[0];
229         }
230
231         if (title == null)
232             // still null. no title.
233
return null;
234         return title.getTitle();
235     }
236
237     /**
238      * @return Returns the style.
239      */

240     public String JavaDoc getStyle() {
241         return style;
242     }
243
244     /**
245      * @return Returns the alt_style.
246      */

247     public String JavaDoc getAltStyle() {
248         return altStyle;
249     }
250
251     /**
252      * Gets all the inherited styles of this page. Styles can be inherited from
253      * includes or from configExtensions.
254      * <p>
255      * Note: this call needs to get all the children of this page, and so it
256      * will resolve this page. might be expensive.
257      *
258      * @return Returns all the inherited styles of this page. Returns an empty
259      * array if page is not expandable or does not have inherited
260      * styles.
261      */

262     public String JavaDoc[] getStyles() {
263         // call get children first to resolve includes and populate styles
264
// vector. Resolving children will initialize the style vectors.
265
getChildren();
266         if (styles == null)
267             // style vector is still null because page does not have styles.
268
return new String JavaDoc[0];
269         String JavaDoc[] stylesArray = new String JavaDoc[styles.size()];
270         styles.copyInto(stylesArray);
271         return stylesArray;
272     }
273
274     /**
275      * Gets all the inherited alt-styles of this page (ie: styles for the SWT
276      * presentation). A hashtable is returned that has inhertied alt-styles as
277      * keys, and plugin descriptors as values. This is needed to be able to load
278      * resources from the inherited target plugin. Note: this call needs to get
279      * all the children of this page, and so its will resolve this page. might
280      * be expensive.
281      *
282      * @return Returns all the inherited styles of this page. Returns an empty
283      * hashtable if page is not expandable, does not have any includes,
284      * or has includes that do not merge styles.
285      */

286     public Hashtable JavaDoc getAltStyles() {
287         // call get children first to resolve includes and populate hashtable.
288
// Resolving children will initialize the style vectors.
289
getChildren();
290         return altStyles;
291     }
292
293     /**
294      * Adds the given style to the list. Style is not added if it already exists
295      * in the list.
296      *
297      * @param style
298      */

299     protected void addStyle(String JavaDoc style) {
300         if (!initStyles(style))
301             return;
302         if (styles.contains(style))
303             return;
304         styles.add(style);
305     }
306
307     public void insertStyle(String JavaDoc style, int location) {
308         if (!initStyles(style))
309             return;
310         if (styles.contains(style))
311             return;
312         styles.add(location, style);
313     }
314
315
316
317     /**
318      * Adds the given style to the list.Style is not added if it already exists
319      * in the list.
320      *
321      * @param altStyle
322      */

323     protected void addAltStyle(String JavaDoc altStyle, Bundle bundle) {
324         if (!initAltStyles(altStyle))
325             return;
326         if (altStyles.containsKey(altStyle))
327             return;
328         altStyles.put(altStyle, bundle);
329     }
330
331
332     /**
333      * Util method to add given styles to the list.
334      *
335      */

336     protected void addStyles(String JavaDoc[] styles) {
337         if (styles == null)
338             return;
339         for (int i = 0; i < styles.length; i++)
340             addStyle(styles[i]);
341     }
342
343     /**
344      * Util method to add map of altstyles to list.
345      */

346     protected void addAltStyles(Hashtable JavaDoc altStyles) {
347         if (altStyles == null)
348             return;
349         if (this.altStyles == null)
350             // delay creation until needed.
351
this.altStyles = new Hashtable JavaDoc();
352         this.altStyles.putAll(altStyles);
353     }
354
355
356     private boolean initStyles(String JavaDoc style) {
357         if (style == null)
358             return false;
359         if (this.styles == null)
360             // delay creation until needed.
361
this.styles = new Vector JavaDoc();
362         return true;
363     }
364
365     private boolean initAltStyles(String JavaDoc style) {
366         if (style == null)
367             return false;
368         if (this.altStyles == null)
369             // delay creation until needed.
370
this.altStyles = new Hashtable JavaDoc();
371         return true;
372     }
373
374
375     /*
376      * (non-Javadoc)
377      *
378      * @see org.eclipse.ui.internal.intro.impl.model.IntroElement#getType()
379      */

380     public int getType() {
381         return AbstractIntroElement.ABSTRACT_PAGE;
382     }
383
384     /*
385      * Override parent behavior to lazily initialize styles vectors. This will
386      * only be called once, if resolved == false. In the case of DOM model,
387      * resolve this page's full DOM.
388      *
389      * @see org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer#resolveChildren()
390      */

391     protected void resolveChildren() {
392         // flag would be set
393
if (isXHTMLPage)
394             resolvePage();
395         else
396             super.resolveChildren();
397     }
398
399
400
401     /**
402      * Override parent behavior to add support for HEAD & Title element in pages
403      * only, and not in divs.
404      *
405      * @see org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer#getModelChild(org.eclipse.core.runtime.IConfigurationElement)
406      */

407     protected AbstractIntroElement getModelChild(Element childElement,
408             Bundle bundle, String JavaDoc base) {
409         AbstractIntroElement child = null;
410         if (childElement.getNodeName().equalsIgnoreCase(IntroHead.TAG_HEAD)) {
411             child = new IntroHead(childElement, bundle, base);
412         } else if (childElement.getNodeName().equalsIgnoreCase(
413             IntroPageTitle.TAG_TITLE)) {
414             // if we have a title, only add it as a child if we did not load one
415
// before. A page can only have one title.
416
if (title == null) {
417                 child = new IntroPageTitle(childElement, bundle);
418             }
419         }
420         if (child != null)
421             return child;
422         return super.getModelChild(childElement, bundle, base);
423     }
424
425     /**
426      * Returns all head contributions in this page. There can be more than one
427      * head contribution in the page;
428      *
429      * @return
430      */

431     public IntroHead[] getHTMLHeads() {
432         return (IntroHead[]) getChildrenOfType(AbstractIntroElement.HEAD);
433     }
434
435
436     /**
437      * load the children of this container. Override parent behavior because we
438      * want to support loading content from other xml files. The design is that
439      * only the id and content from the existing page are honored. All other
440      * attributes are what they are defined in the external paget. For XHTML
441      * content, all info is in the xhtml page. If we fail to load the page,
442      * display the Invalid Page page.
443      */

444     protected void loadChildren() {
445         if (content == null) {
446             // no content. do regular loading.
447
super.loadChildren();
448             return;
449         }
450
451         // content attribute is defined. It either points to an XHTML file, or
452
// an introContent.xml file. Process each case. Assume it is an
453
// introContent file.
454
// INTRO: XHTML file is loaded needlessly when we have XHTML content and
455
// SWT presentation.
456
IntroContentParser parser = new IntroContentParser(content);
457         Document JavaDoc dom = parser.getDocument();
458         if (dom == null) {
459             // bad xml. This could be bad XHTML or bad intro XML. Parser would
460
// have logged fact. Load dom for invalid page, and make sure to
461
// force an extract on parent folder to enabling jarring.
462
Bundle introBundle = Platform.getBundle(IIntroConstants.PLUGIN_ID);
463             ModelUtil.ensureFileURLsExist(introBundle, INVALID_CONTENT);
464
465             String JavaDoc invalidContentFilePath = BundleUtil
466                 .getResolvedResourceLocation(INVALID_CONTENT, introBundle);
467             parser = new IntroContentParser(invalidContentFilePath);
468             dom = parser.getDocument();
469             // make sure to override all attributes to resolve the Invalid
470
// Page page correctly.
471
content = invalidContentFilePath;
472             this.base = INVALID_CONTENT_BASE;
473             setBundle(introBundle);
474         }
475
476         // parse content depending on type. Make sure to set the loaded flag
477
// accordingly, otherwise content file will always be parsed.
478
if (parser.hasXHTMLContent()) {
479             loadXHTMLContent(dom);
480             // make sure to use correct base.
481
init(element, getBundle(), initialBase);
482             super.loadChildren();
483         } else
484             // load the first page with correct id, from content xml file.
485
loadXMLContent(dom);
486     }
487
488     /**
489      * Load the xml content from the introContent.xml file pointed to by the
490      * content attribute, and loaded into the passed DOM. Load the first page
491      * with correct id from this content file.
492      *
493      * @param dom
494      */

495     private void loadXMLContent(Document JavaDoc dom) {
496         Element[] pages = ModelUtil.getElementsByTagName(dom,
497             AbstractIntroPage.TAG_PAGE);
498         if (pages.length == 0) {
499             Log.warning("Content file has no pages."); //$NON-NLS-1$
500
return;
501         }
502         // point the element of this page to the new element. Pick first page
503
// with matching id. Make sure to disable loading of children of current
504
// element if a matching page in the external content file is not found.
505
boolean foundMatchingPage = false;
506         for (int i = 0; i < pages.length; i++) {
507             Element pageElement = pages[i];
508             if (pageElement.getAttribute(AbstractIntroIdElement.ATT_ID).equals(
509                 getId())) {
510                 this.element = pageElement;
511                 // call init on the new element. the filtering and the style-id
512
// are loaded by the parent class.
513
init(pageElement, getBundle(), base);
514                 // INTRO: revisit. Special processing here should be made more
515
// general. we know id is correct.
516
style_id = getAttribute(element,
517                     AbstractBaseIntroElement.ATT_STYLE_ID);
518                 filteredFrom = getAttribute(element,
519                     AbstractBaseIntroElement.ATT_FILTERED_FROM);
520                 sharedStyle = getAttribute(element, ATT_SHARED_STYLE);
521                 if (sharedStyle == null)
522                     sharedStyle = "true"; //$NON-NLS-1$
523
foundMatchingPage = true;
524             }
525         }
526         if (foundMatchingPage)
527             // now do children loading as usual.
528
super.loadChildren();
529         else {
530             // page was not found in content file. Perform load actions, and log
531
// fact. init the children vector.
532
children = new Vector JavaDoc();
533             loaded = true;
534             // free DOM model for memory performance.
535
element = null;
536             Log.warning("Content file does not have page with id= " + getId()); //$NON-NLS-1$
537
}
538     }
539
540     private void loadXHTMLContent(Document JavaDoc dom) {
541         // no need to load any children since we use XSLT to print XHTML
542
// content. Simply cache DOM.
543
this.dom = dom;
544         this.isXHTMLPage = true;
545         // init empty children vector.
546
children = new Vector JavaDoc();
547         loaded = true;
548     }
549
550     /**
551      * Returns the DOM representing an external XHTML file. May return null if
552      * extension content is 3.0 format. The page is resolved before returning,
553      * meaning includes are resolved, and the base of the page is defined.
554      *
555      * @return
556      */

557     public Document JavaDoc getResolvedDocument() {
558         // we need to force a getChildren to resolve the page.
559
getChildren();
560         return dom;
561     }
562
563
564     /**
565      * Returns the DOM representing an external XHTML file. May return null if
566      * extension content is 3.0 format. The page is NOT resolved before
567      * returning. It is retruned as given by the dom parser.
568      *
569      * @return
570      */

571     public Document JavaDoc getDocument() {
572         // we only need to load children here.
573
if (!loaded)
574             loadChildren();
575         return dom;
576     }
577
578
579     /**
580      * Returns whether or not we have an XHTML page as the content for this
581      * page. The XHTML page is defined through the content attribute. This
582      * method forces the content file to be parsed and loaded in memory.
583      *
584      * @return
585      */

586     public boolean isXHTMLPage() {
587         // we need to force loading of children since we need to determine
588
// content type. Load the children without resolving (for performance),
589
// this will set the XHTML flag at the page level.
590
if (!loaded)
591             loadChildren();
592         return isXHTMLPage;
593     }
594
595
596     /**
597      * Deep searches all children in this container's DOM for the first child
598      * with the given id. The element retrieved must have the passed local name.
599      * Note that in an XHTML file (aka DOM) elements should have a unique id
600      * within the scope of a document. We use local name because this allows for
601      * finding intro anchors, includes and dynamic content element regardless of
602      * whether or not an xmlns was used in the xml. note: could not have used
603      * inheritance from parent container because return type for parent is intro
604      * legacy model.
605      *
606      */

607     public Element findDomChild(String JavaDoc id, String JavaDoc localElementName) {
608         if (!loaded)
609             loadChildren();
610         // using getElementById is tricky and we need to have intro XHTML
611
// modules to properly use this method.
612
return ModelUtil.getElementById(dom, id, localElementName);
613     }
614
615     /**
616      * Search for any element with the given id.
617      *
618      * @param id
619      * @return
620      */

621     public Element findDomChild(String JavaDoc id) {
622         return findDomChild(id, "*"); //$NON-NLS-1$
623

624     }
625
626
627
628     /**
629      * Resolves the full page. It is called just before the page needs to be
630      * displayed.
631      * <li>adds a BASE child to the DOM HEAD element, if one is not defined.
632      * All intro documents must have a base defined to resolve all urls.</li>
633      * <li>resolves all includes in the page. This means importing target DOM.
634      * </li>
635      * <li>resolves all XHTML attributes for resources, eg: src, href
636      * attributes.</li>
637      */

638     protected void resolvePage() {
639         // insert base meta-tag,
640
ModelUtil.insertBase(dom, ModelUtil.getParentFolderOSString(content));
641
642         // resolve all relative resources relative to content file. Do it before
643
// inserting shared style to enable comparing fully qualified styles.
644
ModelUtil.updateResourceAttributes(dom.getDocumentElement(), this);
645
646         // now add shared style.
647
IntroModelRoot modelRoot = (IntroModelRoot)getParent();
648         IntroPartPresentation presentation = modelRoot.getPresentation();
649         String JavaDoc [] styles = presentation!=null?presentation.getImplementationStyles():null;
650         if (styles != null && injectSharedStyle()) {
651             for (int i=0; i<styles.length; i++)
652                 ModelUtil.insertStyle(dom, styles[i]);
653         }
654
655         // filter the content
656
if (domProcessor == null) {
657             domProcessor = new DocumentProcessor(new ProcessorHandler[] { new FilterHandler(IntroEvaluationContext.getContext()) });
658         }
659         UAElement element = UAElementFactory.newElement(dom.getDocumentElement());
660         domProcessor.process(element, null);
661         
662         // and resolve includes.
663
resolveIncludes();
664
665         // now remove all anchors from this page.
666
ModelUtil.removeAllElements(dom, IntroAnchor.TAG_ANCHOR);
667         resolved = true;
668     }
669
670     /**
671      * Resolves all includes in this page. This means importing the DOM of the
672      * target path into the current page DOM, and resolving XHTML attributes for
673      * resources.
674      */

675     protected void resolveIncludes() {
676         // get all includes elements in DOM.
677
NodeList JavaDoc includes = dom.getElementsByTagNameNS("*", //$NON-NLS-1$
678
IntroInclude.TAG_INCLUDE);
679         // get the array version of the include nodelist to work around
680
// replaceChild() DOM api design.
681
Node JavaDoc[] nodes = ModelUtil.getArray(includes);
682         for (int i = 0; i < nodes.length; i++) {
683             Element includeElement = (Element) nodes[i];
684             IntroInclude include = new IntroInclude(includeElement, getBundle());
685             // result[0] is target parent page, result[1] is target element.
686
Object JavaDoc[] results = findDOMIncludeTarget(include);
687             Element targetElement = (Element) results[1];
688             if (targetElement == null) {
689                 String JavaDoc message = "Could not resolve following include: " //$NON-NLS-1$
690
+ ModelLoaderUtil.getLogString(getBundle(),
691                             includeElement, IntroInclude.ATT_PATH);
692                 Log.warning(message);
693                 return;
694             }
695
696             // insert the target element instead of the include.
697
Node JavaDoc targetNode = dom.importNode(targetElement, true);
698             // update the src attribute of this node, if defined by w3
699
// specs.
700
AbstractIntroPage page = ((AbstractIntroPage) results[0]);
701             ModelUtil.updateResourceAttributes((Element) targetNode, page);
702             // use of replace API to remove include element is tricky. It
703
// confuses the NodeList used in the loop above. Removing an include
704
// removes it from the NodeList. Used cloned Array instead.
705
includeElement.getParentNode().replaceChild(targetNode,
706                 includeElement);
707         }
708     }
709
710
711     /**
712      * Find the target Element pointed to by the path in the include. It is
713      * assumed that configId always points to an external config, and not the
714      * same config of the inlcude.
715      *
716      * @param include
717      * @param path
718      * @return
719      */

720     private Object JavaDoc[] findDOMIncludeTarget(IntroInclude include) {
721         String JavaDoc path = include.getPath();
722         IntroModelRoot targetModelRoot = (IntroModelRoot) getParentPage()
723             .getParent();
724         String JavaDoc targetConfigID = include.getConfigId();
725         if (targetConfigID != null)
726             targetModelRoot = ExtensionPointManager.getInst().getModel(
727                 targetConfigID);
728         if (targetModelRoot == null)
729             // if the target config was not found, skip this include.
730
return null;
731         return findDOMTarget(targetModelRoot, path);
732
733     }
734
735
736
737     /**
738      * Finds the child element that corresponds to the given path in the passed
739      * model.
740      *
741      * @param model
742      * model containing target path.
743      * @param path
744      * the path to look for
745      * @param results
746      * two object array that will return the target intro page as the
747      * first result, and the actual target DOM Element as the second
748      * result. It is gauranteed to not be null. Content may be null.
749      * @return target DOM element
750      */

751     public Object JavaDoc[] findDOMTarget(IntroModelRoot model, String JavaDoc path) {
752         Object JavaDoc[] results = new Object JavaDoc[2];
753         // path must be pageId/anchorID in the case of of XHTML pages.
754
// pages.
755
String JavaDoc[] pathSegments = StringUtil.split(path, "/"); //$NON-NLS-1$
756
if (pathSegments.length != 2)
757             // path does not have correct format. Return empty results.
758
return results;
759
760         // save to cast.
761
AbstractIntroPage targetPage = (AbstractIntroPage) model.findChild(
762             pathSegments[0], ABSTRACT_PAGE);
763
764         if (targetPage != null) {
765             results[0] = targetPage;
766             Element targetElement = targetPage.findDomChild(pathSegments[1]);
767             if (targetElement != null)
768                 results[1] = targetElement;
769         }
770         return results;
771     }
772
773
774     /**
775      * @return Returns the content.
776      */

777     public String JavaDoc getContent() {
778         return content;
779     }
780
781
782
783     /**
784      * Deep copy since class has mutable objects.
785      */

786     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
787         AbstractIntroPage clone = (AbstractIntroPage) super.clone();
788         if (title != null) {
789             IntroPageTitle clonedTitle = (IntroPageTitle) title.clone();
790             clonedTitle.setParent(clone);
791             clone.title = clonedTitle;
792         }
793         // styles are safe for a shallow copy.
794
if (styles != null)
795             clone.styles = (Vector JavaDoc) styles.clone();
796         if (altStyles != null)
797             clone.altStyles = (Hashtable JavaDoc) altStyles.clone();
798         return clone;
799     }
800
801     /**
802      * Used when cloning pages to assign a unique id. Cache original id before
803      * setting.
804      *
805      * @param id
806      */

807     public void setId(String JavaDoc id) {
808         this.originalId = this.id;
809         this.id = id;
810     }
811
812     /*
813      * Creates an IFrame and injects it as the only child of the specified path.
814      */

815     public boolean injectIFrame(String JavaDoc url, String JavaDoc embedTarget) {
816         // embed url as IFrame in target div. We need to find target div in
817
// this cloned page not in the original page.
818
IntroGroup divToReplace = (IntroGroup) findTarget(embedTarget);
819         if (divToReplace == null) {
820             // we failed to find embed div, log and exit.
821
Log.warning("Failed to find embedTarget: " + embedTarget //$NON-NLS-1$
822
+ " in page " + getId()); //$NON-NLS-1$
823
return false;
824         }
825
826         this.iframe = new IntroInjectedIFrame(getElement(), getBundle());
827         this.iframe.setParent(divToReplace);
828         this.iframe.setIFrameURL(url);
829         divToReplace.clearChildren();
830         divToReplace.addChild(iframe);
831         return true;
832     }
833
834     /**
835      * Return true if this page is a cloned page that has an IFrame.
836      *
837      * @return
838      */

839     public boolean isIFramePage() {
840         return (iframe != null) ? true : false;
841     }
842
843
844     public String JavaDoc getUnmangledId() {
845         if (isIFramePage())
846             return originalId;
847         return id;
848     }
849
850
851     /**
852      * Set the url of the embedded IFrame, if this page is an IFrame page.
853      *
854      * @param url
855      */

856     public void setIFrameURL(String JavaDoc url) {
857         if (!isIFramePage())
858             return;
859         this.iframe.setIFrameURL(url);
860     }
861
862     /**
863      * Return the url of the embedded IFrame, if this page is an IFrame page.
864      *
865      * @param url
866      */

867     public String JavaDoc getIFrameURL() {
868         if (!isIFramePage())
869             return null;
870         return this.iframe.getIFrameURL();
871     }
872
873     /**
874      * Returns the raw or unprocessed base location.
875      */

876     public String JavaDoc getInitialBase() {
877         return initialBase;
878     }
879     
880     /**
881      * Return the url of the embedded IFrame, if this page is an IFrame page.
882      *
883      * @param url
884      */

885     public boolean injectSharedStyle() {
886         return this.sharedStyle.equals("true") ? true : false; //$NON-NLS-1$
887
}
888
889 }
890
Popular Tags