package org.kie.eclipse.navigator.preferences;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;

import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;

public class JsonPreferenceStore implements IPreferenceStore {

	/** The JSON object that is acting as the store **/
	private JsonObject object;
	boolean dirty = false;

	/** Listeners on this store */
	private ListenerList fListeners= new ListenerList(ListenerList.IDENTITY);

	public JsonPreferenceStore(JsonObject object) {
		this.object = object;
	}

	/**
	 * {@inheritDoc}
	 */
	public void addPropertyChangeListener(IPropertyChangeListener listener) {
		fListeners.add(listener);
	}

	/**
	 * {@inheritDoc}
	 */
	public void removePropertyChangeListener(IPropertyChangeListener listener) {
		fListeners.remove(listener);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean contains(String name) {
		JsonValue value = object.get(name);
		return value!=null;
	}

	/**
	 * {@inheritDoc}
	 */
	public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
		firePropertyChangeEvent(this, name, oldValue, newValue);
	}

	/**
	 * Fires a property change event with the given source, property name, old and new value. Used
	 * when the event source should be different from this mockup preference store.
	 * @param source The event source
	 * @param name The property name
	 * @param oldValue The property's old value
	 * @param newValue The property's new value
	 */
	public void firePropertyChangeEvent(Object source, String name, Object oldValue, Object newValue) {
		PropertyChangeEvent event= new PropertyChangeEvent(source, name, oldValue, newValue);
		Object[] listeners= fListeners.getListeners();
		for (int i= 0; i < listeners.length; i++)
			((IPropertyChangeListener) listeners[i]).propertyChange(event);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean getBoolean(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean getDefaultBoolean(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public double getDefaultDouble(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public float getDefaultFloat(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public int getDefaultInt(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public long getDefaultLong(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public String getDefaultString(String name) {
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public double getDouble(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public float getFloat(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public int getInt(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public long getLong(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public String getString(String name) {
		JsonValue value = object.get(name);
		if (value!=null)
			return value.asString();
		return "";
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean isDefault(String name) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean needsSaving() {
		return dirty;
	}

	/**
	 * {@inheritDoc}
	 */
	public void putValue(String name, String value) {
		object.set(name, value);
		dirty = true;
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, double value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, float value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, int value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, long value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, String defaultObject) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDefault(String name, boolean value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setToDefault(String name) {
		setValue(name, getDefaultString(name));
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, double value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, float value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, int value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, long value) {
		throw new UnsupportedOperationException();
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, String value) {
		String oldValue = this.getString(name);
		putValue(name, value);
		firePropertyChangeEvent(name, oldValue, value);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setValue(String name, boolean value) {
		throw new UnsupportedOperationException();
	}

}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.guvnor.tools.actions;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

import org.eclipse.compare.CompareUI;
import org.eclipse.compare.ITypedElement;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.webdav.IResponse;
import org.guvnor.tools.Activator;
import org.guvnor.tools.utils.GuvnorMetadataProps;
import org.guvnor.tools.utils.GuvnorMetadataUtils;
import org.guvnor.tools.utils.PlatformUtils;
import org.guvnor.tools.utils.VersionChooserDialog;
import org.guvnor.tools.utils.webdav.IWebDavClient;
import org.guvnor.tools.utils.webdav.StreamProcessingUtils;
import org.guvnor.tools.utils.webdav.WebDavClientFactory;
import org.guvnor.tools.utils.webdav.WebDavException;
import org.guvnor.tools.utils.webdav.WebDavServerCache;
import org.guvnor.tools.views.model.ResourceHistoryEntry;

/**
 * Simple text-based compare editor input.
 */
public class CompareVersionAction implements IObjectActionDelegate {

    private IFile selectedFile;
    private GuvnorMetadataProps props;

    private IWorkbenchPart targetPart;

    private IWebDavClient client;

    public CompareVersionAction() {
        super();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
     */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        this.targetPart = targetPart;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
     */
    public void run(IAction action) {
        if (selectedFile == null
           || props == null
           || targetPart == null) {
            return;
        }
        VersionChooserDialog dialog =
            new VersionChooserDialog(targetPart.getSite().getShell(),
                                    selectedFile.getName(),
                                    getVersionEntries());
        if (dialog.open() == VersionChooserDialog.OK) {
            compareWithSelectedVersion(dialog.getSelectedEntry());
        }
    }

    private void compareWithSelectedVersion(ResourceHistoryEntry revision) {
        IResponse response = null;
        try {
            IWorkbenchPage page = targetPart.getSite().getPage();
            String leftContents = StreamProcessingUtils.getStreamContents(selectedFile.getContents());
            GuvnorResourceEdition left =
                new GuvnorResourceEdition(selectedFile.getName(),
                                         ITypedElement.TEXT_TYPE,
                                         leftContents, selectedFile.getCharset());
            response = client.getResourceVersionInputStream(props.getFullpath(), revision.getRevision());
            String rightContents = StreamProcessingUtils.getStreamContents(response.getInputStream());
            //Assuming UTF-8 for Guvnor resources...
            GuvnorResourceEdition right =
                new GuvnorResourceEdition(selectedFile.getName() + ", " + revision.getRevision(), //$NON-NLS-1$
                                         ITypedElement.TEXT_TYPE,
                                         rightContents, "UTF-8"); //$NON-NLS-1$
            CompareUI.openCompareEditorOnPage(new GuvnorCompareEditorInput(left, right), page);
        } catch (Exception e) {
            Activator.getDefault().displayError(IStatus.ERROR, e.getMessage(), e, true);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    Activator.getDefault().writeLog(IStatus.ERROR, ioe.getMessage(), ioe);
                }
            }
        }
    }

    private ResourceHistoryEntry[] getVersionEntries() {
        ResourceHistoryEntry[] entries = new ResourceHistoryEntry[0];
        IResponse response = null;
        try {
            client = WebDavServerCache.getWebDavClient(props.getRepository());
            if (client == null) {
                client = WebDavClientFactory.createClient(new URL(props.getRepository()));
                WebDavServerCache.cacheWebDavClient(props.getRepository(), client);
            }
            InputStream ins = null;
            try {
                response = client.getResourceVersions(props.getFullpath());
                ins = response.getInputStream();
            } catch (WebDavException wde) {
                if (wde.getErrorCode() != IResponse.SC_UNAUTHORIZED) {
                    // If not an authentication failure, we don't know what to do with it
                    throw wde;
                }
                boolean retry = PlatformUtils.getInstance().
                                    authenticateForServer(props.getRepository(), client);
                if (retry) {
                    response = client.getResourceVersions(props.getFullpath());
                    ins = response.getInputStream();
                }
            }
            if (ins != null) {
                Properties verProps = new Properties();
                verProps.load(ins);
                entries = GuvnorMetadataUtils.parseHistoryProperties(verProps);
            }
        } catch (Exception e) {
            Activator.getDefault().writeLog(IStatus.ERROR, e.getMessage(), e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    Activator.getDefault().writeLog(IStatus.ERROR, ioe.getMessage(), ioe);
                }
            }
        }
        return entries;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
     */
    public void selectionChanged(IAction action, ISelection selection) {
        // Reset state to default
        selectedFile = null;
        props = null;
        action.setEnabled(false);
        // See if we should enable for the selection
        try {
            if (selection instanceof IStructuredSelection) {
                IStructuredSelection sel = (IStructuredSelection)selection;
                if (sel.getFirstElement() instanceof IFile
                   && sel.size() == 1) {
                    props = GuvnorMetadataUtils.getGuvnorMetadata((IFile)sel.getFirstElement());
                    if (props != null) {
                        selectedFile = (IFile)sel.getFirstElement();
                        action.setEnabled(true);
                    }
                }
            }
        } catch (Exception e) {
            Activator.getDefault().writeLog(IStatus.ERROR, e.getMessage(), e);
        }
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors;

import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.ui.actions.ZoomComboContributionItem;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.editors.text.TextEditorActionContributor;
import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
import org.eclipse.ui.texteditor.ITextEditor;

/**
 * ActionContributors for DRLRuleEditor2
 *
 * Currently implements contributors to zoom feature at rete viewer.
 */
public class DRLRuleEditorActionContributor extends MultiPageEditorActionBarContributor {

    private TextEditorActionContributor contributor = new TextEditorActionContributor();

    private ZoomComboContributionItem   zitem;
    private ZoomOutAction2              zoomOut;
    private ZoomInAction2               zoomIn;

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.EditorActionBarContributor#init(org.eclipse.ui.IActionBars, org.eclipse.ui.IWorkbenchPage)
     */
    public void init(IActionBars bars,
                     IWorkbenchPage page) {
        contributor.init( bars );
        super.init( bars,
                    page );
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.MultiPageEditorActionBarContributor#setActivePage(org.eclipse.ui.IEditorPart)
     */
    public void setActivePage(IEditorPart activeEditor) {
        IActionBars bars = getActionBars();
        if ( activeEditor instanceof ITextEditor ) {
            if ( bars != null ) {
                contributor.setActiveEditor( activeEditor );
            }
        }
    }

    /**
     * In addition to @link org.eclipse.ui.part.MultiPageEditorActionBarContributor#setActiveEditor(org.eclipse.ui.IEditorPart)
     * it sets contribution items to DRLRuleEditor2 for later use when
     * multipageditor tabs are switched.
     */
    public void setActiveEditor(IEditorPart part) {
        super.setActiveEditor( part );
        if ( part instanceof DRLRuleEditor2 ) {
            DRLRuleEditor2 p = (DRLRuleEditor2) part;
            p.setZoomComboContributionItem( zitem );
            p.setZoomInAction( zoomIn );
            p.setZoomOutAction( zoomOut );
        }
    }

    /**
     * Adds Zoom-related contributions.
     *
     * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToToolBar(org.eclipse.jface.action.IToolBarManager)
     */
    public void contributeToToolBar(IToolBarManager toolBarManager) {
        super.contributeToToolBar( toolBarManager );
        toolBarManager.add( new Separator() );
        String[] zoomStrings = new String[]{ZoomManager.FIT_ALL, ZoomManager.FIT_HEIGHT, ZoomManager.FIT_WIDTH};

        zitem = new ZoomComboContributionItem( getPage(),
                                               zoomStrings );
        zitem.setZoomManager( null );
        zitem.setVisible( false );

        zoomIn = new ZoomInAction2();
        zoomIn.setEnabled( false );

        zoomOut = new ZoomOutAction2();
        zoomOut.setEnabled( false );

        toolBarManager.add( zitem );
        toolBarManager.add( zoomIn );
        toolBarManager.add( zoomOut );

    }

}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors.completion;

import static org.drools.compiler.compiler.DRLFactory.buildParser;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.regex.Pattern;

import org.drools.compiler.lang.DRLParser;
import org.drools.compiler.lang.DroolsEditorType;
import org.drools.compiler.lang.DroolsToken;
import org.drools.compiler.lang.Location;
import org.kie.internal.builder.conf.LanguageLevelOption;

/**
 * A utility class that invokes the DRLParser on some partial drl text, and
 * provides information back about the context of that parsed drl, such as a
 * location type, a dialect, and so on.
 */
public class CompletionContext {

    static final Pattern MVEL_DIALECT_PATTERN = Pattern.compile(
            ".*dialect\\s+\"mvel\".*", Pattern.DOTALL);

    static final Pattern JAVA_DIALECT_PATTERN = Pattern.compile(
            ".*dialect\\s+\"java\".*", Pattern.DOTALL);

    static final String MVEL_DIALECT = "mvel";
    static final String JAVA_DIALECT = "java";

    private LinkedList<Object> parserList;
    private int location;
    private int locationIndex;
    private String dialect;

    @SuppressWarnings("unchecked")
    public CompletionContext(String backText) {
        DRLParser parser = getParser(backText);

        try {
            parser.compilationUnit();
        } catch (Exception ex) {
        }
        parserList = parser.getEditorInterface().get(0).getContent();
        deriveLocation();
        determineDialect(backText);
    }

    public boolean isJavaDialect() {
        return JAVA_DIALECT.equalsIgnoreCase(dialect);
    }

    public boolean isMvelDialect() {
        return MVEL_DIALECT.equalsIgnoreCase(dialect);
    }

    public boolean isDefaultDialect() {
        return !isJavaDialect() && !isMvelDialect();
    }

    // note: this is a crude but reasonably fast way to determine the dialect,
    // especially when parsing incomplete rules
    private void determineDialect(String backText) {
        dialect = null;
        boolean mvel = MVEL_DIALECT_PATTERN.matcher(backText).matches();
        boolean java = JAVA_DIALECT_PATTERN.matcher(backText).matches();
        if (mvel) {
            dialect = MVEL_DIALECT;
        } else if (java) {
            dialect = JAVA_DIALECT;
        }
    }

    public Location getLocation() {
        Location location = new Location(this.location);
        switch (this.location) {
            case Location.LOCATION_LHS_INSIDE_CONDITION_START:
                int index = findToken("(", Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                if (index != -1) {
                    Object o = parserList.get(index - 1);
                    if (o instanceof DroolsToken) {
                        String className = ((DroolsToken) o).getText();
                        location.setProperty(Location.LOCATION_PROPERTY_CLASS_NAME, className);
                    }
                }
                String propertyName = null;
                if (index + 1 < parserList.size()) {
                    propertyName = "";
                }
                int i = index + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        propertyName += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_PROPERTY_PROPERTY_NAME, propertyName);
                break;
            case Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR:
                index = findToken("(", Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                if (index != -1) {
                    Object o = parserList.get(index - 1);
                    if (o instanceof DroolsToken) {
                        String className = ((DroolsToken) o).getText();
                        location.setProperty(Location.LOCATION_PROPERTY_CLASS_NAME, className);
                    }
                }
                propertyName = null;
                index = findTokenBack(Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                if (index != -1) {
                    if (index + 1 < locationIndex) {
                        propertyName = "";
                    }
                    i = index + 1;
                    while (i < locationIndex) {
                        Object o = parserList.get(i++);
                        if (o instanceof DroolsToken) {
                            String token = ((DroolsToken) o).getText();
                            if (":".equals(token)) {
                                propertyName = "";
                            } else {
                                propertyName += token;
                            }
                        } else {
                            break;
                        }
                    }
                    location.setProperty(Location.LOCATION_PROPERTY_PROPERTY_NAME, propertyName);
                }
                break;
            case Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT:
                int index1 = findToken("(", Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                int index2 = findTokenBack(Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR, locationIndex);
                int index3 = findTokenBack(Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                int index4 = findTokenBack(Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT, locationIndex);
                if (index1 != -1 && index2 != -1) {
                    Object o = parserList.get(index1 - 1);
                    if (o instanceof DroolsToken) {
                        String className = ((DroolsToken) o).getText();
                        location.setProperty(Location.LOCATION_PROPERTY_CLASS_NAME, className);
                    }
                }
                String operator = "";
                for (i = index2 + 1; i < locationIndex; i++) {
                    Object o = parserList.get(i);
                    if (o instanceof DroolsToken) {
                        operator += ((DroolsToken) o).getText();
                    }
                    if (index4 != -1 && i >= index4 ){
                    	break;
                    }
                    if (i < locationIndex - 1) {
                        operator += " ";
                    }
                }
                location.setProperty(Location.LOCATION_PROPERTY_OPERATOR, operator.trim());
                propertyName = null;
                if (index1 != -1) {
                    if (index3 + 1 < locationIndex - 1) {
                        propertyName = "";
                    }
                    i = index3 + 1;
                    while (i < locationIndex - 1) {
                        Object o = parserList.get(i++);
                        if (o instanceof DroolsToken) {
                            String token = ((DroolsToken) o).getText();
                            if (":".equals(token)) {
                                propertyName = "";
                            } else {
                                propertyName += token;
                            }
                        } else {
                            break;
                        }
                    }
                    location.setProperty(Location.LOCATION_PROPERTY_PROPERTY_NAME, propertyName);
                }
                break;
            case Location.LOCATION_LHS_INSIDE_CONDITION_END:
                index = findToken("(", Location.LOCATION_LHS_INSIDE_CONDITION_START, locationIndex);
                if (index != -1) {
                    Object o = parserList.get(index - 1);
                    if (o instanceof DroolsToken) {
                        String className = ((DroolsToken) o).getText();
                        location.setProperty(Location.LOCATION_PROPERTY_CLASS_NAME, className);
                    }
                }
                break;
            case Location.LOCATION_LHS_INSIDE_EVAL:
                String eval = "";
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        eval += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_EVAL_CONTENT, eval.trim());
                break;
            case Location.LOCATION_LHS_FROM:
                String from = null;
                if (locationIndex + 1 < parserList.size()) {
                    from = "";
                }
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        from += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_FROM_CONTENT, from);
                break;
            case Location.LOCATION_LHS_FROM_ACCUMULATE_INIT_INSIDE:
                from = "";
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        from += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_INIT_CONTENT, from);
                break;
            case Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION_INSIDE:
                from = "";
                index = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_INIT_INSIDE, locationIndex);
                index2 = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION, locationIndex);
                if (index != -1 && index2 != -1) {
                    for (i = index + 1; i < index2 - 3; i++) {
                        Object o = parserList.get(i);
                        if (o instanceof DroolsToken) {
                            from += ((DroolsToken) o).getText();
                        }
                    }
                    location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_INIT_CONTENT, from.trim());
                }
                from = "";
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        from += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_ACTION_CONTENT, from);
                break;
            case Location.LOCATION_LHS_FROM_ACCUMULATE_RESULT_INSIDE:
                from = "";
                index = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_INIT_INSIDE, locationIndex);
                index2 = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION, locationIndex);
                index3 = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION_INSIDE, locationIndex);
                index4 = findTokenBack(Location.LOCATION_LHS_FROM_ACCUMULATE_RESULT, locationIndex);
                if (index != -1 && index2 != -1) {
                    for (i = index + 1; i < index2 - 3; i++) {
                        Object o = parserList.get(i);
                        if (o instanceof DroolsToken) {
                            from += ((DroolsToken) o).getText();
                        }
                    }
                    location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_INIT_CONTENT, from.trim());
                }
                from = "";
                if (index3 != -1 && index4 != -1) {
                    for (i = index3 + 1; i < index4 - 3; i++) {
                        Object o = parserList.get(i);
                        if (o instanceof DroolsToken) {
                            from += ((DroolsToken) o).getText();
                        }
                    }
                    location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_ACTION_CONTENT, from);
                }
                from = "";
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        from += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_PROPERTY_FROM_ACCUMULATE_RESULT_CONTENT, from);
                break;
            case Location.LOCATION_RHS:
                String rhs = "";
                i = locationIndex + 1;
                int endLocationOfLast = Integer.MAX_VALUE - 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        DroolsToken token = (DroolsToken) o;
                        if (endLocationOfLast + 1 < token.getStartIndex()) {
                            rhs += " ";
                        }
                        rhs += token.getText();
                        endLocationOfLast = token.getStopIndex();
                    }
                }
                location.setProperty(Location.LOCATION_RHS_CONTENT, rhs);
                break;
            case Location.LOCATION_RULE_HEADER:
                String header = "";
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        header += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_HEADER_CONTENT, header);
                break;
            case Location.LOCATION_RULE_HEADER_KEYWORD:
                header = "";
                index = findTokenBack(Location.LOCATION_RULE_HEADER, locationIndex);
                if (index != -1) {
                    for (i = index + 1; i < locationIndex; i++) {
                        Object o = parserList.get(i);
                        if (o instanceof DroolsToken) {
                            header += ((DroolsToken) o).getText();
                        }
                    }
                }
                i = locationIndex + 1;
                while (i < parserList.size()) {
                    Object o = parserList.get(i++);
                    if (o instanceof DroolsToken) {
                        header += ((DroolsToken) o).getText();
                    }
                }
                location.setProperty(Location.LOCATION_HEADER_CONTENT, header.trim());
                break;
        }
        return location;
    }

    public String getRuleName() {
        if (parserList.size() >= 2) {
            Object o = parserList.get(1);
            if (o instanceof DroolsToken) {
                String name = ((DroolsToken) o).getText();
                if (name.startsWith("\"") && (name.endsWith("\""))) {
                    name = name.substring(1, name.length() - 1);
                }
                return name;
            }
        }
        return null;
    }

    /**
     * Returns the variables defined in the given rule (fragment).
     * The key is the name of the variable.
     * The value is a list of 2 String:
     *  - the first one is the class name of the variable
     *  - the second one is the property of the given class that defines the type of this variable,
     *    note that this property could be nested,
     *    if this property is null then the given class is the type of the variable
     */
    public Map<String, String[]> getRuleParameters() {
        Map<String, String[]> result = new HashMap<String, String[]>();
        int i = 0;
        int lastLocation = -1;
        for (Object o: parserList) {
            if (o instanceof DroolsToken) {
                DroolsToken token = (DroolsToken) o;
                if (DroolsEditorType.IDENTIFIER_VARIABLE.equals(token.getEditorType()) || DroolsEditorType.IDENTIFIER_PATTERN.equals(token.getEditorType())) {
                    String variableName = token.getText();
                    if (lastLocation == Location.LOCATION_LHS_BEGIN_OF_CONDITION) {
                        int j = i + 2;
                        String className = "";
                        while (j < parserList.size()) {
                            Object obj = parserList.get(j++);
                            if (obj instanceof DroolsToken) {
                                String s = ((DroolsToken) obj).getText();
                                if ("(".equals(s)) {
                                    result.put(variableName, new String[] { className, null });
                                    break;
                                } else {
                                    className += s;
                                }

                            }
                        }
                    } else if (lastLocation == Location.LOCATION_LHS_INSIDE_CONDITION_START) {
                        int index = findTokenBack(Location.LOCATION_LHS_BEGIN_OF_CONDITION, i);
                        int j = index + 3;
                        String className = "";
                        while (j < i) {
                            Object obj = parserList.get(j++);
                            if (obj instanceof DroolsToken) {
                                String s = ((DroolsToken) obj).getText();
                                if ("(".equals(s)) {
                                    break;
                                } else {
                                    className += s;
                                }

                            }
                        }
                        j = i + 2;
                        String propertyName = "";
                        while (j < parserList.size()) {
                            Object obj = parserList.get(j++);
                            if (obj instanceof DroolsToken) {
                                String s = ((DroolsToken) obj).getText();
                                if (",".equals(s) || ")".equals(s)) {
                                    result.put(variableName, new String[] { className, propertyName });
                                    break;
                                } else {
                                    propertyName += s;
                                }
                            } else {
                                result.put(variableName, new String[] { className, propertyName });
                            }
                        }
                    }
                }
            } else if (o instanceof Integer) {
                lastLocation = (Integer) o;
            }
            i++;
        }
        return result;
    }

    private int findToken(String token, int integer, int location) {
        int index = location - 1;
        while (index >= 0) {
            Object o = parserList.get(index);
            if (o instanceof DroolsToken) {
                if ("(".equals(((DroolsToken) o).getText())) {
                	if (getNextInteger(index) == integer){
                		return index;
                	}
//                    o = parserList.get(index + 1);
//                    if (o instanceof Integer) {
//                        if (integer == (Integer) o) {
//                            return index;
//                        }
//                    }
                }
            }
            index--;
        }
        return -1;
    }

    private int findTokenBack(int token, int location) {
        int index = location - 1;
        while (index >= 0) {
            Object o = parserList.get(index);
            if (o instanceof Integer) {
                if (token == (Integer) o) {
                    return index;
                }
            }
            index--;
        }
        return -1;
    }

    private int getNextInteger(int location) {
        int index = location;
        while (index >= 0) {
            Object o = parserList.get(index);
            if (o instanceof Integer) {
                return (Integer) o;
            }
            index++;
        }
        return -1;
    }

	private void deriveLocation() {
	    location = -1;
	    int i = 0;
	    for (Object object : parserList) {
	        if (object instanceof Integer) {
	            location = (Integer) object;
	            locationIndex = i;
	        }
	        i++;
	    }
	}

    private DRLParser getParser(final String text) {
    	// TODO: support different language levels
    	DRLParser parser = buildParser(text, LanguageLevelOption.DRL5);
    	parser.enableEditorInterface();
    	return parser;
    }

}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.utils;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringTokenizer;
import org.eclipse.webdav.Policy;
import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * Decodes a URL from an ASCII readable
 * URL that is safe for transport.
 *
 * @see URLEncoder
 */
public final class URLDecoder {

    private static final byte[] hexChars = {(byte) '0', //
            (byte) '1', //
            (byte) '2', //
            (byte) '3', //
            (byte) '4', //
            (byte) '5', //
            (byte) '6', //
            (byte) '7', //
            (byte) '8', //
            (byte) '9', //
            (byte) 'a', //
            (byte) 'b', //
            (byte) 'c', //
            (byte) 'd', //
            (byte) 'e', //
            (byte) 'f', //
            (byte) 'A', //
            (byte) 'B', //
            (byte) 'C', //
            (byte) 'D', //
            (byte) 'E', //
            (byte) 'F'};
    private static final byte[] hexCharValues = {(byte) ('0' - '0'), //
            (byte) ('1' - '0'), //
            (byte) ('2' - '0'), //
            (byte) ('3' - '0'), //
            (byte) ('4' - '0'), //
            (byte) ('5' - '0'), //
            (byte) ('6' - '0'), //
            (byte) ('7' - '0'), //
            (byte) ('8' - '0'), //
            (byte) ('9' - '0'), //
            (byte) ('a' - 'a' + 10), //
            (byte) ('b' - 'a' + 10), //
            (byte) ('c' - 'a' + 10), //
            (byte) ('d' - 'a' + 10), //
            (byte) ('e' - 'a' + 10), //
            (byte) ('f' - 'a' + 10), //
            (byte) ('A' - 'A' + 10), //
            (byte) ('B' - 'A' + 10), //
            (byte) ('C' - 'A' + 10), //
            (byte) ('D' - 'A' + 10), //
            (byte) ('E' - 'A' + 10), //
            (byte) ('F' - 'A' + 10)};

    /**
     * Prevents instances from being created.
     */
    private URLDecoder() {
        super();
    }

    /**
     * Decodes the given URL from an ASCII
     * readable URL that is safe for transport. Returns the
     * result.
     *
     * @return the result of decoding the given URL from an
     *         ASCII readable URL that is safe for
     *         transport
     */
    public static String decode(String url) {
        try {
            return decode(new URL(url)).toString();
        } catch (MalformedURLException e) {
            // ignore or log?
        }

        String file;
        String ref = null;

        int lastSlashIndex = url.lastIndexOf('/');
        int lastHashIndex = url.lastIndexOf('#');
        if ((lastHashIndex - lastSlashIndex > 1) && lastHashIndex < url.length() - 1) {
            file = url.substring(0, lastHashIndex);
            ref = url.substring(lastHashIndex + 1, url.length());
        } else {
            file = url;
        }

        return decode(file, ref);
    }

    /**
     * Decodes the file and reference parts of a URL from an
     * ASCII readable URL that is safe for
     * transport. Returns the result.
     *
     * @return the result of decoding the file and reference parts of a
     *         URL from an ASCII readable
     *         URL that is safe for transport
     */
    public static String decode(String file, String ref) {
        StringBuffer buf = new StringBuffer();
        StringTokenizer tokenizer = new StringTokenizer(file, "/", true); //$NON-NLS-1$

        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            if (token.equals("/")) { //$NON-NLS-1$
                buf.append(token);
            } else {
                buf.append(decodeSegment(token));
            }
        }

        if (ref != null) {
            buf.append('#');
            buf.append(decodeSegment(ref));
        }

        return buf.toString();
    }

    /**
     * Decodes the given URL from an ASCII
     * readable URL that is safe for transport. Returns the
     * result.
     *
     * @return the result of decoding the given URL from an
     *         ASCII readable URL that is safe for
     *         transport
     */
    public static URL decode(URL url) {
        String file = url.getFile();
        String ref = url.getRef();
        try {
            return new URL(url.getProtocol(), url.getHost(), url.getPort(), decode(file, ref));
        } catch (MalformedURLException e) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
        }
        return null;
    }

    public static String decodeSegment(String segment) {
        byte[] encodedBytes = segment.getBytes();
        byte[] decodedBytes = new byte[encodedBytes.length];
        int decodedLength = 0;

        for (int i = 0; i < encodedBytes.length; i++) {
            byte b = encodedBytes[i];
            try {
                if (b == '%') {
                    byte enc1 = encodedBytes[++i];
                    byte enc2 = encodedBytes[++i];
                    b = (byte) ((hexToByte(enc1) << 4) + hexToByte(enc2));
                }
                decodedBytes[decodedLength++] = b;
            } catch (ArrayIndexOutOfBoundsException e) {
                Assert.isTrue(false, Policy.bind("assert.decodeSegment")); //$NON-NLS-1$
            } catch (IllegalArgumentException e) {
                Assert.isTrue(false, Policy.bind("assert.decodeSegment")); //$NON-NLS-1$
            }
        }
        try {
            return new String(decodedBytes, 0, decodedLength, "UTF8"); //$NON-NLS-1$
        } catch (UnsupportedEncodingException exception) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
            // avoid compiler error
            return null;
        }
    }

    private final static byte hexToByte(byte ch) {
        for (int i = 0; i < hexChars.length; i++)
            if (hexChars[i] == ch)
                return hexCharValues[i];
        throw new IllegalArgumentException();
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.authentication;

import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * This class implements a BASE64 character encoder as specified in
 * RFC1521.
 */
public final class Base64Encoder {
    /**
     * Returns the BASE64 encoded String of the given data.
     *
     * @param data the bytes to be BASE64 encoded
     * @return     the BASE64 encoded String of the given data
     */
    public static String encode(byte[] data) {
        Assert.isNotNull(data);

        StringBuffer buf = new StringBuffer();

        byte b = 0;
        int bits = 2;

        for (int i = 0; i < data.length; ++i) {
            b = (byte) ((b | (data[i] >> bits)) & 0x003f);
            buf.append(encode(b));
            b = (byte) ((data[i] << 6 - bits) & 0x003f);
            bits += 2;
            if (bits == 8) {
                buf.append(encode((byte) (b & 0x003f)));
                b = 0;
                bits = 2;
            }
        }

        if (bits == 4) {
            buf.append(encode(b));
            buf.append("=="); //$NON-NLS-1$
        } else if (bits == 6) {
            buf.append(encode(b));
            buf.append('=');
        }

        return buf.toString();
    }

    private static char encode(byte b) {
        if (b >= 0 && b <= 25)
            return (char) (b + 65);
        if (b >= 26 && b <= 51)
            return (char) (b + 71);
        if (b >= 52 && b <= 61)
            return (char) (b - 4);
        if (b == 62)
            return '+';
        if (b == 63)
            return '/';
        return '=';
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.client;

import java.net.MalformedURLException;
import org.eclipse.webdav.*;
import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * Dav Clients implement the IServer interface
 * and represent a client's connection to a server.
 *

 * Note: This class/interface is part of an interim API that is still under
 * development and expected to change significantly before reaching stability.
 * It is being made available at this early stage to solicit feedback from pioneering
 * adopters on the understanding that any code that uses this API will almost
 * certainly be broken (repeatedly) as the API evolves.
 *

 */
public abstract class DAVClient implements IServer {

    protected WebDAVFactory davFactory = null;

    /**
     * Creates a new DAV client from a clone of the given DAV client.
     *
     * @param davClient the DAV client to clone
     */
    public DAVClient(DAVClient davClient) {
        davFactory = davClient.davFactory;
    }

    /**
     * Creates a new DAV client.
     *
     * @param davFactory
     */
    public DAVClient(WebDAVFactory davFactory) {
        Assert.isNotNull(davFactory);
        this.davFactory = davFactory;
    }

    /**
     * @see Object#clone()
     */
    protected abstract Object clone();

    public WebDAVFactory getDAVFactory() {
        return davFactory;
    }

    /**
     * Returns a new context that is based on the given context.
     *
     * @param userContext
     * @param locator
     *
     * @return a new context that is based on the given context
     */
    protected IContext newContext(IContext userContext, ILocator locator) throws MalformedURLException {
        Assert.isNotNull(userContext);
        Assert.isNotNull(locator);
        IContext context = davFactory.newContext(userContext);
        if (locator.getLabel() != null)
            context.setLabel(locator.getLabel());
        return context;
    }

    /**
     * Shut down the client for future use, and release any system resources associated with the
     * instance.  Callers should not expect the client to succeed with further API calls once the
     * client has been closed.
     */
    public void close() {
        // Default is to do nothing.
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.dsl.editor;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.drools.compiler.lang.dsl.AntlrDSLMappingEntry;
import org.drools.compiler.lang.dsl.DSLMappingEntry;
import org.drools.compiler.lang.dsl.DSLMappingFile;
import org.drools.compiler.lang.dsl.DSLTokenizedMappingFile;
import org.drools.compiler.lang.dsl.MappingError;
import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.builder.IDroolsModelMarker;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.FileEditorInput;

/**
 * This is the tablular DSL configuration editor.
 */
public class DSLEditor extends EditorPart {

    private Table          table;
    private TableViewer    tableViewer;
    private NLGrammarModel model;          //this is the model that does all the work (from drools-compiler)
    private boolean        dirty = false;  //editing or deleting will make it dirty
    private Text           exprText;       //for language expression
    private Text           mappingText;    //for target rule expression
    private Text           descriptionText; //just a comment field
    private Text           objText;        // for the object name
    private Combo          sortCombo;      // for the sort field

    public void doSave(IProgressMonitor monitor) {

        FileEditorInput input = (FileEditorInput) getEditorInput();
        File outputFile = input.getFile().getLocation().toFile();
        saveFile( monitor,
                  outputFile,
                  input );

    }

    private void saveFile(IProgressMonitor monitor,
                          File outputFile,
                          FileEditorInput input) {
        try {
            validate( input );

            FileWriter writer = new FileWriter( outputFile );
            DSLMappingFile.saveMapping( writer,
                                        model );

            makeClean();
            writer.close();
            input.getFile().getProject().refreshLocal( IResource.DEPTH_INFINITE,
                                                       monitor );
        } catch ( IOException e ) {
            throw new IllegalStateException( "Unable to save DSL configuration file. (IOException: " + e.getMessage() + ")" );
        } catch ( CoreException e ) {
            throw new IllegalStateException( "Unable to resync workbench after DSL save. (CoreException: " + e.getMessage() + ")" );
        }
    }

    @SuppressWarnings("unchecked")
    private void validate(FileEditorInput input) {
        removeProblemsFor( input.getFile() );
        List<MappingError> errs = new ArrayList<MappingError>();
        for (DSLMappingEntry item : model.getEntries()) {
            errs.addAll( item.getErrors() );
        }
        if ( errs.size() > 0 ) {
            for (MappingError mapEr : errs) {
                createMarker( input.getFile(),
                              mapEr.getMessage() + "  From [" + mapEr.getTemplateText() + "]",
                              -1 );
            }
        }
    }

    private void createMarker(final IResource res,
                              final String message,
                              final int lineNumber) {
        try {
            IWorkspaceRunnable r = new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                    IMarker marker = res.createMarker( IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER );
                    marker.setAttribute( IMarker.MESSAGE,
                                         message );
                    marker.setAttribute( IMarker.SEVERITY,
                                         IMarker.SEVERITY_WARNING );
                    marker.setAttribute( IMarker.LINE_NUMBER,
                                         lineNumber );
                }
            };
            res.getWorkspace().run( r,
                                    null,
                                    IWorkspace.AVOID_UPDATE,
                                    null );
        } catch ( CoreException e ) {
            DroolsEclipsePlugin.log( e );
        }
    }

    private void removeProblemsFor(IResource resource) {
        try {
            if ( resource != null && resource.exists() ) {
                resource.deleteMarkers( IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER,
                                        false,
                                        IResource.DEPTH_INFINITE );
            }
        } catch ( CoreException e ) {
            DroolsEclipsePlugin.log( e );
        }
    }

    void makeClean() {
        this.dirty = false;
        firePropertyChange( PROP_DIRTY );

    }

    public void doSaveAs() {
        // TODO Implement this.
    }

    public void init(IEditorSite site,
                     IEditorInput editorInput) throws PartInitException {
        setSite( site );
        setInput( editorInput );
        setVisibleName( editorInput );

        try {
            InputStream stream = null;
            if (editorInput instanceof FileEditorInput) {
                FileEditorInput input = (FileEditorInput) editorInput;
                stream = input.getFile().getContents();
            } else if (editorInput instanceof IStorageEditorInput) {
                IStorageEditorInput input = (IStorageEditorInput) editorInput;
                stream = input.getStorage().getContents();
            }

            model = new NLGrammarModel();
            DSLMappingFile file = new DSLTokenizedMappingFile();
            file.parseAndLoad( new InputStreamReader( stream ) );
            model.addEntries( file.getMapping().getEntries() );
            stream.close();

        } catch ( CoreException e ) {
            throw new IllegalStateException( "Unable to load DSL configuration file. (CoreException: " + e.getMessage() + ")" );
        } catch ( IOException e ) {
            throw new IllegalStateException( "Unabel to close stream fo DSL config file. (IOException: " + e.getMessage() + ")" );
        }

    }

    private void setVisibleName(IEditorInput input) {
        setPartName( input.getName() );
        setContentDescription( "Editing Domain specific language: [" + input.getName() + "]" );
    }

    public boolean isDirty() {
        return dirty;
    }

    /**
     * Sets the dirty flag, and notifies the workbench.
     */
    void makeDirty() {
        dirty = true;
        firePropertyChange( PROP_DIRTY );
    }

    public void sortModel() {
        if ( sortCombo.getSelectionIndex() == DSLMappingSorter.EXPRESSION ) {
            tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.EXPRESSION ) );
        } else if ( sortCombo.getSelectionIndex() == DSLMappingSorter.OBJECT ) {
            tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.OBJECT ) );
        } else if ( sortCombo.getSelectionIndex() == DSLMappingSorter.SCOPE ) {
            tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.SCOPE ) );
        } else if ( sortCombo.getSelectionIndex() == DSLMappingSorter.MAPPING ) {
            tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.MAPPING ) );
        }
    }

    public boolean isSaveAsAllowed() {
        // TODO implement SaveAs
        return false;
    }

    public void createPartControl(Composite parent) {

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_BOTH );
        parent.setLayoutData( gridData );

        // Set numColumns to 3 in the overall grid
        GridLayout layout = new GridLayout( 3,
                                            false );
        layout.marginWidth = 4;
        parent.setLayout( layout );

        //create the overall desc field (comments).
        createDescriptionField( parent );

        // create the table
        createTable( parent );

        // Create and setup the TableViewer
        createTableViewer();

        //set up the table "binding" with the model
        tableViewer.setContentProvider( new DSLContentProvider( tableViewer,
                                                                model ) );
        tableViewer.setLabelProvider( new DSLLabelProvider() );
        refreshModel();

        //setup the fields below the table
        createExpressionViewField( parent );
        createEditButton( parent );
        createMappingViewField( parent );
        createDeleteButton( parent );
        createObjectViewField( parent );
        createAddButton( parent );
        createSortField( parent );
        createSortButton( parent );
        createCopyButton( parent );

        //listeners on the table...
        createTableListeners();

    }

    /**
     * Setup table listeners for GUI events.
     */
    private void createTableListeners() {

        //setup views into current selected
        table.addSelectionListener( new SelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                populate();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                populate();
            }

            private void populate() {
                DSLMappingEntry selected = getCurrentSelected();
                exprText.setText( selected.getMappingKey() );
                mappingText.setText( selected.getMappingValue() );
                objText.setText( selected.getMetaData().getMetaData() == null ? "" : selected.getMetaData().getMetaData() );
            }

        } );

        //double click support
        table.addMouseListener( new MouseListener() {

            public void mouseDoubleClick(MouseEvent e) {
                showEditPopup();
            }

            public void mouseDown(MouseEvent e) {
            }

            public void mouseUp(MouseEvent e) {
            }

        } );

    }

    private void createDescriptionField(Composite parent) {
        Label descLbl = new Label( parent,
                                   SWT.NONE );
        descLbl.setText( "Description:" );
        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        descLbl.setLayoutData( gridData );

        descriptionText = new Text( parent,
                                    SWT.BORDER );
        descriptionText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
        descriptionText.setText( model.getDescription() == null ? "" : model.getDescription() );
        descriptionText.addModifyListener( new ModifyListener() {

            public void modifyText(ModifyEvent e) {
                String text = descriptionText.getText();
                if ( !text.equals( model.getDescription() ) ) {
                    model.setDescription( text );
                    makeDirty();
                }
            }

        } );
    }

    private void createMappingViewField(Composite parent) {
        Label mapping = new Label( parent,
                                   SWT.NONE );
        mapping.setText( "Mapping:" );
        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        mapping.setLayoutData( gridData );

        mappingText = new Text( parent,
                                SWT.BORDER );
        mappingText.setEditable( false );

        mappingText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
    }

    private void createExpressionViewField(Composite parent) {

        Label expr = new Label( parent,
                                SWT.NONE );
        expr.setText( "Expression:" );
        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        expr.setLayoutData( gridData );

        exprText = new Text( parent,
                             SWT.BORDER );
        exprText.setEditable( false );
        gridData = new GridData( GridData.FILL_HORIZONTAL );

        exprText.setLayoutData( gridData );

    }

    private void createObjectViewField(Composite parent) {

        Label obj = new Label( parent,
                               SWT.NONE );
        obj.setText( "Object:" );
        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        obj.setLayoutData( gridData );

        objText = new Text( parent,
                            SWT.BORDER );
        objText.setEditable( false );
        gridData = new GridData( GridData.FILL_HORIZONTAL );

        objText.setLayoutData( gridData );

    }

    private void createSortField(Composite parent) {
        Label sort = new Label( parent,
                                SWT.NONE );
        sort.setText( "Sort by:" );
        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        sort.setLayoutData( gridData );

        sortCombo = new Combo( parent,
                               SWT.READ_ONLY );
        sortCombo.add( "Object",
                       DSLMappingSorter.OBJECT );
        sortCombo.add( "Language Expression",
                       DSLMappingSorter.EXPRESSION );
        sortCombo.add( "Rule Language Mapping",
                       DSLMappingSorter.MAPPING );
        sortCombo.add( "Scope",
                       DSLMappingSorter.SCOPE );
        gridData = new GridData( GridData.FILL_HORIZONTAL );

        sortCombo.setLayoutData( gridData );
    }

    /** Refreshes the table do make sure it is up to date with the model. */
    private void refreshModel() {
        tableViewer.setInput( model );
    }

    private void createEditButton(Composite parent) {
        // Create and configure the "Add" button
        Button add = new Button( parent,
                                 SWT.PUSH | SWT.CENTER );
        add.setText( "Edit" );

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        add.setLayoutData( gridData );

        add.addSelectionListener( new SelectionAdapter() {

            // Add a task to the ExampleTaskList and refresh the view
            public void widgetSelected(SelectionEvent e) {
                showEditPopup();
            }

        } );
    }

    private void showEditPopup() {
        DSLMappingEntry selected = getCurrentSelected();
        if (selected != null) {
            MappingEditor editor = new MappingEditor( getSite().getShell() );
            editor.create();
            editor.getShell().setText( "Edit language mapping" );
            editor.setTitle( "Edit an existing language mapping item." );
            editor.setTitleImage( getTitleImage() );

            editor.setNLMappingItem( selected );

            editor.open();
            if ( !editor.isCancelled() ) {
                refreshModel();
                makeDirty();
                exprText.setText(selected.getMappingKey());
                mappingText.setText(selected.getMappingValue());
                objText.setText(selected.getMetaData().getMetaData() == null ? "" : selected.getMetaData().getMetaData());
            }
        }
    }

    private void createDeleteButton(Composite parent) {
        // Create and configure the "Add" button
        Button add = new Button( parent,
                                 SWT.PUSH | SWT.CENTER );
        add.setText( "Remove" );

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        add.setLayoutData( gridData );
        add.addSelectionListener( new SelectionAdapter() {
            // Add a task to the ExampleTaskList and refresh the view
            public void widgetSelected(SelectionEvent e) {
                for (DSLMappingEntry entry: getAllSelected()) {
                    model.removeEntry( entry );
                }
                refreshModel();
                makeDirty();
                exprText.setText( "" );
                mappingText.setText( "" );
                objText.setText( "" );
            }
        } );
    }

    private void createSortButton(Composite parent) {
        // Create and configure the "Add" button
        Button sort = new Button( parent,
                                  SWT.PUSH | SWT.CENTER );
        sort.setText( "Sort" );

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        sort.setLayoutData( gridData );
        sort.addSelectionListener( new SelectionAdapter() {
            // Add a task to the ExampleTaskList and refresh the view
            public void widgetSelected(SelectionEvent e) {
                sortModel();
                refreshModel();
                makeDirty();
            }

        } );
    }

    /**
     * Return the selected item from the table grid thingy.
     */
    private DSLMappingEntry getCurrentSelected() {
        return (DSLMappingEntry) ((IStructuredSelection) tableViewer.getSelection()).getFirstElement();
    }

    private List<DSLMappingEntry> getAllSelected() {
        List<DSLMappingEntry> result = new ArrayList<DSLMappingEntry>();
        for (Object e: ((IStructuredSelection) tableViewer.getSelection()).toList()) {
            result.add((DSLMappingEntry) e);
        }
        return result;
    }

    private void createAddButton(Composite parent) {
        // Create and configure the "Add" button
        Button add = new Button( parent,
                                 SWT.PUSH | SWT.CENTER );
        add.setText( "Add" );

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        add.setLayoutData( gridData );

        add.addSelectionListener( new SelectionAdapter() {

            // Add an item, should pop up the editor
            public void widgetSelected(SelectionEvent e) {

                DSLMappingEntry newItem = new AntlrDSLMappingEntry();

                MappingEditor editor = new MappingEditor( getSite().getShell() );//shell);
                editor.create();
                editor.getShell().setText( "New language mapping" );
                editor.setTitle( "Create a new language element mapping." );
                editor.setTitleImage( getTitleImage() );

                editor.setNLMappingItem( newItem );

                editor.open();
                if ( !editor.isCancelled() ) {
                    model.addEntry( newItem );
                    refreshModel();
                    makeDirty();
                }

            }
        } );
    }

    private void createCopyButton(Composite parent) {
        // Create and configure the "Add" button
        Button copy = new Button( parent,
                                  SWT.PUSH | SWT.CENTER );
        copy.setText( "Copy" );

        GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_BEGINNING );
        gridData.widthHint = 80;
        copy.setLayoutData( gridData );

        copy.addSelectionListener( new SelectionAdapter() {

            // Add an item, should pop up the editor
            public void widgetSelected(SelectionEvent e) {

                DSLMappingEntry curr = getCurrentSelected();
                if (curr != null) {
                    DSLMappingEntry newItem = new AntlrDSLMappingEntry( curr.getSection(),
                                                                          curr.getMetaData(),
                                                                          curr.getMappingKey(),
                                                                          curr.getMappingValue(),
                                                                          null,
                                                                          null);

                    MappingEditor editor = new MappingEditor( getSite().getShell() );//shell);
                    editor.create();
                    editor.getShell().setText( "New language mapping" );
                    editor.setTitle( "Create a new language element mapping from a copy." );
                    editor.setTitleImage( getTitleImage() );

                    editor.setNLMappingItem( newItem );

                    editor.open();
                    if ( !editor.isCancelled() ) {
                        model.addEntry( newItem );
                        refreshModel();
                        makeDirty();
                    }
                }
            }
        } );
    }

    /**
     * Create the viewer.
     */
    private void createTableViewer() {
        tableViewer = new TableViewer( table );
        tableViewer.setUseHashlookup( true );
        //following is if we want default sorting... my thought is no...
    }

    /**
     * Create the Table
     */
    private void createTable(Composite parent) {
        int style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.HIDE_SELECTION;

        table = new Table( parent,
                           style );

        GridData gridData = new GridData( GridData.FILL_BOTH );
        gridData.grabExcessVerticalSpace = true;
        gridData.horizontalSpan = 3;
        table.setLayoutData( gridData );

        table.setLinesVisible( true );
        table.setHeaderVisible( true );

        TableColumn column;

        //Expression col
        column = new TableColumn( table,
                                  SWT.LEFT,
                                  0 );
        column.setText( "Language Expression" );
        column.setWidth( 350 );
        // Add listener to column so sorted when clicked
        column.addSelectionListener( new SelectionAdapter() {

            public void widgetSelected(SelectionEvent e) {
                tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.EXPRESSION ) );
            }
        } );

        // 3rd column with task Owner
        column = new TableColumn( table,
                                  SWT.LEFT,
                                  1 );
        column.setText( "Rule Language Mapping" );
        column.setWidth( 200 );
        // Add listener to column so sorted when clicked
        column.addSelectionListener( new SelectionAdapter() {

            public void widgetSelected(SelectionEvent e) {
                tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.MAPPING ) );
            }
        } );

        // 4th column with task PercentComplete
        column = new TableColumn( table,
                                  SWT.LEFT,
                                  2 );
        column.setText( "Object" );
        column.setWidth( 80 );

        // 5th column with task PercentComplete
        column = new TableColumn( table,
                                  SWT.LEFT,
                                  3 );
        column.setText( "Scope" );
        column.setWidth( 80 );

        //  Add listener to column so tasks are sorted when clicked
        column.addSelectionListener( new SelectionAdapter() {

            public void widgetSelected(SelectionEvent e) {
                tableViewer.setSorter( new DSLMappingSorter( DSLMappingSorter.SCOPE ) );
            }
        } );

    }

    public void setFocus() {
    }

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

}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.client;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * A URLTable is a simple hashtable whose keys are
 * URLs. A URL key with a trailing slash is
 * considered by the table to be equal to the same URL
 * without a trailing slash.
 *

 * Note: This class/interface is part of an interim API that is still under
 * development and expected to change significantly before reaching stability.
 * It is being made available at this early stage to solicit feedback from pioneering
 * adopters on the understanding that any code that uses this API will almost
 * certainly be broken (repeatedly) as the API evolves.
 *

 */
public class URLTable {

    private Hashtable table;

    /**
     * A URLKey is an equality wrapper class for
     * URLs. The wrapper treats URLs with and
     * without a trailing slash as equal. The equals method
     * works with URLKeys, URLs, and
     * Strings.
     *

     * Note: This class/interface is part of an interim API that is still under
     * development and expected to change significantly before reaching stability.
     * It is being made available at this early stage to solicit feedback from pioneering
     * adopters on the understanding that any code that uses this API will almost
     * certainly be broken (repeatedly) as the API evolves.
     *

     */
    class URLKey {
        URL url;
        int hashCode = -1;

        /**
         * Creates a new URLKey from the given URL.
         *
         * @param url the URL to wrap
         */
        public URLKey(URL url) {
            this.url = url;
        }

        /**
         * Returns true if this URLKey is equal to the
         * given object. Returns false otherwise. The object may be
         * a URLKey, String, or URL.
         *
         * @param obj the object to compare with this URLKey
         * @return    a boolean indicating whether or not this
         *            URLKey is equal to the given object
         */
        public boolean equals(Object obj) {
            if (obj == null)
                return false;
            if (this == obj)
                return true;
            if (obj instanceof URLKey)
                return equals(((URLKey) obj).getURL());
            if (obj instanceof String) {
                try {
                    return equals(new URL((String) obj));
                } catch (MalformedURLException e) {
                    return false;
                }
            }
            if (!(obj instanceof URL))
                return false;
            if (url == (URL) obj)
                return true;
            URL url1 = URLTool.removeTrailingSlash(url);
            URL url2 = URLTool.removeTrailingSlash((URL) obj);
            return url1.equals(url2);
        }

        /**
         * Returns the URL that this URLKey wraps.
         *
         * @return the URL that this URLKey wraps
         */
        public URL getURL() {
            return url;
        }

        /**
         * Returns an integer suitable for indexing this URLKey in
         * a hash table.
         *
         * @return an integer suitable for hash table indexing
         */
        public int hashCode() {
            if (hashCode == -1)
                hashCode = URLTool.removeTrailingSlash(url).hashCode();
            return hashCode;
        }

        /**
         * Returns this URLKeys URL as a
         * String.
         *
         * @return a string
         */
        public String toString() {
            return url.toString();
        }
    } // end-class URLKey

    /**
     * Construct an empty URLTable.
     */
    public URLTable() {
        table = new Hashtable();
    }

    /**
     * Construct an empty URLTable with the given size.
     */
    public URLTable(int size) {
        table = new Hashtable(size);
    }

    /**
     * Returns the value to which the given URL is mapped to in the table. If
     * the given URL not mapped to any value, or is malformed, returns
     * null.
     *
     * @param url a URL as a String
     * @return    the value to which the given URL is mapped to in the table,
     *            or null
     * @throws    MalformedURLException if the given URL is malformed
     */
    public Object get(String url) throws MalformedURLException {
        Assert.isNotNull(url);
        return get(new URL(url));
    }

    /**
     * Returns the value to which the given URL is mapped to in
     * the table. If the given URL not mapped to any value,
     * returns null.
     *
     * @param url a URL
     * @return    the value to which the given URL is mapped to
     *            in the table, or null
     */
    public Object get(URL url) {
        Assert.isNotNull(url);
        return get(new URLKey(url));
    }

    /**
     * Returns the value to which the specified URL is mapped to in the
     * table. If the specified URL is not mapped to any value, returns
     * null.
     *
     * @param url a URLKey
     * @return    the value to which the specified URL is mapped to in the
     *            table, or null
     */
    private Object get(URLKey url) {
        Assert.isNotNull(url);
        return table.get(url);
    }

    /**
     * Returns an Enumeration over the keys in this
     * URLTable.
     *
     * @return an Enumeration over URLs
     */
    public Enumeration keys() {
        final Enumeration keys = table.keys();
        Enumeration e = new Enumeration() {
            public boolean hasMoreElements() {
                return keys.hasMoreElements();
            }

            public Object nextElement() {
                return ((URLKey) keys.nextElement()).getURL();
            }
        };
        return e;
    }

    /**
     * Maps the given URL to the given value in this table.
     *
     * @param url   a URL as a String
     * @param value an object
     * @throws      MalformedURLException if the given URL is malformed
     */
    public void put(String url, Object value) throws MalformedURLException {
        Assert.isNotNull(url);
        Assert.isNotNull(value);
        put(new URL(url), value);
    }

    /**
     * Maps the given URL to the given value in this table.
     *
     * @param url   a URL
     * @param value an object
     */
    public void put(URL url, Object value) {
        Assert.isNotNull(url);
        Assert.isNotNull(value);
        put(new URLKey(url), value);
    }

    /**
     * Maps the specified URL to the given value in this table.
     *
     * @param url   a URLKey
     * @param value an object
     */
    private void put(URLKey url, Object value) {
        Assert.isNotNull(url);
        Assert.isNotNull(value);
        // Remove the old entry so the url key is replaced
        if (table.get(url) != null)
            table.remove(url);
        table.put(url, value);
    }

    public void remove(String url) throws MalformedURLException {
        Assert.isNotNull(url);
        remove(new URL(url));
    }

    public void remove(URL url) {
        Assert.isNotNull(url);
        remove(new URLKey(url));
    }

    private void remove(URLKey url) {
        Assert.isNotNull(url);
        table.remove(url);
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors.completion;

import java.util.Collection;
import java.util.HashMap;

public class Node {
    private HashMap<String, Node> children = new HashMap<String, Node>();
    private Node parent = null;
    private String token;
    private int depth = 0;

    public Node(String name) {
        this.token = name;
    }

    /**
     * The method will create a new Node instance and try to add it as
     * a child node. If an Node with the same string token exists, the
     * method will return the existing node instead.
     * @param token
     * @return
     */
    public Node addToken(String token) {
        Node newnode = new Node(token);
        // set the depth first
        newnode.setDepth(depth + 1);
        // add the node as a child
        newnode = addChild(newnode);
        return newnode;
    }

    /**
     * if the string matches this node's token, the method will return
     * true. Otherwise it returns false.
     * @param input
     * @return
     */
    public boolean isMatch(String input) {
        return input.equals(token);
    }

    public boolean isMatch(Node n) {
        return this.token.equals(n.getToken());
    }

    /**
     * The method will check to see if a Node with the same string token
     * already exists. If it doesn't, it will add the token as a child and
     * return the same node.
     *
     * On the otherhand, if there is an existing Node for the same string
     * token, the method returns the existing Node instance.
     * @param n
     * @return
     */
    public Node addChild(Node n) {
        if (!this.children.containsKey(n.getToken())) {
            this.children.put(n.getToken(),n);
            n.setParent(this);
            return n;
        } else {
            return (Node)this.children.get(n.getToken());
        }
    }

    public void removeChild(Node n) {
        this.children.remove(n.getToken());
    }

    public Collection<Node> getChildren() {
        return this.children.values();
    }

    /**
     * The method will get the child matching the string token
     * @param token
     * @return
     */
    public Node getChild(String token) {
        return (Node)this.children.get(token);
    }

    public Node getParent() {
        return parent;
    }

    public void setParent(Node parent) {
        this.parent = parent;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public int getDepth() {
        return depth;
    }

    public void setDepth(int depth) {
        this.depth = depth;
    }

    public void clearChildren() {
        this.children.clear();
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.core;

import org.eclipse.core.resources.IFile;

/**
 * This represents a drools model element.  It is linked to its direct
 * parents and its children. If relevant, Drools model elements refer
 * to the file they are defined in and the offset and length of that
 * element in the file.
 */
public abstract class DroolsElement {

    public static final int RULESET = 0;
    public static final int PACKAGE = 1;
    public static final int RULE = 2;
    public static final int QUERY = 3;
    public static final int FUNCTION = 4;
    public static final int TEMPLATE = 5;
    public static final int EXPANDER = 6;
    public static final int GLOBAL = 7;
    public static final int IMPORT = 8;
    public static final int RULE_ATTRIBUTE = 9;
    public static final int PROCESS = 10;

    public static final int DEFAULT_RULE_GROUP = 11;
    public static final int ACTIVATION_GROUP = 12;
    public static final int AGENDA_GROUP = 13;
    public static final int RULEFLOW_GROUP = 14;

    protected static final DroolsElement[] NO_ELEMENTS = new DroolsElement[0];

    private DroolsElement parent;
    private IFile file;
    private int offset;
    private int length;

    protected DroolsElement(DroolsElement parent) {
        this.parent = parent;
    }

    public abstract int getType();

    public DroolsElement getParent() {
        return parent;
    }

    public abstract DroolsElement[] getChildren();

    public IFile getFile() {
        return file;
    }

    public int getOffset() {
        return offset;
    }

    public int getLength() {
        return length;
    }

    // These are helper methods for creating the model and should not
    // be used directly.  Use DroolsModelBuilder instead.

    void setFile(IFile file, int offset, int length) {
        this.file = file;
        this.offset = offset;
        this.length = length;
    }

}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors.rete.commands;

import org.drools.eclipse.reteoo.BaseVertex;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;

/**
 * A command to move a vertex.
 */
public class NodeSetConstraintCommand extends Command {

    /** Stores the new size and location. */
    private final Rectangle           newBounds;

    /** Stores the old size and location. */
    private Rectangle                 oldBounds;

    /** A request to move/resize an edit part. */
    private final ChangeBoundsRequest request;

    /** BaseVertex to manipulate. */
    private final BaseVertex          vertex;

    /**
     * Create a command that can resize and/or move a vertex.
     *
     * @param vertex the vertex to manipulate
     * @param req       the move request
     * @param newBounds the new location. size is ignored
     * @throws IllegalArgumentException if any of the parameters is null
     */
    public NodeSetConstraintCommand(BaseVertex vertex,
                                    ChangeBoundsRequest req,
                                    Rectangle newBounds) {
        if ( vertex == null || req == null || newBounds == null ) {
            throw new IllegalArgumentException();
        }
        this.vertex = vertex;
        this.request = req;
        this.newBounds = newBounds.getCopy();
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.commands.Command#canExecute()
     */
    public boolean canExecute() {
        Object type = request.getType();
        return (RequestConstants.REQ_MOVE.equals( type ) || RequestConstants.REQ_MOVE_CHILDREN.equals( type ));
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.commands.Command#execute()
     */
    public void execute() {
        oldBounds = new Rectangle( vertex.getLocation(),
                                   vertex.getSize() );
        redo();
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.commands.Command#redo()
     */
    public void redo() {
        vertex.setSize( newBounds.getSize() );
        vertex.setLocation( newBounds.getLocation() );
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.commands.Command#undo()
     */
    public void undo() {
        vertex.setSize( oldBounds.getSize() );
        vertex.setLocation( oldBounds.getLocation() );
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.kernel;

import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
import org.eclipse.webdav.IResponse;

/**
 * A Precondition represents some condition or collection of conditions
 * representing states of a resource. If the state of the resource does not
 * match any of the specified states in any of the conditions, then the
 * method must fail. Conditions in a Precondition are OR'd together while
 * ConditionFactors in a ConditionTerm are AND'ed.
 */
public class Precondition {

    private Vector conditions = new Vector();

    /**
     * Construct an empty Precondition. The client must add Conditions.
     */
    public Precondition() {
        super();
    }

    /**
     * Construct a Precondition by parsing the given If header as defined by
     * section 8.4 in the WebDAV spec.
     *
     * @param ifHeader the contents of a WebDAV If header
     */
    public Precondition(String ifHeader) throws WebDAVException {
        StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(ifHeader));
        // URI characters
        tokenizer.wordChars('!', '/');
        tokenizer.wordChars(':', '@');
        tokenizer.ordinaryChar('(');
        tokenizer.ordinaryChar(')');
        tokenizer.ordinaryChar('<');
        tokenizer.ordinaryChar('>');
        tokenizer.ordinaryChar('[');
        tokenizer.ordinaryChar(']');
        tokenizer.quoteChar('"');
        int token = 0;
        try {
            token = tokenizer.nextToken();
            switch (token) {
                case '<' :
                    while (token == '<') {
                        addCondition(Condition.create(tokenizer));
                        token = tokenizer.ttype;
                    }
                    break;
                case '(' :
                    while (token == '(') {
                        addCondition(Condition.create(tokenizer));
                        token = tokenizer.ttype;
                    }
                    break;
            }
            if (token != StreamTokenizer.TT_EOF)
                throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissing", String.valueOf(token), "EOF")); //$NON-NLS-1$ //$NON-NLS-2$

            if (!getConditions().hasMoreElements())
                throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseEmptyList", ifHeader)); //$NON-NLS-1$

        } catch (IOException exc) {
            // ignore or log?
        }
    }

    /**
     * Add a Condition to this Precondition. Conditions are OR'd together to
     * check for a matching resource.
     *
     * @param condition the Condition to add
     * @exception WebDAVException thrown if the precondition already contains this condition
     */
    public void addCondition(Condition condition) throws WebDAVException {
        // a Resource URI can only be specified once in a Precondition
        Enumeration conditions = getConditions();
        if (condition.getResourceURI() != null) {
            while (conditions.hasMoreElements()) {
                Condition existingCondition = (Condition) conditions.nextElement();
                if (existingCondition.getResourceURI() != null && existingCondition.getResourceURI().equals(condition.getResourceURI()))
                    throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMultipleSpecification", condition.getResourceURI())); //$NON-NLS-1$
            }
        }
        this.conditions.addElement(condition);
    }

    /**
     * Add a condition created from the given URI and state token. This is a
     * convenience method used primarily to create preconditions for lock tokens
     * that must be provided in the resource context for methods that update
     * the resource.
     *
     * @param resourceURI the URI of the resource the state token applies to. Null
     *     implicitly specifies the resource processing the request
     * @param stateToken the state token to match
     */
    public void addStateTokenCondition(String resourceURI, String stateToken) throws WebDAVException {
        Condition condition = new Condition(resourceURI);
        ConditionTerm term = new ConditionTerm();
        term.addConditionFactor(new StateToken(stateToken));
        condition.addConditionTerm(term);
        addCondition(condition);
    }

    /**
     * Construct a Precondition by parsing the given If header as defined by
     * section 9.4 in the WebDAV spec.
     *
     * @param ifHeader the contents of a WebDAV If header
     * @return the parser If header
     * @exception WebDAVException thrown if there is a syntax error in the If header
     */
    public static Precondition create(String ifHeader) throws WebDAVException {
        return new Precondition(ifHeader);
    }

    /**
     * Get the Conditions contained in this Precondition. At least one must match
     * in order for a valid match to occur.
     *
     * @return an Enumeration of Conditions
     */
    public Enumeration getConditions() {
        return conditions.elements();
    }

    /**
     * See if this Precondition contains a matching Condition.
     *
     * @param condition the condition to match
     * @return true if this precondition contains atleast one condition matching the given condition
     */
    public boolean matches(Condition condition) {
        boolean match = false;
        Enumeration conditions = getConditions();
        while (!match && conditions.hasMoreElements()) {
            Condition existingCondition = (Condition) conditions.nextElement();
            match = existingCondition.matches(condition);
        }
        return match;
    }

    /**
     * Return a String representation of this Precondition as defined by section 9.4
     * of the WebDAV Spec. The string is the value of an If header.
     *
     * @return a string representation of this precondition
     */
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        Enumeration conditions = getConditions();
        while (conditions.hasMoreElements()) {
            Condition condition = (Condition) conditions.nextElement();
            buffer.append(condition.toString());
            if (conditions.hasMoreElements())
                buffer.append(' ');
        }
        return buffer.toString();
    }
}