Package org.eclipse.jst.jsf.core.internal.tld

Source Code of org.eclipse.jst.jsf.core.internal.tld.CMUtil

/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. 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:
*     Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.core.internal.tld;

import java.util.Iterator;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.CMDocumentFactoryTLD;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TaglibTracker;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
import org.w3c.dom.Element;

/**
* Utility class to content model related information.
*
* @author mengbo
*/
public final class CMUtil {
  /**
   * If the element is a custom tag, get the URI of it. If the element is a
   * standard JSP tag, return null. If is not jsp tag, then return null
   * @param decl
     * 
   * @return the tag uri as a string
   */
  public static String getTagURI(CMElementDeclaration decl) {
    if (decl instanceof CMNodeWrapper) {
      decl = (CMElementDeclaration) ((CMNodeWrapper) decl)
          .getOriginNode();
    }
    if (decl instanceof TLDElementDeclaration) {
      CMDocument doc = ((TLDElementDeclaration) decl).getOwnerDocument();
      if (doc instanceof TLDDocument) {
        TLDDocument tldDoc = (TLDDocument)doc;
        return getURIFromDoc(tldDoc , null);
      }
    }
    return null;
  }
  /**
   * @param doc
   * @param project - may be null in which case it is calculated as necessary from the doc baseLocation
   * @return valid string to use for the uri when given a TLD doc
   *       Must <ul>not</ul> be called with HTML or JSP documents.
   *       As there is no API on the doc for standalone or tagDir doc, it is possible that this could return an invalid string. 
   *         However, if the code is consistent in it's usage, all should be well.
   *         or null if not found.
   */
  public static String  getURIFromDoc(final TLDDocument doc, final IProject project) {
    String uri = doc.getUri();
    IProject proj = project;
    if (uri == null) {//
      Path baseLoc = new Path(doc.getBaseLocation());
      if (proj == null) {
        proj = getProjectFor(baseLoc);
        if (proj == null) {//log error
          return null;
        }
      }
     
      if (isTagDirDocument(doc, proj)) {
        uri = getTagDirURI(doc, proj);
      } else {
        uri = getStandaloneTLDURI(doc, proj);
      }
    }
    return uri;
  }

  /**
   * @param tldRec
   * @param project
   * @return valid string to use for the uri when given a ITaglibRecord
   * or null.
   */
  public static String getURIFromTaglibRecord(ITaglibRecord tldRec, IProject project) {   
    //similar code in PaletteHelper and above   
    String uri = tldRec.getDescriptor().getURI();
    if (uri == null || uri.trim().equals("")) {     //$NON-NLS-1$
      //need to construct valid string representing taglib identifier
      CMDocumentFactoryTLD factory = new CMDocumentFactoryTLD();
      TLDDocument doc = (TLDDocument)factory.createCMDocument(tldRec);
      if (tldRec.getRecordType() == ITaglibRecord.TLD) {   
        uri = getStandaloneTLDURI(doc, project);     
      }
      else if (tldRec.getRecordType() == ITaglibRecord.TAGDIR) { 
        uri =  getTagDirURI(doc, project);       
      }
     
    }
    return uri;
  }
 
  private static String getStandaloneTLDURI(TLDDocument doc, IProject project) {
    Path p = new Path(doc.getBaseLocation());
    IPath webContentPath = ComponentCore.createComponent(project).getRootFolder().getUnderlyingFolder().getLocation();
    return getURIFromPath(p.makeAbsolute().makeRelativeTo(webContentPath.makeAbsolute()));   
  }

  private static String getTagDirURI(TLDDocument doc, IProject project) {
    Path p = new Path(doc.getBaseLocation());
    IVirtualComponent projectComp = ComponentCore.createComponent(project);
   
    if (projectComp != null)
    {
        IVirtualFolder rootFolder = projectComp.getRootFolder();
       
        if (rootFolder != null)
        {
            IPath webContentPath =
                rootFolder.getUnderlyingFolder().getFullPath();
            return getURIFromPath(p.makeRelativeTo(webContentPath));
        }
    }
    return null;
  }

  private static String getURIFromPath(IPath uriPath)
  {
    if (uriPath != null)
      return "/"+uriPath.toString(); //$NON-NLS-1$ - do not remove "/" since is necessary for tagdir attr on taglib directive
   
    return null;
  }

  /**
   * @param tldDoc - must not be null
   * @param project - must not be null
   * @return true if this is a tag dir tldDocument
   */
  public static boolean isTagDirDocument(final TLDDocument tldDoc, final IProject project) {
    if (tldDoc.getUri() == null || tldDoc.getUri().equals("")) { //$NON-NLS-1$
      IPath p = new Path(tldDoc.getBaseLocation());
      IPath webContentPath = ComponentCore.createComponent(project).getRootFolder().getUnderlyingFolder().getFullPath();
      if (p.matchingFirstSegments(webContentPath) == webContentPath.segmentCount()) {
        p = p.removeFirstSegments(webContentPath.segmentCount());
        if (p.matchingFirstSegments(new Path("WEB-INF/tags")) == 2) { //$NON-NLS-1$)  {
          return true;
        }
      }
    }
    return false;
  }
 
  //Code taken from jsf.common.ui.WorkspaceUtil
  private static IProject getProjectFor(IPath path) {
    String[] segs = path.segments();
    String projectPath = new String();
    IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
        .getProjects();
    IProject project = null;
    for (int p = 0; p < projects.length; p++) {
      if (projects[p].isOpen()) {
        for (int s = 0; s < segs.length; s++) {
          if (segs[s].equalsIgnoreCase(projects[p].getName())) {
            // Once we have a match on the project name, then
            // the remainder of the segments equals the project path
            for (int s2 = s + 1; s2 < segs.length; s2++) {
              projectPath = projectPath
                  + "/" //$NON-NLS-1$
                  + segs[s2];
            }
            project = projects[p];
            break;
          }
        }
      }
    }
    if (project == null) {
      return null;
    }

    // TODO: still don't understand why this refreshLocal is necessary
    // for now, going to only allow it if this method is called
    // when the tree isn't locked.  This shouldn't cause a regression, since
    // when the call fails currently things keep on going due to the catch
    if (!project.getWorkspace().isTreeLocked())
    {
        try {
          project.refreshLocal(IResource.DEPTH_INFINITE, null);
        } catch (CoreException e) {
//                 TODO C.B.:pushing this down to a warning because it creates really
//                 spurious output.  Don't know why we are calling refreshLocal at all.
                JSFCorePlugin.log(Status.WARNING, "Error.RefreshingLocal", e); //$NON-NLS-1$
        }
    }
   
    IResource res = project.findMember(new Path(projectPath));
    if ((res != null) && (res.exists())) {
      return project;
    }
    return null;
  }
 
  /**
   * Test whether this is the JSP core tag.
   *
   * @param decl
   * @return true if decl is a jsp element declaration
   */
  public static boolean isJSP(CMElementDeclaration decl) {
    if (!decl.supports(HTMLCMProperties.IS_JSP)) {
      return false;
    }
    Boolean b = (Boolean) decl.getProperty(HTMLCMProperties.IS_JSP);
    return b.booleanValue();
  }

  /**
   * @param decl
   * @return true if the element declartion is a non-JSP html element
   */
  public static boolean isHTML(CMElementDeclaration decl) {
    if (!isJSP(decl) && (decl instanceof HTMLElementDeclaration)) {
      return true;
    }
    return false;
  }

  /**
   * get element declaration of specified element
   *
   * @param element
   * @return null if can't get it.
   */
  public static CMElementDeclaration getElementDeclaration(Element element) {
    if (element == null) {
      return null;
    }
    INodeNotifier notifier = (INodeNotifier) element.getOwnerDocument();
    if (notifier == null) {
      return null;
    }
    ModelQueryAdapter mqa = (ModelQueryAdapter) notifier
        .getAdapterFor(ModelQueryAdapter.class);
    if (mqa == null) {
      return null;
    }
    return mqa.getModelQuery().getCMElementDeclaration(element);
  }

  /**
   * @param element
   * @return the TLDElementDeclaration for element or null if not found
   */
  public static TLDElementDeclaration getTLDElementDeclaration(Element element) {
    CMNode decl = getElementDeclaration(element);
    if (decl instanceof CMNodeWrapper) {
      decl = ((CMNodeWrapper) decl).getOriginNode();
    }
    if (decl instanceof TLDElementDeclaration) {
      return (TLDElementDeclaration) decl;
    }
        return null;
  }
 
  /**
   * !!! NOTE: this function is intended to work around the problem that if your element
   * has not yet been added to an  IDOMModel, getElementDeclaration won't be able to find
   * it.  This method does nothing (unlike the ModelQuery-based approach in getElementDeclaration)
   * to ensure that the namespace "uri" provided is valid in the structured document provided.  It is
   * therefore only advisable to use this method in cases where your node is not already a member of a
   * IDOMModel.
   *
   * @param uri
   * @param elementName
   * @param document
   * @return the TLDElementDeclaration for this required tag or null if there  is nothing appropriate
   */
  public static CMElementDeclaration getTLDElementDeclaration(final String uri, final String elementName, IDocument document)
  {
      TLDCMDocumentManager tldmgr = TaglibController.getTLDCMDocumentManager(document);
     
      if (tldmgr != null)
      {
            for (Iterator it = tldmgr.getTaglibTrackers().iterator();it.hasNext();)
            {
                TaglibTracker  tracker = (TaglibTracker) it.next();
               
                if (tracker.getURI().equals(uri))
                {
                    return (CMElementDeclaration) tracker.getElements().getNamedItem(tracker.getPrefix()+":"+elementName); //$NON-NLS-1$
                }
            }
      }
        // fallthrough
        return null;
  }

  /**
   * give an element, get its namespace URI.
   *
   * @param element
   * @return the namespace URI
   */
  public static String getElementNamespaceURI(Element element) {
      //System.out.printf("uri for %s is %s\n", element.toString(), element.getNamespaceURI());

      CMElementDeclaration decl = getElementDeclaration(element);
    if (decl == null) {
       
        // if the content model has nothing, see if the element
        // itself has an xml namespace
        // TODO: should only apply this if the source document
        // is a valid XML doc?
        final String uri = element.getNamespaceURI();
       
        // may be null which the default state
      return uri;
    }

    if (isJSP(decl)) {
      return ITLDConstants.URI_JSP;
    } else if (isHTML(decl)) {
      return ITLDConstants.URI_HTML;
    }

    return getTagURI(decl);
  }

  /**
   * @param element
   * @return true if the element can have children
   */
  public static boolean canHaveDirectTextChild(Element element) {
    CMElementDeclaration decl = getElementDeclaration(element);
    if (decl == null) {
      return true;
    }
    int contentType = decl.getContentType();
    return contentType != CMElementDeclaration.ELEMENT
        && contentType != CMElementDeclaration.EMPTY;

  }
   
    private CMUtil()
    {
        // util class, no external instantiation
    }

}
TOP

Related Classes of org.eclipse.jst.jsf.core.internal.tld.CMUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.