com.puppetlabs.geppetto.pp.dsl.ui.preferences.PPPreferencesHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.puppetlabs.geppetto.pp.dsl.ui.preferences.PPPreferencesHelper.java

Source

/**
 * Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
 * 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:
 *   Puppet Labs
 */
package com.puppetlabs.geppetto.pp.dsl.ui.preferences;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreInitializer;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.puppetlabs.geppetto.forge.model.Constants;
import com.puppetlabs.geppetto.forge.model.ModuleName;
import com.puppetlabs.geppetto.pp.dsl.target.PuppetTarget;
import com.puppetlabs.geppetto.pp.dsl.ui.builder.PPBuildJob;
import com.puppetlabs.geppetto.pp.dsl.ui.pptp.PptpTargetProjectHandler;
import com.puppetlabs.geppetto.pp.dsl.validation.IValidationAdvisor;
import com.puppetlabs.geppetto.pp.dsl.validation.ValidationPreference;

/**
 * A facade that helps with preference checking.
 * (The idea is to not litter the code with specifics about how preferences are stated, where they are stored etc.)
 * 
 */
@Singleton
public class PPPreferencesHelper implements IPreferenceStoreInitializer, IPropertyChangeListener {

    private class RebuildChecker extends Job {
        private boolean drainAndBuild;

        /**
         * The purpose of the RebuildChecker is to collect/aggregate events for validation preferences
         * to avoid having to issue multiple rebuilds for a set of changes.
         * This job reschedules itself.
         */
        RebuildChecker() {
            super("Puppet RebuildChecker");
            setSystem(true);
            this.setUser(false);
            drainAndBuild = false;
        }

        @Override
        protected IStatus run(IProgressMonitor monitor) {
            if (monitor.isCanceled())
                return Status.CANCEL_STATUS;
            if (problemChanges.peek() == null) {
                drainAndBuild = false;
                this.schedule(500);
                return Status.OK_STATUS;
            }
            // if one event found, wait 500ms and then drain queue and rebuild
            if (!drainAndBuild) {
                drainAndBuild = true;
                this.schedule(500);
                return Status.OK_STATUS;
            }
            drainAndBuild = false;

            if (monitor.isCanceled())
                return Status.CANCEL_STATUS;
            // drain the queue of everything pending
            List<String> drained = Lists.newArrayList();
            problemChanges.drainTo(drained);

            if (monitor.isCanceled())
                return Status.CANCEL_STATUS;

            // run a build
            PPBuildJob job = new PPBuildJob(workspace);
            job.schedule();
            this.schedule(1000);

            return Status.OK_STATUS;
        }

    }

    private int autoInsertOverrides = 0;

    private final static String OVERRIDE_AUTO_INSERT = "com.puppetlabs.geppetto.override.autoinsert";

    public final static int AUTO_INSERT_BRACKETS = 0x01;

    public final static int AUTO_INSERT_BRACES = 0x02;

    public final static int AUTO_INSERT_PARENTHESES = 0x04;

    public final static int AUTO_INSERT_COMMENT = 0x08;

    public final static int AUTO_INSERT_SQ = 0x10;

    public final static int AUTO_INSERT_DQ = 0x20;

    private IPreferenceStore store;

    @Inject
    private PptpTargetProjectHandler pptpHandler;

    private static final String defaultProjectPath = "lib/*:environments/$environment/*:manifests/*:modules/*"; //$NON-NLS-1$

    private static final String defaultPuppetEnvironment = "production"; //$NON-NLS-1$

    @Inject
    IWorkspace workspace;

    LinkedBlockingQueue<String> problemChanges;

    Job backgroundRebuildChecker;

    /**
     * IMPORTANT:
     * Add all preference that requires a rebuild when their value change.
     */
    private List<String> requiresRebuild = Lists.newArrayList(//
            PPPreferenceConstants.PUPPET_TARGET_VERSION, //
            PPPreferenceConstants.PUPPET_ENVIRONMENT, //
            PPPreferenceConstants.PUPPET_PROJECT_PATH, //
            PPPreferenceConstants.PROBLEM_INTERPOLATED_HYPHEN, //
            PPPreferenceConstants.PROBLEM_CIRCULAR_DEPENDENCY, //
            PPPreferenceConstants.PROBLEM_BOOLEAN_STRING, //
            PPPreferenceConstants.PROBLEM_MISSING_DEFAULT, //
            PPPreferenceConstants.PROBLEM_CASE_DEFAULT_LAST, //
            PPPreferenceConstants.PROBLEM_SELECTOR_DEFAULT_LAST, //

            PPPreferenceConstants.PROBLEM_UNQUOTED_RESOURCE_TITLE, //
            PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED, //
            PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED_VAR, //
            PPPreferenceConstants.PROBLEM_UNBRACED_INTERPOLATION, //
            PPPreferenceConstants.PROBLEM_ML_COMMENTS, //
            PPPreferenceConstants.PROBLEM_RTOL_RELATIONSHIP, //
            PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_STRING, //
            PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_TRUSTED, //
            PPPreferenceConstants.PROBLEM_ENSURE_NOT_FIRST //

    );

    private IPreferenceStoreAccess preferenceStoreAccess;

    public PPPreferencesHelper() {
        configureAutoInsertOverride();
    }

    private void configureAutoInsertOverride() {
        String propValue = System.getProperty(OVERRIDE_AUTO_INSERT, "0");

        try {
            autoInsertOverrides = Integer.parseInt(propValue);
        } catch (NumberFormatException e) {
            autoInsertOverrides = 0;
        }
    }

    public ValidationPreference getAssignmentToVariableNamedString() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_STRING));
    }

    public ValidationPreference getAssignmentToVariableNamedTrusted() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_TRUSTED));
    }

    public ValidationPreference getBooleansInStringForm() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_BOOLEAN_STRING));
    }

    public ValidationPreference getCaseDefaultShouldAppearLast() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_CASE_DEFAULT_LAST));
    }

    public ValidationPreference getcircularDependencyPreference() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_CIRCULAR_DEPENDENCY));
    }

    public ValidationPreference getDqStringNotRequired() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED));
    }

    public ValidationPreference getDqStringNotRequiredVar() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED_VAR));
    }

    public ValidationPreference getEnsureShouldAppearFirst() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_ENSURE_NOT_FIRST));
    }

    public String getForgeLogin() {
        return store.getString(PPPreferenceConstants.FORGE_LOGIN);
    }

    public String getForgeURI() {
        return store.getString(PPPreferenceConstants.FORGE_LOCATION);
    }

    public ValidationPreference getInterpolatedNonBraceEnclosedHypens() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_INTERPOLATED_HYPHEN));
    }

    public ValidationPreference getMissingDefaultInSwitch() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_MISSING_DEFAULT));
    }

    public ValidationPreference getMLCommentsValidationPreference() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_ML_COMMENTS));
    }

    public PuppetTarget getPuppetTarget() {
        String targetLiteral = store.getString(PPPreferenceConstants.PUPPET_TARGET_VERSION);

        // there never was a 2.8, but older preferences settings may still have this string, use 3.0 instead
        if ("2.8".equals(targetLiteral))
            targetLiteral = "3.0";

        try {
            return PuppetTarget.forLiteral(targetLiteral);
        } catch (IllegalArgumentException e) {
            return PuppetTarget.getDefault();
        }
    }

    private boolean getResourceSpecificBoolean(IResource r, String property) {
        // get project specific preference and use them if they are enabled
        IPreferenceStore store = preferenceStoreAccess.getContextPreferenceStore(r.getProject());
        return store.getBoolean(property);

    }

    public ValidationPreference getRightToLeftRelationships() {
        return ValidationPreference.fromString(store.getString(PPPreferenceConstants.PROBLEM_RTOL_RELATIONSHIP));
    }

    public boolean getSaveActionEnsureEndsWithNewLine() {
        return store.getBoolean(PPPreferenceConstants.SAVE_ACTION_ENSURE_ENDS_WITH_NL);
    }

    public boolean getSaveActionEnsureEndsWithNewLine(IResource r) {
        boolean projectSpecific = getResourceSpecificBoolean(r,
                PPPreferenceConstants.SAVE_ACTIONS_USE_PROJECT_SETTINGS);
        return projectSpecific
                ? getResourceSpecificBoolean(r, PPPreferenceConstants.SAVE_ACTION_ENSURE_ENDS_WITH_NL)
                : getSaveActionEnsureEndsWithNewLine();
    }

    public boolean getSaveActionFormat() {
        return store.getBoolean(PPPreferenceConstants.SAVE_ACTION_FORMAT);
    }

    public boolean getSaveActionFormat(IResource r) {
        boolean projectSpecific = getResourceSpecificBoolean(r,
                PPPreferenceConstants.SAVE_ACTIONS_USE_PROJECT_SETTINGS);
        return projectSpecific ? getResourceSpecificBoolean(r, PPPreferenceConstants.SAVE_ACTION_FORMAT)
                : getSaveActionFormat();
    }

    public boolean getSaveActionReplaceFunkySpaces() {
        return store.getBoolean(PPPreferenceConstants.SAVE_ACTION_REPLACE_FUNKY_SPACES);
    }

    public boolean getSaveActionReplaceFunkySpaces(IResource r) {
        boolean projectSpecific = getResourceSpecificBoolean(r,
                PPPreferenceConstants.SAVE_ACTIONS_USE_PROJECT_SETTINGS);
        return projectSpecific
                ? getResourceSpecificBoolean(r, PPPreferenceConstants.SAVE_ACTION_REPLACE_FUNKY_SPACES)
                : getSaveActionReplaceFunkySpaces();
    }

    public boolean getSaveActionTrimLines() {
        return store.getBoolean(PPPreferenceConstants.SAVE_ACTION_TRIM_LINES);
    }

    public boolean getSaveActionTrimLines(IResource r) {
        boolean projectSpecific = getResourceSpecificBoolean(r,
                PPPreferenceConstants.SAVE_ACTIONS_USE_PROJECT_SETTINGS);
        return projectSpecific ? getResourceSpecificBoolean(r, PPPreferenceConstants.SAVE_ACTION_TRIM_LINES)
                : getSaveActionTrimLines();
    }

    public ValidationPreference getSelectorDefaultShouldAppearLast() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_SELECTOR_DEFAULT_LAST));
    }

    public ValidationPreference getUnbracedInterpolation() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_UNBRACED_INTERPOLATION));
    }

    public ValidationPreference getUnquotedResourceTitles() {
        return ValidationPreference
                .fromString(store.getString(PPPreferenceConstants.PROBLEM_UNQUOTED_RESOURCE_TITLE));
    }

    synchronized public IValidationAdvisor.ComplianceLevel getValidationComplianceLevel() {
        return getPuppetTarget().getComplianceLevel();
    }

    @Override
    synchronized public void initialize(IPreferenceStoreAccess access) {
        // if already initialized
        if (store != null)
            return;
        preferenceStoreAccess = access;
        store = preferenceStoreAccess.getWritablePreferenceStore();
        store.setDefault(PPPreferenceConstants.AUTO_EDIT_STRATEGY, 0);
        store.setDefault(PPPreferenceConstants.AUTO_EDIT_COMPLETE_COMPOUND_BLOCKS, true);
        store.setDefault(PPPreferenceConstants.PUPPET_TARGET_VERSION, PuppetTarget.getDefault().getLiteral());
        store.setDefault(PPPreferenceConstants.PUPPET_PROJECT_PATH, defaultProjectPath);
        store.setDefault(PPPreferenceConstants.PUPPET_ENVIRONMENT, defaultPuppetEnvironment);
        store.setDefault(PPPreferenceConstants.FORGE_LOCATION, Constants.FORGE_SERVICE_BASE_URL);
        store.setDefault(PPPreferenceConstants.FORGE_LOGIN, ModuleName.safeOwner(System.getProperty("user.name")));

        store.setDefault(PPPreferenceConstants.PROBLEM_INTERPOLATED_HYPHEN,
                ValidationPreference.WARNING.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_CIRCULAR_DEPENDENCY,
                ValidationPreference.WARNING.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_BOOLEAN_STRING, ValidationPreference.WARNING.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_MISSING_DEFAULT, ValidationPreference.WARNING.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_STRING,
                ValidationPreference.WARNING.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_ASSIGNMENT_TO_VAR_NAMED_TRUSTED,
                ValidationPreference.WARNING.toString());

        // stylistic
        store.setDefault(PPPreferenceConstants.PROBLEM_CASE_DEFAULT_LAST, ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_SELECTOR_DEFAULT_LAST,
                ValidationPreference.IGNORE.toString());

        store.setDefault(PPPreferenceConstants.PROBLEM_UNQUOTED_RESOURCE_TITLE,
                ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED,
                ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_DQ_STRING_NOT_REQUIRED_VAR,
                ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_UNBRACED_INTERPOLATION,
                ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_ML_COMMENTS, ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_RTOL_RELATIONSHIP, ValidationPreference.IGNORE.toString());
        store.setDefault(PPPreferenceConstants.PROBLEM_ENSURE_NOT_FIRST, ValidationPreference.IGNORE.toString());

        // save actions
        store.setDefault(PPPreferenceConstants.SAVE_ACTION_ENSURE_ENDS_WITH_NL, false);
        store.setDefault(PPPreferenceConstants.SAVE_ACTION_TRIM_LINES, false);
        store.setDefault(PPPreferenceConstants.SAVE_ACTION_REPLACE_FUNKY_SPACES, false);
        store.setDefault(PPPreferenceConstants.SAVE_ACTION_FORMAT, false);

        autoInsertOverrides = (int) store.getLong(PPPreferenceConstants.AUTO_EDIT_STRATEGY);

        // Schedule the background job that makes rebuild after property changes more efficient
        // (Removes the need to run one rebuild per changing preference).
        problemChanges = new LinkedBlockingQueue<String>();
        backgroundRebuildChecker = new RebuildChecker();
        backgroundRebuildChecker.schedule();
        store.addPropertyChangeListener(this);

    }

    public boolean isAutoBraceInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_BRACES) == 0;
    }

    public boolean isAutoBracketInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_BRACKETS) == 0;
    }

    public boolean isAutoCompleteBlockWanted() {
        return store.getBoolean(PPPreferenceConstants.AUTO_EDIT_COMPLETE_COMPOUND_BLOCKS);
    }

    public boolean isAutoDqStringInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_DQ) == 0;
    }

    public boolean isAutoMLCommentInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_COMMENT) == 0;
    }

    public boolean isAutoParenthesisInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_PARENTHESES) == 0;
    }

    public boolean isAutoSqStringInsertWanted() {
        return (autoInsertOverrides & AUTO_INSERT_SQ) == 0;
    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        // System.err.println("Preference changed value: " + event.getProperty());
        if (PPPreferenceConstants.AUTO_EDIT_STRATEGY.equals(event.getProperty()))
            autoInsertOverrides = Integer.valueOf((String) event.getNewValue());

        // If pptp changes, recheck the workspace
        if (PPPreferenceConstants.PUPPET_TARGET_VERSION.equals(event.getProperty())) {
            pptpHandler.initializePuppetTargetProject();
            // problemChanges.offer(event.getProperty());
        }
        if (requiresRebuild.contains(event.getProperty()))
            problemChanges.offer(event.getProperty());
        // System.out.println("PPHelper gets event:" + event.getProperty());
    }

    /**
     * Stops the helper from checking for preference store changes and scheduling rebuilds.
     */
    public void stop() {
        store.removePropertyChangeListener(this);
        if (backgroundRebuildChecker == null)
            return;
        if (!backgroundRebuildChecker.cancel()) {
            // if not in cancelable state, poke it harder
            Thread t = backgroundRebuildChecker.getThread();
            t.interrupt();
            try {
                // must wait for *job* to die
                backgroundRebuildChecker.join();
            } catch (InterruptedException e) {
                // ok ok, I was interrupted when stopping... no need to make it worse...
                System.err.println("Interrupted");
            }
        }
    }

}