com.cb.eclipse.folding.java.calculation.AbstractBlockStrategy.java Source code

Java tutorial

Introduction

Here is the source code for com.cb.eclipse.folding.java.calculation.AbstractBlockStrategy.java

Source

/*******************************************************************************
 * Copyright (c) 2004 Coffee-Bytes.com and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/cpl.php
 * 
 * Contributors:
 *     Coffee-Bytes.com - initial API and implementation
 *******************************************************************************/
package com.cb.eclipse.folding.java.calculation;

import java.util.Set;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;

import com.cb.eclipse.folding.EnhancedPosition;
import com.cb.eclipse.folding.FoldingPlugin;
import com.cb.eclipse.folding.java.JavaPositionMetadata;
import com.cb.eclipse.folding.java.preferences.PreferenceKeys;
import com.cb.eclipse.folding.util.IntStack;

/**
 * A generic implementation of CalculationStrategy that processes based on block
 * identifiers (e.g. { and } ).
 * 
 * This class provides nested block handling capabilities by using stack
 * mathematics.
 * 
 * @author RJ
 */
public abstract class AbstractBlockStrategy extends AbstractCalculationStrategy {

    private IntStack braceStack = new IntStack();
    private boolean digestComments = false;

    private int lastValidOpener = -1;

    private CommentHelper helper;

    public AbstractBlockStrategy(boolean digestComments) {
        super();

        this.helper = new CommentHelper();

        this.digestComments = digestComments;

    }

    /**
     * Push left braces, pop right braces and calculate the distance in between
     * as a region.
     * 
     * @see com.cb.eclipse.folding.java.calculation.RegionCalculationStrategy#handle(int,
     *      int, int, org.eclipse.jdt.core.IJavaElement)
     */
    public void handle(int token, int start, int end, IJavaElement owner) throws JavaModelException {

        boolean collapseComments = FoldingPlugin.getPrefs().getBoolean(PreferenceKeys.COLLAPSE_COMMENT_BLOCKS);
        boolean collapseJavadoc = FoldingPlugin.getPrefs().getBoolean(PreferenceKeys.COLLAPSE_JAVADOCS);

        switch (token) {

        case ITerminalSymbols.TokenNameLBRACE: {
            pushBrace(start);
            helper.end();
            break;
        }
        case ITerminalSymbols.TokenNameRBRACE: {
            if (hasUsablePeer()) {

                int oldStart = popBrace();
                helper.end();
                if (shouldFold(owner, token)) {
                    boolean doCollapse = shouldCollapse(owner, token);
                    boolean shouldNegate = shouldFilterLastLine(owner, token);
                    addRegion(new EnhancedPosition(oldStart, end - oldStart,
                            new JavaPositionMetadata(false, shouldNegate, doCollapse, true, getClass().getName())));
                }
            } else {
                System.out.println("Bad brace found... omitting!");
            }

            break;
        }

        default: {
            if (digestComments)
                helper.handle(token, start, end, owner);

        }

        }

    }

    /**
     * Currently designed to process until EOF is hit.
     * 
     * @see com.cb.eclipse.folding.java.calculation.CalculationStrategy#keepProcessing(int)
     */
    public boolean keepProcessing(int nextToken) {
        return true;
    }

    /**
     * Push another left brace location on to the stack, and grow the left-brace
     * location stack if neccessary.
     * 
     * @param location
     */
    private void pushBrace(int location) {

        braceStack.push(location);
    }

    /**
     * Pop a left-brace location off of the stack.
     * 
     * @return a left brace location.
     */
    private int popBrace() {
        int location;
        if (isEmpty()) {
            location = lastValidOpener;
        } else {
            location = braceStack.pop();
            if (isEmpty()) {
                lastValidOpener = location;
            }
        }
        return location;

    }

    /**
     * Ensures that one way or another the brace being matched has a usable peer.
     * 
     * This may mean that in the case of mismatched braces we are looking for the broadest 
     * set of braces, or it may simply mean that it is looking for a matching brace.
     * @return
     */
    private boolean hasUsablePeer() {
        return !isEmpty() || lastValidOpener >= 0;
    }

    /**
     * Determine if we have any braces pushed on the stack.
     * 
     * @return
     */
    protected boolean isEmpty() {
        return braceStack.isEmpty();
    }

    protected int getLevel() {
        return braceStack.size();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.cb.eclipse.folding.calculation.RegionCalculationStrategy#result()
     */
    public Set result() throws JavaModelException {
        super.addAllRegions(helper.result());
        return super.result();
    }

    public abstract boolean shouldFold(IJavaElement owner, int token) throws JavaModelException;

    public abstract boolean shouldFilterLastLine(IJavaElement owner, int token) throws JavaModelException;

    public abstract boolean shouldCollapse(IJavaElement owner, int token) throws JavaModelException;
}