blob: fd082423f958b1688aab055e8f9285efe07d291e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.jface.text.reconciler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IRegion;
/**
* Abstract implementation of a reconcile step.
*
* @since 3.0
*/
public abstract class AbstractReconcileStep implements IReconcileStep {
private IReconcileStep fNextStep;
private IReconcileStep fPreviousStep;
private IProgressMonitor fProgressMonitor;
protected IReconcilableModel fInputModel;
/**
* Creates an intermediate reconcile step which adds
* the given step to the pipe.
*
* @param step the reconcile step
*/
public AbstractReconcileStep(IReconcileStep step) {
Assert.isNotNull(step);
fNextStep= step;
fNextStep.setPreviousStep(this);
}
/**
* Creates the last reconcile step of the pipe.
*/
public AbstractReconcileStep() {
}
public boolean isLastStep() {
return fNextStep == null;
}
public boolean isFirstStep() {
return fPreviousStep == null;
}
/*
* @see org.eclipse.text.reconcilerpipe.IReconcilerResultCollector#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
*/
public void setProgressMonitor(IProgressMonitor monitor) {
fProgressMonitor= monitor;
if (!isLastStep())
fNextStep.setProgressMonitor(monitor);
}
/*
* @see org.eclipse.jface.text.reconciler.IReconcileStep#getProgressMonitor()
*/
public IProgressMonitor getProgressMonitor() {
return fProgressMonitor;
}
/*
* @see IReconcileStep#reconcile(IRegion)
*/
public final IReconcileResult[] reconcile(IRegion partition) {
IReconcileResult[] result= reconcileModel(null, partition);
if (!isLastStep()) {
fNextStep.setInputModel(getModel());
IReconcileResult[] nextResult= fNextStep.reconcile(partition);
return merge(result, convertToInputModel(nextResult));
}
return result;
}
/*
* @see IReconcileStep#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion, org.eclipse.jface.text.IRegion)
*/
public final IReconcileResult[] reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
IReconcileResult[] result= reconcileModel(dirtyRegion, subRegion);
if (!isLastStep()) {
fNextStep.setInputModel(getModel());
IReconcileResult[] nextResult= fNextStep.reconcile(dirtyRegion, subRegion);
return merge(result, convertToInputModel(nextResult));
}
return result;
}
/**
* Reconciles the model of this reconcile step. The
* result is based on the input model.
*
* @param dirtyRegion the document region which has been changed
* @param subRegion the sub region in the dirty region which should be reconciled
* @return an array with reconcile results
*/
abstract protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion, IRegion subRegion);
/**
* Adapts the given an array with reconcile results to
* this step's input model and returns it.
*
* @param inputResults an array with reconcile results
* @return an array with the reconcile results adapted to the input model
*/
protected IReconcileResult[] convertToInputModel(IReconcileResult[] inputResults) {
return inputResults;
}
/**
* Merges the two reconcile result arrays.
*
* @param results1 an array with reconcile results
* @param results2 an array with reconcile results
* @return an array with the merged reconcile results
*/
private IReconcileResult[] merge(IReconcileResult[] results1, IReconcileResult[] results2) {
if (results1 == null)
return results2;
if (results2 == null)
return results1;
// XXX: not yet performance optimized
Collection collection= new ArrayList(Arrays.asList(results1));
collection.addAll(Arrays.asList(results2));
return (IReconcileResult[])collection.toArray(new IReconcileResult[collection.size()]);
}
/*
* @see IProgressMonitor#isCanceled()
*/
protected final boolean isCanceled() {
return fProgressMonitor != null && fProgressMonitor.isCanceled();
}
/*
* @see IReconcileStep#setPreviousStep(IReconcileStep)
*/
public void setPreviousStep(IReconcileStep step) {
Assert.isNotNull(step);
Assert.isTrue(fPreviousStep == null);
fPreviousStep= step;
}
/*
* @see IReconcileStep#setInputModel(Object)
*/
public void setInputModel(IReconcilableModel inputModel) {
fInputModel= inputModel;
if (!isLastStep())
fNextStep.setInputModel(getModel());
}
/**
* Returns the reconcilable input model.
*
* @return the reconcilable input model.
*/
public IReconcilableModel getInputModel() {
return fInputModel;
}
/**
* Returns the reconcilable model.
*
* @return the reconcilable model
*/
abstract public IReconcilableModel getModel();
}