Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2004, 2007 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation /
 
 package org.eclipse.ui.internal.intro.impl.model;
 
 
 import  org.eclipse.core.runtime.IPath;
 import  org.eclipse.core.runtime.Path;
Base class for all Intro pages, inlcuding HomePage. Adds page specific support:
  • support for page styles, and style inheritance
  • support for XHTML via a DOM instance var. Resolving the page is also handled here.
  • a pge has the concept of being an IFramePage. This is indicated by the isIFrame flag. A page is an IFramePage when it is not defined in any content file, but instead is actually created at runtime. This is done to display a Help System topic embedded in any given div. The current page is cloned, its id is mangled with "_embedDivId", the content of the div pointed to by embedDivId is replaced with an IFrame that loads the Help System topic.
 
 public abstract class AbstractIntroPage extends AbstractIntroContainer {
 
     protected static final String TAG_PAGE = "page"//$NON-NLS-1$
     private static final String ATT_STYLE = "style"//$NON-NLS-1$
     private static final String ATT_ALT_STYLE = "alt-style"//$NON-NLS-1$
     private static final String ATT_CONTENT = "content"//$NON-NLS-1$
     private static final String ATT_SHARED_STYLE = "shared-style"//$NON-NLS-1$
     private static final String INVALID_CONTENT = "invalidPage/invalidPage.xhtml"//$NON-NLS-1$
     private static final String INVALID_CONTENT_BASE = "invalidPage"//$NON-NLS-1$
 	protected static final String ATT_URL = "url"//$NON-NLS-1$
 
     private String style;
     private String altStyle;
     private String sharedStyle;
     private IntroPageTitle title;
     private String content;
     private String url;
 
     // if iframe is not null, this indicates that this page was cloned at
     // runtime from another page whose id was "originalId".
     private IntroInjectedIFrame iframe;
 
     // id of page from which this page was cloned.
     private String originalId;
 
     // DOM representing XHTML content. DOM is only cached in the case of XHTML
     // content.
     private Document dom;
     
     private DocumentProcessor domProcessor;
 
     // set when the content file is loaded (ie: loadChildren is called)
     private boolean isXHTMLPage;
 
     // Model base attribute is stored in parent class. This base attribute here
     // is to cache the initial location of the content file. When content
     // attribute is defined, the base in the model becomes relative to
     // new xml file. However, in the case of XHTML content, and when
     // presentation is UI forms, we need to reuse initial content file location.
     private String initialBase;

    
The vectors to hold all inhertied styles and alt styles from included elements. They are lazily created when children are resolved (ie: includes are resolved) OR when extensions are resolved and styles need to be added to the target page.

Style Rules:

  • For includes, merge-style controls wether or not the enclosing page inherits the styles of the target.
  • If a page is including a shared div, merging target styles into this page is ignored. Shared divs do not have styles.
  • For extensions, if the style or alt-style is not defined, that means that no style inheritence is needed, and the style of the target page are not updated.
  • If an extension is extending a shared div, merging the styles of this extension into the target is ignored. Shared divs do not have styles.
  • Shared hashtable has alt-styles as keys and bundles as values.
    private Vector styles;
    private Hashtable altStyles;
	private boolean isDynamic = false;
	protected boolean isStandbyPage;

    
Parent class for all pages. Make sure to set the bundle to where the pages are loaded from. This means that the bundle for root may be different from the bundle for all the other pages. Only pages do this logic and so other model objects might have the wrong bundle cached if the resource was loaded from an nl directory.

Parameters:
element
    AbstractIntroPage(Element elementBundle bundleString base) {
        super(elementbundlebase);
        this. = base;
         = getAttribute(element);
        if ( == null) {
        	//Delaying init until we have the model
        	// so that we can resolve theme
            //init(element, bundle, base);
        }
        else {
            // Content is not null. Resolve it. Other page attributes (style,
            // alt-style...) will be loaded when xml content file is loaded
            // since we need to pick them up from external xml content file. In
            // the case where this external content file is XHTML and we have
            // HTML presentation, page attributes are simply not loaded. In the
            // case where we have XHTML in a UI forms presentation, we will need
            // to load initial page attributes.
            // BASE: since content is being loaded from another xml file, point
            // the base of this page to be relative to the new xml file
            // location.
            IPath subBase = ModelUtil.getParentFolderPath();
            this. = new Path(base).append(subBase).toString();
             = BundleUtil.getResolvedResourceLocation(base,
                bundle);
        }
        // load shared-style attribure. This is needed in the XML and in the
        // XHTML cases. Default is to include shared style.
        this. = getAttribute(element);
        if ( == null)
             = "true"//$NON-NLS-1$
         = getAttribute(element);
        if ( == null)
            // if we do not have a URL attribute, then we have dynamic content.
             = true;
        else
            // check the url/standby-url attributes and update accordingly.
             = ModelUtil.resolveURL(basebundle);
    }
    
    public void setParent(AbstractIntroElement parent) {
    	super.setParent(parent);
        if ( == null)
            init(getBundle(), );
    }
    
    
Returns unresolved content value as found in the source file. the source file.

Returns:
the unresolved content value
    
    public String getRawContent() {
    	return getAttribute();
    }

    
Initialize styles. Take first style in style attribute and make it the page style. Then put other styles in styles vectors. Make sure to resolve each style.

Parameters:
element
bundle
    private void init(Element elementBundle bundleString base) {
        String[] styleValues = getAttributeList(element);
        if (styleValues != null && styleValues.length > 0) {
             = styleValues[0];
             = BundleUtil.getResolvedResourceLocation(basebundle);
            for (int i = 1; i < styleValues.lengthi++) {
                String style = styleValues[i];
                style = BundleUtil.getResolvedResourceLocation(basestyle,
                    bundle);
                addStyle(style);
            }
        }
        String[] altStyleValues = getAttributeList(element);
        if (altStyleValues != null && altStyleValues.length > 0) {
             = altStyleValues[0];
             = BundleUtil.getResolvedResourceLocation(base,
                bundle);
            for (int i = 1; i < altStyleValues.lengthi++) {
                String style = altStyleValues[i];
                style = BundleUtil.getResolvedResourceLocation(basestyle,
                    bundle);
                addAltStyle(stylebundle);
            }
        }
    }




    
The page's title. Each page can have one title.

Returns:
Returns the title of this page.
    public String getTitle() {
        // title is a child of the page, and so we have to load children first.
        // We also have to resolve children because someone might be including a
        // title. Update title instance after all includes and extensions have
        // been resolved.
        getChildren();
        if ( == null) {
            // there should only be one title child per page. safe to cast.
            if (titles.length > 0)
                 = titles[0];
        }
        if ( == null)
            // still null. no title.
            return null;
        return .getTitle();
    }

    

Returns:
Returns the style.
    public String getStyle() {
        return ;
    }

    

Returns:
Returns the alt_style.
    public String getAltStyle() {
        return ;
    }

    
Gets all the inherited styles of this page. Styles can be inherited from includes or from configExtensions.

Note: this call needs to get all the children of this page, and so it will resolve this page. might be expensive.

Returns:
Returns all the inherited styles of this page. Returns an empty array if page is not expandable or does not have inherited styles.
    public String[] getStyles() {
        // call get children first to resolve includes and populate styles
        // vector. Resolving children will initialize the style vectors.
        getChildren();
        if ( == null)
            // style vector is still null because page does not have styles.
            return new String[0];
        String[] stylesArray = new String[.size()];
        .copyInto(stylesArray);
        return stylesArray;
    }

    
Gets all the inherited alt-styles of this page (ie: styles for the SWT presentation). A hashtable is returned that has inhertied alt-styles as keys, and plugin descriptors as values. This is needed to be able to load resources from the inherited target plugin. Note: this call needs to get all the children of this page, and so its will resolve this page. might be expensive.

Returns:
Returns all the inherited styles of this page. Returns an empty hashtable if page is not expandable, does not have any includes, or has includes that do not merge styles.
    public Hashtable getAltStyles() {
        // call get children first to resolve includes and populate hashtable.
        // Resolving children will initialize the style vectors.
        getChildren();
        return ;
    }

    
Adds the given style to the list. Style is not added if it already exists in the list.

Parameters:
style
    protected void addStyle(String style) {
        if (!initStyles(style))
            return;
        if (.contains(style))
            return;
        .add(style);
    }
    public void insertStyle(String styleint location) {
        if (!initStyles(style))
            return;
        if (.contains(style))
            return;
        .add(locationstyle);
    }



    
Adds the given style to the list.Style is not added if it already exists in the list.

Parameters:
altStyle
    protected void addAltStyle(String altStyleBundle bundle) {
        if (!initAltStyles(altStyle))
            return;
        if (.containsKey(altStyle))
            return;
        .put(altStylebundle);
    }


    
Util method to add given styles to the list.
    protected void addStyles(String[] styles) {
        if (styles == null)
            return;
        for (int i = 0; i < styles.lengthi++)
            addStyle(styles[i]);
    }

    
Util method to add map of altstyles to list.
    protected void addAltStyles(Hashtable altStyles) {
        if (altStyles == null)
            return;
        if (this. == null)
            // delay creation until needed.
            this. = new Hashtable();
        this..putAll(altStyles);
    }
    private boolean initStyles(String style) {
        if (style == null)
            return false;
        if (this. == null)
            // delay creation until needed.
            this. = new Vector();
        return true;
    }
    private boolean initAltStyles(String style) {
        if (style == null)
            return false;
        if (this. == null)
            // delay creation until needed.
            this. = new Hashtable();
        return true;
    }
    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.internal.intro.impl.model.IntroElement#getType()
     */
    public int getType() {
        return .;
    }
    /*
     * Override parent behavior to lazily initialize styles vectors. This will
     * only be called once, if resolved == false. In the case of DOM model,
     * resolve this page's full DOM.
     * 
     * @see org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer#resolveChildren()
     */
    protected void resolveChildren() {
        // flag would be set
        if ()
            resolvePage();
        else
            super.resolveChildren();
    }



    
Override parent behavior to add support for HEAD & Title element in pages only, and not in divs.

    protected AbstractIntroElement getModelChild(Element childElement,
            Bundle bundleString base) {
        AbstractIntroElement child = null;
        if (childElement.getNodeName().equalsIgnoreCase(.)) {
            child = new IntroHead(childElementbundlebase);
        } else if (childElement.getNodeName().equalsIgnoreCase(
            .)) {
            // if we have a title, only add it as a child if we did not load one
            // before. A page can only have one title.
            if ( == null) {
                child = new IntroPageTitle(childElementbundle);
            }
        }
        if (child != null)
            return child;
        return super.getModelChild(childElementbundlebase);
    }

    
Returns all head contributions in this page. There can be more than one head contribution in the page;

Returns:
    public IntroHead[] getHTMLHeads() {
    }


    
load the children of this container. Override parent behavior because we want to support loading content from other xml files. The design is that only the id and content from the existing page are honored. All other attributes are what they are defined in the external paget. For XHTML content, all info is in the xhtml page. If we fail to load the page, display the Invalid Page page.
    protected void loadChildren() {
        if ( == null) {
            // no content. do regular loading.
            super.loadChildren();
            return;
        }
        // content attribute is defined. It either points to an XHTML file, or
        // an introContent.xml file. Process each case. Assume it is an
        // introContent file.
        // INTRO: XHTML file is loaded needlessly when we have XHTML content and
        // SWT presentation.
        IntroContentParser parser = new IntroContentParser();
        Document dom = parser.getDocument();
        if (dom == null) {
            // bad xml. This could be bad XHTML or bad intro XML. Parser would
            // have logged fact. Load dom for invalid page, and make sure to
            // force an extract on parent folder to enabling jarring.
            Bundle introBundle = Platform.getBundle(.);
            ModelUtil.ensureFileURLsExist(introBundle);
            String invalidContentFilePath = BundleUtil
                .getResolvedResourceLocation(introBundle);
            parser = new IntroContentParser(invalidContentFilePath);
            dom = parser.getDocument();
            // make sure to override all attributes to resolve the Invalid
            // Page page correctly.
             = invalidContentFilePath;
            this. = ;
            setBundle(introBundle);
        }
        // parse content depending on type. Make sure to set the loaded flag
        // accordingly, otherwise content file will always be parsed.
        if (parser.hasXHTMLContent()) {
            loadXHTMLContent(dom);
            // make sure to use correct base.
            init(getBundle(), );
            super.loadChildren();
        } else
            // load the first page with correct id, from content xml file.
            loadXMLContent(dom);
    }

    
Load the xml content from the introContent.xml file pointed to by the content attribute, and loaded into the passed DOM. Load the first page with correct id from this content file.

Parameters:
dom
    private void loadXMLContent(Document dom) {
        Element[] pages = ModelUtil.getElementsByTagName(dom,
            .);
        if (pages.length == 0) {
            Log.warning("Content file has no pages."); //$NON-NLS-1$
            return;
        }
        // point the element of this page to the new element. Pick first page
        // with matching id. Make sure to disable loading of children of current
        // element if a matching page in the external content file is not found.
        boolean foundMatchingPage = false;
        for (int i = 0; i < pages.lengthi++) {
            Element pageElement = pages[i];
            if (pageElement.getAttribute(.).equals(
                getId())) {
                this. = pageElement;
                // call init on the new element. the filtering and the style-id
                // are loaded by the parent class.
                init(pageElementgetBundle(), );
                // INTRO: revisit. Special processing here should be made more
                // general. we know id is correct.
                 = getAttribute(,
                    .);
                 = getAttribute(,
                    .);
                 = getAttribute();
                if ( == null)
                     = "true"//$NON-NLS-1$
                foundMatchingPage = true;
            }
        }
        if (foundMatchingPage)
            // now do children loading as usual.
            super.loadChildren();
        else {
            // page was not found in content file. Perform load actions, and log
            // fact. init the children vector.
             = new Vector();
             = true;
            // free DOM model for memory performance.
             = null;
            Log.warning("Content file does not have page with id= " + getId()); //$NON-NLS-1$
        }
    }
    private void loadXHTMLContent(Document dom) {
        // no need to load any children since we use XSLT to print XHTML
        // content. Simply cache DOM.
        this. = dom;
        this. = true;
        // init empty children vector.
         = new Vector();
         = true;
    }

    
Returns the DOM representing an external XHTML file. May return null if extension content is 3.0 format. The page is resolved before returning, meaning includes are resolved, and the base of the page is defined.

Returns:
    public Document getResolvedDocument() {
        // we need to force a getChildren to resolve the page.
        getChildren();
        return ;
    }


    
Returns the DOM representing an external XHTML file. May return null if extension content is 3.0 format. The page is NOT resolved before returning. It is retruned as given by the dom parser.

Returns:
    public Document getDocument() {
        // we only need to load children here.
        if (!)
            loadChildren();
        return ;
    }


    
Returns whether or not we have an XHTML page as the content for this page. The XHTML page is defined through the content attribute. This method forces the content file to be parsed and loaded in memory.

Returns:
    public boolean isXHTMLPage() {
        // we need to force loading of children since we need to determine
        // content type. Load the children without resolving (for performance),
        // this will set the XHTML flag at the page level.
        if (!)
            loadChildren();
        return ;
    }


    
Deep searches all children in this container's DOM for the first child with the given id. The element retrieved must have the passed local name. Note that in an XHTML file (aka DOM) elements should have a unique id within the scope of a document. We use local name because this allows for finding intro anchors, includes and dynamic content element regardless of whether or not an xmlns was used in the xml. note: could not have used inheritance from parent container because return type for parent is intro legacy model.
    public Element findDomChild(String idString localElementName) {
        if (!)
            loadChildren();
        // using getElementById is tricky and we need to have intro XHTML
        // modules to properly use this method.
        return ModelUtil.getElementById(idlocalElementName);
    }

    
Search for any element with the given id.

Parameters:
id
Returns:
    public Element findDomChild(String id) {
        return findDomChild(id"*"); //$NON-NLS-1$
    }



    
Resolves the full page. It is called just before the page needs to be displayed.
  • adds a BASE child to the DOM HEAD element, if one is not defined. All intro documents must have a base defined to resolve all urls.
  • resolves all includes in the page. This means importing target DOM.
  • resolves all XHTML attributes for resources, eg: src, href attributes.
  •     protected void resolvePage() {
            // insert base meta-tag,
            ModelUtil.insertBase(, ModelUtil.getParentFolderOSString());
            // resolve all relative resources relative to content file. Do it before
            // inserting shared style to enable comparing fully qualified styles.
            ModelUtil.updateResourceAttributes(.getDocumentElement(), this);
            // now add shared style.
            IntroModelRoot modelRoot = (IntroModelRoot)getParent();
            IntroPartPresentation presentation = modelRoot.getPresentation();
            String [] styles = presentation!=null?presentation.getImplementationStyles():null;
            if (styles != null && injectSharedStyle()) {
            	for (int i=0; i<styles.lengthi++)
            		ModelUtil.insertStyle(styles[i]);
            }
            // filter the content
            if ( == null) {
            	 = new DocumentProcessor(new ProcessorHandler[] { new FilterHandler(IntroEvaluationContext.getContext()) });
            }
            UAElement element = UAElementFactory.newElement(.getDocumentElement());
            .process(elementnull);
            
            // and resolve includes.
            resolveIncludes();
            // now remove all anchors from this page.
            ModelUtil.removeAllElements(.);
             = true;
        }

        
    Resolves all includes in this page. This means importing the DOM of the target path into the current page DOM, and resolving XHTML attributes for resources.
        protected void resolveIncludes() {
            // get all includes elements in DOM.
            NodeList includes = .getElementsByTagNameNS("*"//$NON-NLS-1$
                .);
            // get the array version of the include nodelist to work around
            // replaceChild() DOM api design.
            Node[] nodes = ModelUtil.getArray(includes);
            for (int i = 0; i < nodes.lengthi++) {
                Element includeElement = (Elementnodes[i];
                IntroInclude include = new IntroInclude(includeElementgetBundle());
                // result[0] is target parent page, result[1] is target element.
                Object[] results = findDOMIncludeTarget(include);
                Element targetElement = (Elementresults[1];
                if (targetElement == null) {
                    String message = "Could not resolve following include:  " //$NON-NLS-1$
                            + ModelLoaderUtil.getLogString(getBundle(),
                                includeElement.);
                    Log.warning(message);
                    return;
                }
                // insert the target element instead of the include.
                Node targetNode = .importNode(targetElementtrue);
                // update the src attribute of this node, if defined by w3
                // specs.
                AbstractIntroPage page = ((AbstractIntroPageresults[0]);
                ModelUtil.updateResourceAttributes((ElementtargetNodepage);
                // use of replace API to remove include element is tricky. It
                // confuses the NodeList used in the loop above. Removing an include
                // removes it from the NodeList. Used cloned Array instead.
                includeElement.getParentNode().replaceChild(targetNode,
                    includeElement);
            }
        }


        
    Find the target Element pointed to by the path in the include. It is assumed that configId always points to an external config, and not the same config of the inlcude.

    Parameters:
    include
    path
    Returns:
        private Object[] findDOMIncludeTarget(IntroInclude include) {
            String path = include.getPath();
            IntroModelRoot targetModelRoot = (IntroModelRootgetParentPage()
                .getParent();
            String targetConfigID = include.getConfigId();
            if (targetConfigID != null)
                targetModelRoot = ExtensionPointManager.getInst().getModel(
                    targetConfigID);
            if (targetModelRoot == null)
                // if the target config was not found, skip this include.
                return null;
            return findDOMTarget(targetModelRootpath);
        }



        
    Finds the child element that corresponds to the given path in the passed model.

    Parameters:
    model model containing target path.
    path the path to look for
    results two object array that will return the target intro page as the first result, and the actual target DOM Element as the second result. It is gauranteed to not be null. Content may be null.
    Returns:
    target DOM element
        public Object[] findDOMTarget(IntroModelRoot modelString path) {
            Object[] results = new Object[2];
            // path must be pageId/anchorID in the case of of XHTML pages.
            // pages.
            String[] pathSegments = StringUtil.split(path"/"); //$NON-NLS-1$
            if (pathSegments.length != 2)
                // path does not have correct format. Return empty results.
                return results;
            // save to cast.
            AbstractIntroPage targetPage = (AbstractIntroPagemodel.findChild(
                pathSegments[0], );
            if (targetPage != null) {
                results[0] = targetPage;
                Element targetElement = targetPage.findDomChild(pathSegments[1]);
                if (targetElement != null)
                    results[1] = targetElement;
            }
            return results;
        }


        

    Returns:
    Returns the content.
        public String getContent() {
            return ;
        }



        
    Deep copy since class has mutable objects.
        public Object clone() throws CloneNotSupportedException {
            AbstractIntroPage clone = (AbstractIntroPagesuper.clone();
            if ( != null) {
                IntroPageTitle clonedTitle = (IntroPageTitle.clone();
                clonedTitle.setParent(clone);
                clone.title = clonedTitle;
            }
            // styles are safe for a shallow copy.
            if ( != null)
                clone.styles = (Vector.clone();
            if ( != null)
                clone.altStyles = (Hashtable.clone();
            return clone;
        }

        
    Used when cloning pages to assign a unique id. Cache original id before setting.

    Parameters:
    id
        public void setId(String id) {
            this. = this.;
            this. = id;
        }
        /*
         * Creates an IFrame and injects it as the only child of the specified path.
         */
        public boolean injectIFrame(String urlString embedTarget) {
            // embed url as IFrame in target div. We need to find target div in
            // this cloned page not in the original page.
            IntroGroup divToReplace = (IntroGroupfindTarget(embedTarget);
            if (divToReplace == null) {
                // we failed to find embed div, log and exit.
                Log.warning("Failed to find embedTarget: " + embedTarget //$NON-NLS-1$
                        + " in page " + getId()); //$NON-NLS-1$
                return false;
            }
            this. = new IntroInjectedIFrame(getElement(), getBundle());
            this..setParent(divToReplace);
            this..setIFrameURL(url);
            divToReplace.clearChildren();
            divToReplace.addChild();
            return true;
        }

        
    Return true if this page is a cloned page that has an IFrame.

    Returns:
        public boolean isIFramePage() {
            return ( != null) ? true : false;
        }
        public String getUnmangledId() {
            if (isIFramePage())
                return ;
            return ;
        }


        
    Set the url of the embedded IFrame, if this page is an IFrame page.

    Parameters:
    url
        public void setIFrameURL(String url) {
            if (!isIFramePage())
                return;
            this..setIFrameURL(url);
        }

        
    Return the url of the embedded IFrame, if this page is an IFrame page.

    Parameters:
    url
        public String getIFrameURL() {
            if (!isIFramePage())
                return null;
            return this..getIFrameURL();
        }

        
    Returns the raw or unprocessed base location.
        public String getInitialBase() {
        	return ;
        }
        
        
    Return the url of the embedded IFrame, if this page is an IFrame page.

    Parameters:
    url
        public boolean injectSharedStyle() {
            return this..equals("true") ? true : false//$NON-NLS-1$
        }

    Returns true if this is a dynamicpage or not.

    Returns:
    Returns the isDynamic.
    	public boolean isDynamic() {
    	    return ;
    	}

    Returns:
    Returns the url.
        public String getUrl() {
            return ;
        }

    Returns:
    Returns the isStandbyPage.
    	public boolean isStandbyPage() {
    	    return ;
    	}

    Parameters:
    isStandbyPage The isStandbyPage to set.
    	public void setStandbyPage(boolean isStandbyPage) {
    	    this. = isStandbyPage;
    	}
    New to GrepCode? Check out our FAQ X