Source Code Cross Referenced for AbstractIntroPage.java in  » IDE-Eclipse » ui » org » eclipse » ui » internal » intro » impl » model » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui » org.eclipse.ui.internal.intro.impl.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2004, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.internal.intro.impl.model;
011:
012:        import java.util.Hashtable;
013:        import java.util.Vector;
014:
015:        import org.eclipse.core.runtime.IPath;
016:        import org.eclipse.core.runtime.Path;
017:        import org.eclipse.core.runtime.Platform;
018:        import org.eclipse.help.internal.UAElement;
019:        import org.eclipse.help.internal.UAElementFactory;
020:        import org.eclipse.help.internal.dynamic.DocumentProcessor;
021:        import org.eclipse.help.internal.dynamic.FilterHandler;
022:        import org.eclipse.help.internal.dynamic.ProcessorHandler;
023:        import org.eclipse.ui.internal.intro.impl.IIntroConstants;
024:        import org.eclipse.ui.internal.intro.impl.model.loader.ExtensionPointManager;
025:        import org.eclipse.ui.internal.intro.impl.model.loader.IntroContentParser;
026:        import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
027:        import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
028:        import org.eclipse.ui.internal.intro.impl.model.util.ModelUtil;
029:        import org.eclipse.ui.internal.intro.impl.util.IntroEvaluationContext;
030:        import org.eclipse.ui.internal.intro.impl.util.Log;
031:        import org.eclipse.ui.internal.intro.impl.util.StringUtil;
032:        import org.osgi.framework.Bundle;
033:        import org.w3c.dom.Document;
034:        import org.w3c.dom.Element;
035:        import org.w3c.dom.Node;
036:        import org.w3c.dom.NodeList;
037:
038:        /**
039:         * Base class for all Intro pages, inlcuding HomePage. Adds page specific
040:         * support:
041:         * <ul>
042:         * <li>support for page styles, and style inheritance</li>
043:         * <li>support for XHTML via a DOM instance var. Resolving the page is also
044:         * handled here.</li>
045:         * <li>a pge has the concept of being an IFramePage. This is indicated by the
046:         * isIFrame flag. A page is an IFramePage when it is not defined in any content
047:         * file, but instead is actually created at runtime. This is done to display a
048:         * Help System topic embedded in any given div. The current page is cloned, its
049:         * id is mangled with "_embedDivId", the content of the div pointed to by
050:         * embedDivId is replaced with an IFrame that loads the Help System topic.</li>
051:         * </ul>
052:         */
053:        public abstract class AbstractIntroPage extends AbstractIntroContainer {
054:
055:            protected static final String TAG_PAGE = "page"; //$NON-NLS-1$
056:            private static final String ATT_STYLE = "style"; //$NON-NLS-1$
057:            private static final String ATT_ALT_STYLE = "alt-style"; //$NON-NLS-1$
058:            private static final String ATT_CONTENT = "content"; //$NON-NLS-1$
059:            private static final String ATT_SHARED_STYLE = "shared-style"; //$NON-NLS-1$
060:            private static final String INVALID_CONTENT = "invalidPage/invalidPage.xhtml"; //$NON-NLS-1$
061:            private static final String INVALID_CONTENT_BASE = "invalidPage"; //$NON-NLS-1$
062:
063:            private String style;
064:            private String altStyle;
065:            private String sharedStyle;
066:            private IntroPageTitle title;
067:            private String content;
068:
069:            // if iframe is not null, this indicates that this page was cloned at
070:            // runtime from another page whose id was "originalId".
071:            private IntroInjectedIFrame iframe;
072:
073:            // id of page from which this page was cloned.
074:            private String originalId;
075:
076:            // DOM representing XHTML content. DOM is only cached in the case of XHTML
077:            // content.
078:            private Document dom;
079:
080:            private DocumentProcessor domProcessor;
081:
082:            // set when the content file is loaded (ie: loadChildren is called)
083:            private boolean isXHTMLPage;
084:
085:            // Model base attribute is stored in parent class. This base attribute here
086:            // is to cache the initial location of the content file. When content
087:            // attribute is defined, the base in the model becomes relative to
088:            // new xml file. However, in the case of XHTML content, and when
089:            // presentation is UI forms, we need to reuse initial content file location.
090:            private String initialBase;
091:
092:            /**
093:             * The vectors to hold all inhertied styles and alt styles from included
094:             * elements. They are lazily created when children are resolved (ie:
095:             * includes are resolved) OR when extensions are resolved and styles need to
096:             * be added to the target page.
097:             * <p>
098:             * Style Rules:
099:             * <ul>
100:             * <li>For includes, merge-style controls wether or not the enclosing page
101:             * inherits the styles of the target.
102:             * <li>If a page is including a shared div, merging target styles into this
103:             * page is ignored. Shared divs do not have styles.</li>
104:             * <li>For extensions, if the style or alt-style is not defined, that means
105:             * that no style inheritence is needed, and the style of the target page are
106:             * not updated.
107:             * <li>If an extension is extending a shared div, merging the styles of
108:             * this extension into the target is ignored. Shared divs do not have
109:             * styles.</li>
110:             * <li>Shared hashtable has alt-styles as keys and bundles as values.</li>
111:             * </ul>
112:             */
113:            private Vector styles;
114:            private Hashtable altStyles;
115:
116:            /**
117:             * Parent class for all pages. Make sure to set the bundle to where the
118:             * pages are loaded from. This means that the bundle for root may be
119:             * different from the bundle for all the other pages. Only pages do this
120:             * logic and so other model objects might have the wrong bundle cached if
121:             * the resource was loaded from an nl directory.
122:             * 
123:             * @param element
124:             */
125:            AbstractIntroPage(Element element, Bundle bundle, String base) {
126:                super (element, bundle, base);
127:                this .initialBase = base;
128:                content = getAttribute(element, ATT_CONTENT);
129:                if (content == null) {
130:                    //Delaying init until we have the model
131:                    // so that we can resolve theme
132:                    //init(element, bundle, base);
133:                } else {
134:                    // Content is not null. Resolve it. Other page attributes (style,
135:                    // alt-style...) will be loaded when xml content file is loaded
136:                    // since we need to pick them up from external xml content file. In
137:                    // the case where this external content file is XHTML and we have
138:                    // HTML presentation, page attributes are simply not loaded. In the
139:                    // case where we have XHTML in a UI forms presentation, we will need
140:                    // to load initial page attributes.
141:                    // BASE: since content is being loaded from another xml file, point
142:                    // the base of this page to be relative to the new xml file
143:                    // location.
144:                    IPath subBase = ModelUtil.getParentFolderPath(content);
145:                    this .base = new Path(base).append(subBase).toString();
146:                    content = BundleUtil.getResolvedResourceLocation(base,
147:                            content, bundle);
148:                }
149:                // load shared-style attribure. This is needed in the XML and in the
150:                // XHTML cases. Default is to include shared style.
151:                this .sharedStyle = getAttribute(element, ATT_SHARED_STYLE);
152:                if (sharedStyle == null)
153:                    sharedStyle = "true"; //$NON-NLS-1$
154:
155:            }
156:
157:            public void setParent(AbstractIntroElement parent) {
158:                super .setParent(parent);
159:                if (content == null)
160:                    init(element, getBundle(), initialBase);
161:            }
162:
163:            /**
164:             * Returns unresolved content value as found in the source file.
165:             * the source file.
166:             * @return the unresolved content value
167:             */
168:
169:            public String getRawContent() {
170:                return getAttribute(element, ATT_CONTENT);
171:            }
172:
173:            /**
174:             * Initialize styles. Take first style in style attribute and make it the
175:             * page style. Then put other styles in styles vectors. Make sure to resolve
176:             * each style.
177:             * 
178:             * @param element
179:             * @param bundle
180:             */
181:            private void init(Element element, Bundle bundle, String base) {
182:                String[] styleValues = getAttributeList(element, ATT_STYLE);
183:                if (styleValues != null && styleValues.length > 0) {
184:                    style = styleValues[0];
185:                    style = BundleUtil.getResolvedResourceLocation(base, style,
186:                            bundle);
187:                    for (int i = 1; i < styleValues.length; i++) {
188:                        String style = styleValues[i];
189:                        style = BundleUtil.getResolvedResourceLocation(base,
190:                                style, bundle);
191:                        addStyle(style);
192:                    }
193:                }
194:
195:                String[] altStyleValues = getAttributeList(element,
196:                        ATT_ALT_STYLE);
197:                if (altStyleValues != null && altStyleValues.length > 0) {
198:                    altStyle = altStyleValues[0];
199:                    altStyle = BundleUtil.getResolvedResourceLocation(base,
200:                            altStyle, bundle);
201:                    for (int i = 1; i < altStyleValues.length; i++) {
202:                        String style = altStyleValues[i];
203:                        style = BundleUtil.getResolvedResourceLocation(base,
204:                                style, bundle);
205:                        addAltStyle(style, bundle);
206:                    }
207:                }
208:            }
209:
210:            /**
211:             * The page's title. Each page can have one title.
212:             * 
213:             * @return Returns the title of this page.
214:             */
215:            public String getTitle() {
216:                // title is a child of the page, and so we have to load children first.
217:                // We also have to resolve children because someone might be including a
218:                // title. Update title instance after all includes and extensions have
219:                // been resolved.
220:                getChildren();
221:                if (title == null) {
222:                    // there should only be one title child per page. safe to cast.
223:                    IntroPageTitle[] titles = (IntroPageTitle[]) getChildrenOfType(AbstractIntroElement.PAGE_TITLE);
224:                    if (titles.length > 0)
225:                        title = titles[0];
226:                }
227:
228:                if (title == null)
229:                    // still null. no title.
230:                    return null;
231:                return title.getTitle();
232:            }
233:
234:            /**
235:             * @return Returns the style.
236:             */
237:            public String getStyle() {
238:                return style;
239:            }
240:
241:            /**
242:             * @return Returns the alt_style.
243:             */
244:            public String getAltStyle() {
245:                return altStyle;
246:            }
247:
248:            /**
249:             * Gets all the inherited styles of this page. Styles can be inherited from
250:             * includes or from configExtensions.
251:             * <p>
252:             * Note: this call needs to get all the children of this page, and so it
253:             * will resolve this page. might be expensive.
254:             * 
255:             * @return Returns all the inherited styles of this page. Returns an empty
256:             *         array if page is not expandable or does not have inherited
257:             *         styles.
258:             */
259:            public String[] getStyles() {
260:                // call get children first to resolve includes and populate styles
261:                // vector. Resolving children will initialize the style vectors.
262:                getChildren();
263:                if (styles == null)
264:                    // style vector is still null because page does not have styles.
265:                    return new String[0];
266:                String[] stylesArray = new String[styles.size()];
267:                styles.copyInto(stylesArray);
268:                return stylesArray;
269:            }
270:
271:            /**
272:             * Gets all the inherited alt-styles of this page (ie: styles for the SWT
273:             * presentation). A hashtable is returned that has inhertied alt-styles as
274:             * keys, and plugin descriptors as values. This is needed to be able to load
275:             * resources from the inherited target plugin. Note: this call needs to get
276:             * all the children of this page, and so its will resolve this page. might
277:             * be expensive.
278:             * 
279:             * @return Returns all the inherited styles of this page. Returns an empty
280:             *         hashtable if page is not expandable, does not have any includes,
281:             *         or has includes that do not merge styles.
282:             */
283:            public Hashtable getAltStyles() {
284:                // call get children first to resolve includes and populate hashtable.
285:                // Resolving children will initialize the style vectors.
286:                getChildren();
287:                return altStyles;
288:            }
289:
290:            /**
291:             * Adds the given style to the list. Style is not added if it already exists
292:             * in the list.
293:             * 
294:             * @param style
295:             */
296:            protected void addStyle(String style) {
297:                if (!initStyles(style))
298:                    return;
299:                if (styles.contains(style))
300:                    return;
301:                styles.add(style);
302:            }
303:
304:            public void insertStyle(String style, int location) {
305:                if (!initStyles(style))
306:                    return;
307:                if (styles.contains(style))
308:                    return;
309:                styles.add(location, style);
310:            }
311:
312:            /**
313:             * Adds the given style to the list.Style is not added if it already exists
314:             * in the list.
315:             * 
316:             * @param altStyle
317:             */
318:            protected void addAltStyle(String altStyle, Bundle bundle) {
319:                if (!initAltStyles(altStyle))
320:                    return;
321:                if (altStyles.containsKey(altStyle))
322:                    return;
323:                altStyles.put(altStyle, bundle);
324:            }
325:
326:            /**
327:             * Util method to add given styles to the list.
328:             * 
329:             */
330:            protected void addStyles(String[] styles) {
331:                if (styles == null)
332:                    return;
333:                for (int i = 0; i < styles.length; i++)
334:                    addStyle(styles[i]);
335:            }
336:
337:            /**
338:             * Util method to add map of altstyles to list.
339:             */
340:            protected void addAltStyles(Hashtable altStyles) {
341:                if (altStyles == null)
342:                    return;
343:                if (this .altStyles == null)
344:                    // delay creation until needed.
345:                    this .altStyles = new Hashtable();
346:                this .altStyles.putAll(altStyles);
347:            }
348:
349:            private boolean initStyles(String style) {
350:                if (style == null)
351:                    return false;
352:                if (this .styles == null)
353:                    // delay creation until needed.
354:                    this .styles = new Vector();
355:                return true;
356:            }
357:
358:            private boolean initAltStyles(String style) {
359:                if (style == null)
360:                    return false;
361:                if (this .altStyles == null)
362:                    // delay creation until needed.
363:                    this .altStyles = new Hashtable();
364:                return true;
365:            }
366:
367:            /*
368:             * (non-Javadoc)
369:             * 
370:             * @see org.eclipse.ui.internal.intro.impl.model.IntroElement#getType()
371:             */
372:            public int getType() {
373:                return AbstractIntroElement.ABSTRACT_PAGE;
374:            }
375:
376:            /*
377:             * Override parent behavior to lazily initialize styles vectors. This will
378:             * only be called once, if resolved == false. In the case of DOM model,
379:             * resolve this page's full DOM.
380:             * 
381:             * @see org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer#resolveChildren()
382:             */
383:            protected void resolveChildren() {
384:                // flag would be set
385:                if (isXHTMLPage)
386:                    resolvePage();
387:                else
388:                    super .resolveChildren();
389:            }
390:
391:            /**
392:             * Override parent behavior to add support for HEAD & Title element in pages
393:             * only, and not in divs.
394:             * 
395:             * @see org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer#getModelChild(org.eclipse.core.runtime.IConfigurationElement)
396:             */
397:            protected AbstractIntroElement getModelChild(Element childElement,
398:                    Bundle bundle, String base) {
399:                AbstractIntroElement child = null;
400:                if (childElement.getNodeName().equalsIgnoreCase(
401:                        IntroHead.TAG_HEAD)) {
402:                    child = new IntroHead(childElement, bundle, base);
403:                } else if (childElement.getNodeName().equalsIgnoreCase(
404:                        IntroPageTitle.TAG_TITLE)) {
405:                    // if we have a title, only add it as a child if we did not load one
406:                    // before. A page can only have one title.
407:                    if (title == null) {
408:                        child = new IntroPageTitle(childElement, bundle);
409:                    }
410:                }
411:                if (child != null)
412:                    return child;
413:                return super .getModelChild(childElement, bundle, base);
414:            }
415:
416:            /**
417:             * Returns all head contributions in this page. There can be more than one
418:             * head contribution in the page;
419:             * 
420:             * @return
421:             */
422:            public IntroHead[] getHTMLHeads() {
423:                return (IntroHead[]) getChildrenOfType(AbstractIntroElement.HEAD);
424:            }
425:
426:            /**
427:             * load the children of this container. Override parent behavior because we
428:             * want to support loading content from other xml files. The design is that
429:             * only the id and content from the existing page are honored. All other
430:             * attributes are what they are defined in the external paget. For XHTML
431:             * content, all info is in the xhtml page. If we fail to load the page,
432:             * display the Invalid Page page.
433:             */
434:            protected void loadChildren() {
435:                if (content == null) {
436:                    // no content. do regular loading.
437:                    super .loadChildren();
438:                    return;
439:                }
440:
441:                // content attribute is defined. It either points to an XHTML file, or
442:                // an introContent.xml file. Process each case. Assume it is an
443:                // introContent file.
444:                // INTRO: XHTML file is loaded needlessly when we have XHTML content and
445:                // SWT presentation.
446:                IntroContentParser parser = new IntroContentParser(content);
447:                Document dom = parser.getDocument();
448:                if (dom == null) {
449:                    // bad xml. This could be bad XHTML or bad intro XML. Parser would
450:                    // have logged fact. Load dom for invalid page, and make sure to
451:                    // force an extract on parent folder to enabling jarring.
452:                    Bundle introBundle = Platform
453:                            .getBundle(IIntroConstants.PLUGIN_ID);
454:                    ModelUtil.ensureFileURLsExist(introBundle, INVALID_CONTENT);
455:
456:                    String invalidContentFilePath = BundleUtil
457:                            .getResolvedResourceLocation(INVALID_CONTENT,
458:                                    introBundle);
459:                    parser = new IntroContentParser(invalidContentFilePath);
460:                    dom = parser.getDocument();
461:                    // make sure to override all attributes to resolve the Invalid
462:                    // Page page correctly.
463:                    content = invalidContentFilePath;
464:                    this .base = INVALID_CONTENT_BASE;
465:                    setBundle(introBundle);
466:                }
467:
468:                // parse content depending on type. Make sure to set the loaded flag
469:                // accordingly, otherwise content file will always be parsed.
470:                if (parser.hasXHTMLContent()) {
471:                    loadXHTMLContent(dom);
472:                    // make sure to use correct base.
473:                    init(element, getBundle(), initialBase);
474:                    super .loadChildren();
475:                } else
476:                    // load the first page with correct id, from content xml file.
477:                    loadXMLContent(dom);
478:            }
479:
480:            /**
481:             * Load the xml content from the introContent.xml file pointed to by the
482:             * content attribute, and loaded into the passed DOM. Load the first page
483:             * with correct id from this content file.
484:             * 
485:             * @param dom
486:             */
487:            private void loadXMLContent(Document dom) {
488:                Element[] pages = ModelUtil.getElementsByTagName(dom,
489:                        AbstractIntroPage.TAG_PAGE);
490:                if (pages.length == 0) {
491:                    Log.warning("Content file has no pages."); //$NON-NLS-1$
492:                    return;
493:                }
494:                // point the element of this page to the new element. Pick first page
495:                // with matching id. Make sure to disable loading of children of current
496:                // element if a matching page in the external content file is not found.
497:                boolean foundMatchingPage = false;
498:                for (int i = 0; i < pages.length; i++) {
499:                    Element pageElement = pages[i];
500:                    if (pageElement.getAttribute(AbstractIntroIdElement.ATT_ID)
501:                            .equals(getId())) {
502:                        this .element = pageElement;
503:                        // call init on the new element. the filtering and the style-id
504:                        // are loaded by the parent class.
505:                        init(pageElement, getBundle(), base);
506:                        // INTRO: revisit. Special processing here should be made more
507:                        // general. we know id is correct.
508:                        style_id = getAttribute(element,
509:                                AbstractBaseIntroElement.ATT_STYLE_ID);
510:                        filteredFrom = getAttribute(element,
511:                                AbstractBaseIntroElement.ATT_FILTERED_FROM);
512:                        sharedStyle = getAttribute(element, ATT_SHARED_STYLE);
513:                        if (sharedStyle == null)
514:                            sharedStyle = "true"; //$NON-NLS-1$
515:                        foundMatchingPage = true;
516:                    }
517:                }
518:                if (foundMatchingPage)
519:                    // now do children loading as usual.
520:                    super .loadChildren();
521:                else {
522:                    // page was not found in content file. Perform load actions, and log
523:                    // fact. init the children vector.
524:                    children = new Vector();
525:                    loaded = true;
526:                    // free DOM model for memory performance.
527:                    element = null;
528:                    Log
529:                            .warning("Content file does not have page with id= " + getId()); //$NON-NLS-1$
530:                }
531:            }
532:
533:            private void loadXHTMLContent(Document dom) {
534:                // no need to load any children since we use XSLT to print XHTML
535:                // content. Simply cache DOM.
536:                this .dom = dom;
537:                this .isXHTMLPage = true;
538:                // init empty children vector.
539:                children = new Vector();
540:                loaded = true;
541:            }
542:
543:            /**
544:             * Returns the DOM representing an external XHTML file. May return null if
545:             * extension content is 3.0 format. The page is resolved before returning,
546:             * meaning includes are resolved, and the base of the page is defined.
547:             * 
548:             * @return
549:             */
550:            public Document getResolvedDocument() {
551:                // we need to force a getChildren to resolve the page.
552:                getChildren();
553:                return dom;
554:            }
555:
556:            /**
557:             * Returns the DOM representing an external XHTML file. May return null if
558:             * extension content is 3.0 format. The page is NOT resolved before
559:             * returning. It is retruned as given by the dom parser.
560:             * 
561:             * @return
562:             */
563:            public Document getDocument() {
564:                // we only need to load children here.
565:                if (!loaded)
566:                    loadChildren();
567:                return dom;
568:            }
569:
570:            /**
571:             * Returns whether or not we have an XHTML page as the content for this
572:             * page. The XHTML page is defined through the content attribute. This
573:             * method forces the content file to be parsed and loaded in memory.
574:             * 
575:             * @return
576:             */
577:            public boolean isXHTMLPage() {
578:                // we need to force loading of children since we need to determine
579:                // content type. Load the children without resolving (for performance),
580:                // this will set the XHTML flag at the page level.
581:                if (!loaded)
582:                    loadChildren();
583:                return isXHTMLPage;
584:            }
585:
586:            /**
587:             * Deep searches all children in this container's DOM for the first child
588:             * with the given id. The element retrieved must have the passed local name.
589:             * Note that in an XHTML file (aka DOM) elements should have a unique id
590:             * within the scope of a document. We use local name because this allows for
591:             * finding intro anchors, includes and dynamic content element regardless of
592:             * whether or not an xmlns was used in the xml. note: could not have used
593:             * inheritance from parent container because return type for parent is intro
594:             * legacy model.
595:             * 
596:             */
597:            public Element findDomChild(String id, String localElementName) {
598:                if (!loaded)
599:                    loadChildren();
600:                // using getElementById is tricky and we need to have intro XHTML
601:                // modules to properly use this method.
602:                return ModelUtil.getElementById(dom, id, localElementName);
603:            }
604:
605:            /**
606:             * Search for any element with the given id.
607:             * 
608:             * @param id
609:             * @return
610:             */
611:            public Element findDomChild(String id) {
612:                return findDomChild(id, "*"); //$NON-NLS-1$
613:
614:            }
615:
616:            /**
617:             * Resolves the full page. It is called just before the page needs to be
618:             * displayed.
619:             * <li>adds a BASE child to the DOM HEAD element, if one is not defined.
620:             * All intro documents must have a base defined to resolve all urls.</li>
621:             * <li>resolves all includes in the page. This means importing target DOM.
622:             * </li>
623:             * <li>resolves all XHTML attributes for resources, eg: src, href
624:             * attributes.</li>
625:             */
626:            protected void resolvePage() {
627:                // insert base meta-tag,
628:                ModelUtil.insertBase(dom, ModelUtil
629:                        .getParentFolderOSString(content));
630:
631:                // resolve all relative resources relative to content file. Do it before
632:                // inserting shared style to enable comparing fully qualified styles.
633:                ModelUtil.updateResourceAttributes(dom.getDocumentElement(),
634:                        this );
635:
636:                // now add shared style.
637:                IntroModelRoot modelRoot = (IntroModelRoot) getParent();
638:                IntroPartPresentation presentation = modelRoot
639:                        .getPresentation();
640:                String[] styles = presentation != null ? presentation
641:                        .getImplementationStyles() : null;
642:                if (styles != null && injectSharedStyle()) {
643:                    for (int i = 0; i < styles.length; i++)
644:                        ModelUtil.insertStyle(dom, styles[i]);
645:                }
646:
647:                // filter the content
648:                if (domProcessor == null) {
649:                    domProcessor = new DocumentProcessor(
650:                            new ProcessorHandler[] { new FilterHandler(
651:                                    IntroEvaluationContext.getContext()) });
652:                }
653:                UAElement element = UAElementFactory.newElement(dom
654:                        .getDocumentElement());
655:                domProcessor.process(element, null);
656:
657:                // and resolve includes.
658:                resolveIncludes();
659:
660:                // now remove all anchors from this page.
661:                ModelUtil.removeAllElements(dom, IntroAnchor.TAG_ANCHOR);
662:                resolved = true;
663:            }
664:
665:            /**
666:             * Resolves all includes in this page. This means importing the DOM of the
667:             * target path into the current page DOM, and resolving XHTML attributes for
668:             * resources.
669:             */
670:            protected void resolveIncludes() {
671:                // get all includes elements in DOM.
672:                NodeList includes = dom.getElementsByTagNameNS("*", //$NON-NLS-1$
673:                        IntroInclude.TAG_INCLUDE);
674:                // get the array version of the include nodelist to work around
675:                // replaceChild() DOM api design.
676:                Node[] nodes = ModelUtil.getArray(includes);
677:                for (int i = 0; i < nodes.length; i++) {
678:                    Element includeElement = (Element) nodes[i];
679:                    IntroInclude include = new IntroInclude(includeElement,
680:                            getBundle());
681:                    // result[0] is target parent page, result[1] is target element.
682:                    Object[] results = findDOMIncludeTarget(include);
683:                    Element targetElement = (Element) results[1];
684:                    if (targetElement == null) {
685:                        String message = "Could not resolve following include:  " //$NON-NLS-1$
686:                                + ModelLoaderUtil.getLogString(getBundle(),
687:                                        includeElement, IntroInclude.ATT_PATH);
688:                        Log.warning(message);
689:                        return;
690:                    }
691:
692:                    // insert the target element instead of the include.
693:                    Node targetNode = dom.importNode(targetElement, true);
694:                    // update the src attribute of this node, if defined by w3
695:                    // specs.
696:                    AbstractIntroPage page = ((AbstractIntroPage) results[0]);
697:                    ModelUtil.updateResourceAttributes((Element) targetNode,
698:                            page);
699:                    // use of replace API to remove include element is tricky. It
700:                    // confuses the NodeList used in the loop above. Removing an include
701:                    // removes it from the NodeList. Used cloned Array instead.
702:                    includeElement.getParentNode().replaceChild(targetNode,
703:                            includeElement);
704:                }
705:            }
706:
707:            /**
708:             * Find the target Element pointed to by the path in the include. It is
709:             * assumed that configId always points to an external config, and not the
710:             * same config of the inlcude.
711:             * 
712:             * @param include
713:             * @param path
714:             * @return
715:             */
716:            private Object[] findDOMIncludeTarget(IntroInclude include) {
717:                String path = include.getPath();
718:                IntroModelRoot targetModelRoot = (IntroModelRoot) getParentPage()
719:                        .getParent();
720:                String targetConfigID = include.getConfigId();
721:                if (targetConfigID != null)
722:                    targetModelRoot = ExtensionPointManager.getInst().getModel(
723:                            targetConfigID);
724:                if (targetModelRoot == null)
725:                    // if the target config was not found, skip this include.
726:                    return null;
727:                return findDOMTarget(targetModelRoot, path);
728:
729:            }
730:
731:            /**
732:             * Finds the child element that corresponds to the given path in the passed
733:             * model.
734:             * 
735:             * @param model
736:             *            model containing target path.
737:             * @param path
738:             *            the path to look for
739:             * @param results
740:             *            two object array that will return the target intro page as the
741:             *            first result, and the actual target DOM Element as the second
742:             *            result. It is gauranteed to not be null. Content may be null.
743:             * @return target DOM element
744:             */
745:            public Object[] findDOMTarget(IntroModelRoot model, String path) {
746:                Object[] results = new Object[2];
747:                // path must be pageId/anchorID in the case of of XHTML pages.
748:                // pages.
749:                String[] pathSegments = StringUtil.split(path, "/"); //$NON-NLS-1$
750:                if (pathSegments.length != 2)
751:                    // path does not have correct format. Return empty results.
752:                    return results;
753:
754:                // save to cast.
755:                AbstractIntroPage targetPage = (AbstractIntroPage) model
756:                        .findChild(pathSegments[0], ABSTRACT_PAGE);
757:
758:                if (targetPage != null) {
759:                    results[0] = targetPage;
760:                    Element targetElement = targetPage
761:                            .findDomChild(pathSegments[1]);
762:                    if (targetElement != null)
763:                        results[1] = targetElement;
764:                }
765:                return results;
766:            }
767:
768:            /**
769:             * @return Returns the content.
770:             */
771:            public String getContent() {
772:                return content;
773:            }
774:
775:            /**
776:             * Deep copy since class has mutable objects.
777:             */
778:            public Object clone() throws CloneNotSupportedException {
779:                AbstractIntroPage clone = (AbstractIntroPage) super .clone();
780:                if (title != null) {
781:                    IntroPageTitle clonedTitle = (IntroPageTitle) title.clone();
782:                    clonedTitle.setParent(clone);
783:                    clone.title = clonedTitle;
784:                }
785:                // styles are safe for a shallow copy.
786:                if (styles != null)
787:                    clone.styles = (Vector) styles.clone();
788:                if (altStyles != null)
789:                    clone.altStyles = (Hashtable) altStyles.clone();
790:                return clone;
791:            }
792:
793:            /**
794:             * Used when cloning pages to assign a unique id. Cache original id before
795:             * setting.
796:             * 
797:             * @param id
798:             */
799:            public void setId(String id) {
800:                this .originalId = this .id;
801:                this .id = id;
802:            }
803:
804:            /*
805:             * Creates an IFrame and injects it as the only child of the specified path.
806:             */
807:            public boolean injectIFrame(String url, String embedTarget) {
808:                // embed url as IFrame in target div. We need to find target div in
809:                // this cloned page not in the original page.
810:                IntroGroup divToReplace = (IntroGroup) findTarget(embedTarget);
811:                if (divToReplace == null) {
812:                    // we failed to find embed div, log and exit.
813:                    Log.warning("Failed to find embedTarget: " + embedTarget //$NON-NLS-1$
814:                            + " in page " + getId()); //$NON-NLS-1$
815:                    return false;
816:                }
817:
818:                this .iframe = new IntroInjectedIFrame(getElement(), getBundle());
819:                this .iframe.setParent(divToReplace);
820:                this .iframe.setIFrameURL(url);
821:                divToReplace.clearChildren();
822:                divToReplace.addChild(iframe);
823:                return true;
824:            }
825:
826:            /**
827:             * Return true if this page is a cloned page that has an IFrame.
828:             * 
829:             * @return
830:             */
831:            public boolean isIFramePage() {
832:                return (iframe != null) ? true : false;
833:            }
834:
835:            public String getUnmangledId() {
836:                if (isIFramePage())
837:                    return originalId;
838:                return id;
839:            }
840:
841:            /**
842:             * Set the url of the embedded IFrame, if this page is an IFrame page.
843:             * 
844:             * @param url
845:             */
846:            public void setIFrameURL(String url) {
847:                if (!isIFramePage())
848:                    return;
849:                this .iframe.setIFrameURL(url);
850:            }
851:
852:            /**
853:             * Return the url of the embedded IFrame, if this page is an IFrame page.
854:             * 
855:             * @param url
856:             */
857:            public String getIFrameURL() {
858:                if (!isIFramePage())
859:                    return null;
860:                return this .iframe.getIFrameURL();
861:            }
862:
863:            /**
864:             * Returns the raw or unprocessed base location.
865:             */
866:            public String getInitialBase() {
867:                return initialBase;
868:            }
869:
870:            /**
871:             * Return the url of the embedded IFrame, if this page is an IFrame page.
872:             * 
873:             * @param url
874:             */
875:            public boolean injectSharedStyle() {
876:                return this .sharedStyle.equals("true") ? true : false; //$NON-NLS-1$
877:            }
878:
879:        }
www.___ja_v___a___2s___.c_om | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.