Package org.eclipse.wst.sse.ui.internal.reconcile

Source Code of org.eclipse.wst.sse.ui.internal.reconcile.DocumentRegionProcessor

/*******************************************************************************
* Copyright (c) 2006, 2010 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
*     David Carver (Intalio) - bug 307323 - remove extraneous call to spell check strategy
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal.reconcile;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
import org.eclipse.wst.sse.ui.internal.IReleasable;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingStrategy;
import org.eclipse.wst.sse.ui.internal.provisional.preferences.CommonEditorPreferenceNames;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorBuilder;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorMetaData;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorStrategy;
import org.eclipse.wst.sse.ui.internal.spelling.SpellcheckStrategy;
import org.eclipse.wst.sse.ui.reconcile.ISourceReconcilingListener;

/**
* Adds to DirtyRegionProcessor Job: - IDocumentListener - ValidatorStrategy -
* Text viewer(dispose, input changed) listeners. - default, spelling, and
* validator strategies - DirtyRegion processing logic.
*/
public class DocumentRegionProcessor extends DirtyRegionProcessor {
  private static final boolean DEBUG_VALIDATORS = Boolean.TRUE.toString().equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/reconcilerValidators")); //$NON-NLS-1$

  /**
   * A strategy to use the defined default Spelling service.
   */
  private IReconcilingStrategy fSpellcheckStrategy;

  /**
   * The strategy that runs validators contributed via
   * <code>org.eclipse.wst.sse.ui.extensions.sourcevalidation</code>
   * extension point
   */
  private ValidatorStrategy fValidatorStrategy;

  private ISourceReconcilingListener[] fReconcileListeners = new ISourceReconcilingListener[0];

  private IReconcilingStrategy fSemanticHighlightingStrategy;
 
  /**
   * The folding strategy for this processor
   */
  private AbstractStructuredFoldingStrategy fFoldingStrategy;
 
  private final String SSE_UI_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$

  /**
   * true if as you type validation is enabled,
   * false otherwise
   */
  private boolean fValidationEnabled;

  public void addReconcilingListener(ISourceReconcilingListener listener) {
    Set listeners = new HashSet(Arrays.asList(fReconcileListeners));
    listeners.add(listener);
    fReconcileListeners = (ISourceReconcilingListener[]) listeners.toArray(new ISourceReconcilingListener[listeners.size()]);
  }

  protected void beginProcessing() {
    super.beginProcessing();
    ValidatorStrategy validatorStrategy = getValidatorStrategy();
    if (validatorStrategy != null) {
      validatorStrategy.beginProcessing();
    }
    if ((getTextViewer() instanceof ISourceViewer)) {
      for (int i = 0; i < fReconcileListeners.length; i++) {
        fReconcileListeners[i].aboutToBeReconciled();
      }
    }
  }

  protected void endProcessing() {
    super.endProcessing();
    ValidatorStrategy validatorStrategy = getValidatorStrategy();
    if (validatorStrategy != null) {
      validatorStrategy.endProcessing();
    }
    /* single spell-check for everything to ensure that SpellingProblem offsets are correct */
    IReconcilingStrategy spellingStrategy = getSpellcheckStrategy();
    IDocument document = getDocument();
    if (spellingStrategy != null && document != null) {
       spellingStrategy.reconcile(new Region(0, document.getLength()));
    }
   
    IReconcilingStrategy semanticHighlightingStrategy = getSemanticHighlightingStrategy();
    if (semanticHighlightingStrategy != null && document != null) {
      semanticHighlightingStrategy.reconcile(new Region(0, document.getLength()));
    }

    if ((getTextViewer() instanceof ISourceViewer)) {
      ISourceViewer sourceViewer = (ISourceViewer) getTextViewer();
      IAnnotationModel annotationModel = sourceViewer.getAnnotationModel();
      for (int i = 0; i < fReconcileListeners.length; i++) {
        fReconcileListeners[i].reconciled(document, annotationModel, false, new NullProgressMonitor());
      }
    }
  }

  public void forceReconciling() {
    super.forceReconciling();
  }

  protected String getContentType(IDocument doc) {
    if (doc == null)
      return null;

    String contentTypeId = null;

    IContentType ct = null;
    try {
      IContentDescription desc = Platform.getContentTypeManager().getDescriptionFor(new StringReader(doc.get()), null, IContentDescription.ALL);
      if (desc != null) {
        ct = desc.getContentType();
        if (ct != null)
          contentTypeId = ct.getId();
      }
    }
    catch (IOException e) {
      // just bail
    }
    return contentTypeId;
  }

  protected IReconcilingStrategy getSpellcheckStrategy() {
    if (fSpellcheckStrategy == null && getDocument() != null) {
      String contentTypeId = getContentType(getDocument());
      if (contentTypeId == null) {
        contentTypeId = IContentTypeManager.CT_TEXT;
      }
      if (getTextViewer() instanceof ISourceViewer) {
        ISourceViewer viewer = (ISourceViewer) getTextViewer();
        fSpellcheckStrategy = new SpellcheckStrategy(viewer, contentTypeId);
        fSpellcheckStrategy.setDocument(getDocument());
      }
    }
    return fSpellcheckStrategy;
  }
 
  /**
   * <p>Get the folding strategy for this processor. Retrieved from the
   * extended configuration builder.  The processor chosen is set by the plugin.</p>
   *
   * <p>EX:<br />
   * <code>&lt;extension point="org.eclipse.wst.sse.ui.editorConfiguration"&gt;<br />
   *  &lt;provisionalConfiguration<br />
   *      type="foldingstrategy"<br />
   *      class="org.eclipse.wst.xml.ui.internal.projection.XMLFoldingStrategy"<br />
   *      target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" /&gt;<br />
   *  &lt;/extension&gt;</code></p>
   *
   * <p>The type must be equal to <code>AbstractFoldingStrategy.ID</code> (AKA: foldingstrategy)
   * and the class must extend <code>org.eclipse.wst.sse.ui.internal.projection.AbstractFoldingStrategy</code>
   * and the target must be a structured editor content type ID</p>
   *
   * @return the requested folding strategy or null if none can be found
   */
  protected IReconcilingStrategy getFoldingStrategy() {
    if(fFoldingStrategy == null && getDocument() != null) {
      String contentTypeId = getContentType(getDocument());
      if (contentTypeId == null) {
        contentTypeId = IContentTypeManager.CT_TEXT;
      }
     
      ITextViewer viewer = getTextViewer();
      if(viewer instanceof ProjectionViewer) {
        ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
       
        IContentType type = Platform.getContentTypeManager().getContentType(contentTypeId);
        while(fFoldingStrategy == null && type != null) {
          fFoldingStrategy =(AbstractStructuredFoldingStrategy) builder.getConfiguration(
              AbstractStructuredFoldingStrategy.ID, type.getId());
       
          type = type.getBaseType();
        }
       
        if(fFoldingStrategy != null) {
          fFoldingStrategy.setViewer((ProjectionViewer)viewer);
          fFoldingStrategy.setDocument(getDocument());
        }
      }
    }
   
    return fFoldingStrategy;
  }
 
  /**
   * Enable or disable as you type validation. Typically set by a user preference
   *
   * @param enable true to enable as you type validation, false to disable
   */
  public void setValidatorStrategyEnabled(boolean enable) {
    fValidationEnabled = enable;
  }

  /**
   * @return Returns the ValidatorStrategy.
   */
  protected ValidatorStrategy getValidatorStrategy() {
    ValidatorStrategy validatorStrategy = null;
    if (fValidatorStrategy == null && fValidationEnabled) {
      if (getTextViewer() instanceof ISourceViewer) {
        ISourceViewer viewer = (ISourceViewer) getTextViewer();
        String contentTypeId = null;

        IDocument doc = viewer.getDocument();
        contentTypeId = getContentType(doc);

        if (contentTypeId != null) {
          validatorStrategy = new ValidatorStrategy(viewer, contentTypeId);
          ValidatorBuilder vBuilder = new ValidatorBuilder();
          ValidatorMetaData[] vmds = vBuilder.getValidatorMetaData(SSE_UI_ID);
          List enabledValidators = new ArrayList(1);
          /* if any "must" handle this content type, just add them */
          boolean foundSpecificContentTypeValidators = false;
          for (int i = 0; i < vmds.length; i++) {
            if (vmds[i].mustHandleContentType(contentTypeId)) {
              if (DEBUG_VALIDATORS)
                Logger.log(Logger.INFO, contentTypeId + " using specific validator " + vmds[i].getValidatorId()); //$NON-NLS-1$
              foundSpecificContentTypeValidators = true;
              enabledValidators.add(vmds[i]);
            }
          }
          if (!foundSpecificContentTypeValidators) {
            for (int i = 0; i < vmds.length; i++) {
              if (vmds[i].canHandleContentType(contentTypeId)) {
                if (DEBUG_VALIDATORS)
                  Logger.log(Logger.INFO, contentTypeId + " using inherited(?) validator " + vmds[i].getValidatorId()); //$NON-NLS-1$
                enabledValidators.add(vmds[i]);
              }
            }
          }
          for (int i = 0; i < enabledValidators.size(); i++) {
            validatorStrategy.addValidatorMetaData((ValidatorMetaData) enabledValidators.get(i));
          }
        }
      }
      fValidatorStrategy = validatorStrategy;
    } else if(fValidatorStrategy != null && fValidationEnabled) {
      validatorStrategy = fValidatorStrategy;
    }
    return validatorStrategy;
  }
 
  public void setSemanticHighlightingStrategy(IReconcilingStrategy semanticHighlightingStrategy) {
    fSemanticHighlightingStrategy = semanticHighlightingStrategy;
    fSemanticHighlightingStrategy.setDocument(getDocument());
  }
 
  protected IReconcilingStrategy getSemanticHighlightingStrategy() {
    return fSemanticHighlightingStrategy;
  }
 
  /**
   * @param dirtyRegion
   */
  protected void process(DirtyRegion dirtyRegion) {
    if (!isInstalled() || isInRewriteSession() || dirtyRegion == null || getDocument() == null)
      return;

    super.process(dirtyRegion);
   
    ITypedRegion[] partitions = computePartitioning(dirtyRegion);
   
    // call the validator strategy once for each effected partition
    DirtyRegion dirty = null;
    for (int i = 0; i < partitions.length; i++) {
      dirty = createDirtyRegion(partitions[i], DirtyRegion.INSERT);

      // [source]validator (extension) for this partition
      if (getValidatorStrategy() != null) {
        getValidatorStrategy().reconcile(partitions[i], dirty);
      }
    }
   
    /* if there is a folding strategy then reconcile it for the
     * entire dirty region.
     * NOTE: the folding strategy does not care about the sub regions.
     */
    if(getFoldingStrategy() != null) {
      getFoldingStrategy().reconcile(dirtyRegion, null);
    }
  }
 
  public void removeReconcilingListener(ISourceReconcilingListener listener) {
    Set listeners = new HashSet(Arrays.asList(fReconcileListeners));
    listeners.remove(listener);
    fReconcileListeners = (ISourceReconcilingListener[]) listeners.toArray(new ISourceReconcilingListener[listeners.size()]);
  }


  public void setDocument(IDocument doc) {
    super.setDocument(doc);
   
    IReconcilingStrategy validatorStrategy = getValidatorStrategy();
    if (validatorStrategy != null) {
      validatorStrategy.setDocument(doc);
    }
    if (fSemanticHighlightingStrategy != null) {
      fSemanticHighlightingStrategy.setDocument(doc);
    }
   
    fSpellcheckStrategy = null;
    if(fFoldingStrategy != null) {
      fFoldingStrategy.uninstall();
    }
    fFoldingStrategy = null;
  }

  protected void setEntireDocumentDirty(IDocument document) {
    super.setEntireDocumentDirty(document);

    // make the entire document dirty
    // this also happens on a "save as"
    if (document != null && isInstalled() && fLastPartitions != null && document.getLength() == 0) {
      /**
       * https://bugs.eclipse.org/bugs/show_bug.cgi?id=199053
       *
       * Process the strategies for the last known-good partitions.
       */
      for (int i = 0; i < fLastPartitions.length; i++) {
        ValidatorStrategy validatorStrategy = getValidatorStrategy();
        if (validatorStrategy != null) {
          validatorStrategy.reconcile(fLastPartitions[i], createDirtyRegion(fLastPartitions[i], DirtyRegion.REMOVE));
        }
      }
      IReconcilingStrategy spellingStrategy = getSpellcheckStrategy();
      if (spellingStrategy != null) {
        spellingStrategy.reconcile(new Region(0, document.getLength()));
      }
     
      //if there is a folding strategy then reconcile it
      if(getFoldingStrategy() != null) {
        getFoldingStrategy().reconcile(new Region(0, document.getLength()));
      }
    }
  }

  /**
   * @see org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor#install(org.eclipse.jface.text.ITextViewer)
   */
  public void install(ITextViewer textViewer) {
    super.install(textViewer);

    //determine if validation is enabled
    this.fValidationEnabled = SSEUIPlugin.getInstance().getPreferenceStore().getBoolean(
        CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS);
  }
 
  /**
   * @see org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor#uninstall()
   */
  public void uninstall() {
    if (isInstalled()) {

      cancel();

      IReconcilingStrategy validatorStrategy = getValidatorStrategy();

      if (validatorStrategy != null) {
        if (validatorStrategy instanceof IReleasable)
          ((IReleasable) validatorStrategy).release();
      }
     
      if (fSpellcheckStrategy != null) {
        fSpellcheckStrategy.setDocument(null);
        fSpellcheckStrategy = null;
      }

      fReconcileListeners = new ISourceReconcilingListener[0];
    }
    super.uninstall();
  }
}
TOP

Related Classes of org.eclipse.wst.sse.ui.internal.reconcile.DocumentRegionProcessor

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.