Package org.eclipse.wst.html.core.internal.htmlcss

Source Code of org.eclipse.wst.html.core.internal.htmlcss.LinkElementAdapter

/*******************************************************************************
* Copyright (c) 2004, 2009 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.wst.html.core.internal.htmlcss;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.css.core.internal.provisional.adapters.IModelProvideAdapter;
import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
import org.eclipse.wst.css.core.internal.provisional.contenttype.ContentTypeIdForCSS;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.util.URIResolver;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
*/
public class LinkElementAdapter extends AbstractStyleSheetAdapter {

  private final static String CSS_ID = ContentTypeIdForCSS.ContentTypeID_CSS;
  private boolean replaceModel = true;
  // this variable to hold the class is just a VAJava trick.
  // it improves performance in VAJava by minimizing class loading.
  private final Class ModelProvideAdapterClass = IModelProvideAdapter.class;

  /**
   */
  protected LinkElementAdapter() {
    super();
  }

  /**
   */
  private void attrReplaced() {
    this.replaceModel = true;

    Element element = getElement();
    if (element == null)
      return; // error
    Document document = element.getOwnerDocument();
    if (document == null)
      return; // error
    INodeNotifier notifier = (INodeNotifier) document;
    HTMLDocumentAdapter adapter = (HTMLDocumentAdapter) notifier.getAdapterFor(IStyleSheetListAdapter.class);
    if (adapter == null)
      return;
    adapter.childReplaced();
  }

  protected ICSSModel createModel() {
    // create phantom(broken link) external CSS model
    if (getElement() == null)
      return null;
    IStructuredModel baseModel = ((IDOMNode) getElement()).getModel();
    ICSSModel newModel = (ICSSModel) baseModel.getModelManager().createUnManagedStructuredModelFor(CSS_ID);

    // calculate base location and set
    // get resolver in Model
    URIResolver resolver = baseModel.getResolver();

    // resolve to absolute url : this need not exact location of css file. It is important that absurl is not null.
    String ref = getElement().getAttribute(HTML40Namespace.ATTR_NAME_HREF);
    String absurl = (resolver != null && ref != null && ref.length() > 0) ? resolver.getLocationByURI(ref, true) : null;
    if ((absurl == null) || (absurl.length() == 0)) {
      IPath basePath = new Path(baseModel.getBaseLocation());
      URLHelper helper = new URLHelper(basePath.removeLastSegments(1).toString());
      absurl = helper.toAbsolute(ref == null ? "" : ref);//$NON-NLS-1$
    }
    if ((absurl == null) || (absurl.length() == 0)) {
      absurl = ref;
    }
    if (absurl == null) {
      absurl = "";//$NON-NLS-1$
    }
    newModel.setBaseLocation(absurl);

    // set style listener
    newModel.addStyleListener(this);

    return newModel;
  }

  /**
   */
  public ICSSModel getModel() {
    ICSSModel model = getExistingModel();
    if (this.replaceModel) {
      ICSSModel oldModel = model;
      try {
        model = retrieveModel();
        setModel(model);

        // release old model
        if (oldModel != null) {
          // get ModelProvideAdapter
          IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
          if (adapter != null)
            adapter.modelRemoved(oldModel);
        }
      }
      finally {
        if (oldModel != null)
          oldModel.releaseFromRead();
      }
      this.replaceModel = false;
    }
    return model;
  }

  /**
   */
  public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
    if (eventType != INodeNotifier.CHANGE)
      return;
    Attr attr = (Attr) changedFeature;
    if (attr == null)
      return;
    String name = attr.getName();
    if (name.equalsIgnoreCase("rel") || //$NON-NLS-1$
          name.equalsIgnoreCase("type") || //$NON-NLS-1$ 
          name.equalsIgnoreCase("href")) {//$NON-NLS-1$
      attrReplaced();
    }
  }

  /**
   */
  public void refreshSheet() {
    if (!replaceModel) {
      removed();
      replaceModel = true;

      IDOMNode node = (IDOMNode) getElement();
      if (node != null) {
        node.notify(INodeNotifier.CHANGE, getElement().getAttributeNode(org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ATTR_NAME_HREF), null, null, node.getStartOffset());
      }
    }
  }

  /**
   */
  public void released() {
    ICSSModel model = getExistingModel();
    if (model != null) {
      try {
        // get ModelProvideAdapter
        IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);

        // set element to null first, so that no document wide updates
        setElement(null);
        setModel(null);

        if (adapter != null)
          adapter.modelReleased(model);
      }
      finally {
        model.releaseFromRead();
      }
    }
    this.replaceModel = false;
  }

  /**
   */
  public void removed() {
    ICSSModel model = getExistingModel();
    if (model != null) {
      try {
        setModel(null);

        // get ModelProvideAdapter
        IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
        if (adapter != null)
          adapter.modelRemoved(model);
      }
      finally {
        model.releaseFromRead();
      }
    }
    this.replaceModel = false;
  }

  /**
   */
  protected boolean isValidAttribute() {
    Element element = getElement();
    if (element == null)
      return false;
    if (!element.hasAttribute("rel") || !"stylesheet".equalsIgnoreCase(element.getAttribute("rel")))//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      return false;
    if (element.hasAttribute("type") && !"text/css".equalsIgnoreCase(element.getAttribute("type")))//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      return false;
    if (!element.hasAttribute("href") || element.getAttribute("href").length() == 0) //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    return true;
  }

  /**
   */
  private ICSSModel retrieveModel() {
    if (!isValidAttribute()) {
      return null;
    }

    // null,attr check is done in isValidAttribute()
    Element element = getElement();
    String href = element.getAttribute("href");//$NON-NLS-1$

    IDOMModel baseModel = ((IDOMNode) element).getModel();
    if (baseModel == null)
      return null;
    Object id = baseModel.getId();
    if (!(id instanceof String))
      return null;
    //String base = (String)id;

    // get ModelProvideAdapter
    IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(ModelProvideAdapterClass);

    URLModelProvider provider = new URLModelProvider();
    try {
      IStructuredModel newModel = provider.getModelForRead(baseModel, href);
      if (newModel == null)
        return null;
      if (!(newModel instanceof ICSSModel)) {
        newModel.releaseFromRead();
        return null;
      }

      // notify adapter
      if (adapter != null)
        adapter.modelProvided(newModel);

      return (ICSSModel) newModel;
    }
    catch (UnsupportedEncodingException e) {
    }
    catch (IOException e) {
    }

    return null;
  }

  /**
   */
  protected void setModel(ICSSModel model) {
    ICSSModel oldModel = getExistingModel();
    if (model == oldModel)
      return;
    super.setModel(model);
    if (this.replaceModel)
      this.replaceModel = false;
    if (oldModel != null)
      oldModel.removeStyleListener(this);
    if (model != null)
      model.addStyleListener(this);
  }
}
TOP

Related Classes of org.eclipse.wst.html.core.internal.htmlcss.LinkElementAdapter

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.