org.eclipse.wb.tests.designer.core.model.parser.AbstractJavaInfoRelatedTest.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wb.tests.designer.core.model.parser.AbstractJavaInfoRelatedTest.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Google, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Google, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.wb.tests.designer.core.model.parser;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import org.eclipse.wb.core.controls.CCombo3;
import org.eclipse.wb.core.model.JavaInfo;
import org.eclipse.wb.core.model.ObjectInfo;
import org.eclipse.wb.internal.core.model.JavaInfoUtils;
import org.eclipse.wb.internal.core.model.ObjectInfoVisitor;
import org.eclipse.wb.internal.core.model.creation.ConstructorCreationSupport;
import org.eclipse.wb.internal.core.model.creation.ThisCreationSupport;
import org.eclipse.wb.internal.core.model.description.ToolkitDescription;
import org.eclipse.wb.internal.core.model.description.ToolkitDescriptionJava;
import org.eclipse.wb.internal.core.model.generation.GenerationSettings;
import org.eclipse.wb.internal.core.model.generation.statement.block.BlockStatementGeneratorDescription;
import org.eclipse.wb.internal.core.model.property.GenericProperty;
import org.eclipse.wb.internal.core.model.property.GenericPropertyImpl;
import org.eclipse.wb.internal.core.model.property.Property;
import org.eclipse.wb.internal.core.model.property.accessor.ExpressionAccessor;
import org.eclipse.wb.internal.core.model.property.editor.AbstractTextPropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.ITextValuePropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.PropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.TextDialogPropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.TextDisplayPropertyEditor;
import org.eclipse.wb.internal.core.model.property.editor.complex.IComplexPropertyEditor;
import org.eclipse.wb.internal.core.model.property.table.PropertyTooltipProvider;
import org.eclipse.wb.internal.core.model.property.table.PropertyTooltipTextProvider;
import org.eclipse.wb.internal.core.model.variable.FieldUniqueVariableSupport;
import org.eclipse.wb.internal.core.model.variable.NamesManager;
import org.eclipse.wb.internal.core.model.variable.NamesManager.ComponentNameDescription;
import org.eclipse.wb.internal.core.model.variable.VariableSupport;
import org.eclipse.wb.internal.core.model.variable.description.LocalUniqueVariableDescription;
import org.eclipse.wb.internal.core.preferences.IPreferenceConstants;
import org.eclipse.wb.internal.core.utils.IAdaptable;
import org.eclipse.wb.internal.core.utils.StringUtilities;
import org.eclipse.wb.internal.core.utils.ast.AstEditor;
import org.eclipse.wb.internal.core.utils.ast.AstNodeUtils;
import org.eclipse.wb.internal.core.utils.ast.StatementTarget;
import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
import org.eclipse.wb.internal.core.utils.state.EditorState;
import org.eclipse.wb.internal.core.utils.state.EditorState.BadNodeInformation;
import org.eclipse.wb.internal.core.utils.state.EditorState.BadNodesCollection;
import org.eclipse.wb.internal.core.utils.state.EditorWarning;
import org.eclipse.wb.tests.designer.core.AbstractJavaTest;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Abstract test that works with {@link JavaInfo}, but does not parses them directly, as opposed to
 * {@link AbstractJavaInfoTest}.
 * 
 * @author scheglov_ke
 */
public abstract class AbstractJavaInfoRelatedTest extends AbstractJavaTest {
    ////////////////////////////////////////////////////////////////////////////
    //
    // Configuration
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * Configures given {@link ToolkitDescription} for tests.
     */
    public static void configureDefaults(ToolkitDescriptionJava toolkit) {
        IPreferenceStore preferences = toolkit.getPreferences();
        // variable name
        preferences.setValue(IPreferenceConstants.P_VARIABLE_TEXT_MODE,
                IPreferenceConstants.V_VARIABLE_TEXT_MODE_NEVER);
        preferences.setToDefault(IPreferenceConstants.P_VARIABLE_TEXT_TEMPLATE);
        preferences.setToDefault(IPreferenceConstants.P_VARIABLE_TEXT_WORDS_LIMIT);
        preferences.setToDefault(IPreferenceConstants.P_VARIABLE_IN_COMPONENT);
        NamesManager.setNameDescriptions(toolkit, ImmutableList.<ComponentNameDescription>of());
        // please, always use in tests default settings
        {
            GenerationSettings generationSettings = toolkit.getGenerationSettings();
            generationSettings.setDefaultDeduceSettings(false);
            generationSettings.setDeduceSettings(false);
            generationSettings.setDefaultStatement(BlockStatementGeneratorDescription.INSTANCE);
            generationSettings.setDefaultVariable(LocalUniqueVariableDescription.INSTANCE);
            generationSettings.setStatement(generationSettings.getDefaultStatement());
            generationSettings.setVariable(generationSettings.getDefaultVariable());
        }
        preferences.setToDefault(GenerationSettings.P_FORCED_METHOD);
        preferences.setToDefault(FieldUniqueVariableSupport.P_PREFIX_THIS);
        // layouts
        preferences.setToDefault(IPreferenceConstants.P_LAYOUT_OF_PARENT);
        preferences.setToDefault(IPreferenceConstants.P_LAYOUT_DEFAULT);
        // direct edit
        preferences.setValue(IPreferenceConstants.P_GENERAL_DIRECT_EDIT_AFTER_ADD, false);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Utils
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * @return the {@link Statement} with given index's in {@link Block} that contains given
     *         {@link JavaInfo}.
     */
    protected static Statement getStatement(JavaInfo javaInfo, int... indexes) {
        ASTNode node = javaInfo.getCreationSupport().getNode();
        Block block;
        if (node instanceof MethodDeclaration) {
            assertInstanceOf(ThisCreationSupport.class, javaInfo.getCreationSupport());
            block = ((MethodDeclaration) node).getBody();
        } else {
            block = AstNodeUtils.getEnclosingBlock(node);
        }
        return getStatement(block, indexes);
    }

    /**
     * Asserts that given {@link StatementTarget} has same state as expected.
     */
    protected static void assertTarget(StatementTarget target, Block expectedBlock, Statement expectedStatement,
            boolean expectedBefore) {
        StatementTarget expectedTarget = new StatementTarget(expectedBlock, expectedStatement, expectedBefore);
        assertEquals(expectedTarget.toString(), target.toString());
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Hierarchy
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * Prints the active {@link AstEditor} hierarchy, ready to paste as arguments for
     * {@link #assertHierarchy(String...)}.
     */
    public static void printHierarchySource() {
        JavaInfo javaInfo = EditorState.getActiveJavaInfo();
        printHierarchySource(javaInfo);
    }

    /**
     * Asserts that active {@link AstEditor} has expected hierarchy.
     */
    public static void assertHierarchy(String... lines) {
        JavaInfo javaInfo = EditorState.getActiveJavaInfo();
        assertEquals(getSourceDQ(lines), printHierarchy(javaInfo));
    }

    /**
     * Creates string for hierarchy of {@link JavaInfo}'s starting from given root.
     */
    protected static String printHierarchy(JavaInfo root) {
        final StringBuffer buffer = new StringBuffer();
        root.accept(new ObjectInfoVisitor() {
            private int m_level;

            @Override
            public boolean visit(ObjectInfo objectInfo) throws Exception {
                buffer.append(StringUtils.repeat("\t", m_level));
                buffer.append(objectInfo.toString());
                buffer.append("\n");
                m_level++;
                return true;
            }

            @Override
            public void endVisit(ObjectInfo objectInfo) throws Exception {
                m_level--;
            }
        });
        return buffer.toString();
    }

    /**
     * Creates source for {@link String}'s array for hierarchy of {@link JavaInfo}'s starting from
     * given root.
     */
    private static void printHierarchySource(JavaInfo root) {
        final StringBuffer buffer = new StringBuffer();
        root.accept(new ObjectInfoVisitor() {
            private int m_level;

            @Override
            public boolean visit(ObjectInfo objectInfo) throws Exception {
                buffer.append('"');
                buffer.append(StringUtils.repeat("  ", m_level));
                {
                    String line = objectInfo.toString();
                    line = line.replace('"', '\'');
                    buffer.append(StringUtilities.escapeJava(line));
                }
                buffer.append('"');
                buffer.append(",\n");
                m_level++;
                return true;
            }

            @Override
            public void endVisit(ObjectInfo objectInfo) throws Exception {
                m_level--;
            }
        });
        String result = buffer.toString();
        result = StringUtils.removeEnd(result, ",\n");
        System.out.println(result);
    }

    /**
     * @return the {@link JavaInfo} which has variable with given name.
     */
    public static <T extends JavaInfo> T getJavaInfoByName(final String name) throws Exception {
        final AtomicReference<T> result = new AtomicReference<T>();
        EditorState.getActiveJavaInfo().accept0(new ObjectInfoVisitor() {
            @Override
            @SuppressWarnings("unchecked")
            public void endVisit(ObjectInfo objectInfo) throws Exception {
                if (result.get() != null) {
                    return;
                }
                if (objectInfo instanceof JavaInfo) {
                    JavaInfo javaInfo = (JavaInfo) objectInfo;
                    if (isRequestedJavaInfo(javaInfo)) {
                        result.set((T) javaInfo);
                    }
                }
            }

            private boolean isRequestedJavaInfo(JavaInfo javaInfo) throws Exception {
                VariableSupport variable = javaInfo.getVariableSupport();
                // check name
                if (variable.hasName() && name.equals(variable.getName())) {
                    return true;
                }
                // check title
                try {
                    if (name.equals(variable.getTitle())) {
                        return true;
                    }
                } catch (Throwable e) {
                }
                // no
                return false;
            }
        });
        return result.get();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Editor
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * Prints result of {@link #getEditorLinesSource(AstEditor)} .
     */
    protected static void printEditorLinesSource() {
        AstEditor editor = EditorState.getActiveJavaInfo().getEditor();
        String[] lines = StringUtils.split(editor.getSource(), "\r\n");
        System.out.println(getLinesForSourceDQ(lines));
    }

    /**
     * Asserts that {@link EditorState} does not have any parse/refresh error or warnings.
     */
    protected static void assertNoErrors(JavaInfo javaInfo) {
        AstEditor editor = javaInfo.getEditor();
        EditorState editorState = EditorState.get(editor);
        // bad parser nodes
        {
            BadNodesCollection nodes = editorState.getBadParserNodes();
            if (!nodes.isEmpty()) {
                for (BadNodeInformation node : nodes.nodes()) {
                    System.out.println("------------------ bad parser node ------------------");
                    System.out.println(editor.getSource(node.getNode()));
                    node.getException().printStackTrace();
                }
                fail("No parser errors expected.");
            }
        }
        // bad refresh nodes
        {
            BadNodesCollection nodes = editorState.getBadRefreshNodes();
            if (!nodes.isEmpty()) {
                System.out.println("------------------ bad refresh node ------------------");
                for (BadNodeInformation node : nodes.nodes()) {
                    System.out.println(editor.getSource(node.getNode()));
                    node.getException().printStackTrace();
                }
                fail("No refresh errors expected.");
            }
        }
        // warnings
        if (!editorState.getWarnings().isEmpty()) {
            for (EditorWarning warning : editorState.getWarnings()) {
                System.out.println("------------------ warning ------------------");
                System.out.println(warning.getMessage());
                if (warning.getException() != null) {
                    warning.getException().printStackTrace();
                }
            }
            fail("No warnings expected.");
        }
    }

    /**
     * Removes liens which start with "// filler".
     */
    protected static String[] removeFillerLines(String... lines) {
        while (lines.length != 0 && lines[0].startsWith("// filler")) {
            lines = (String[]) ArrayUtils.remove(lines, 0);
        }
        return lines;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Creation
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * @return the new instance of {@link JavaInfo} for given fully qualified class name.
     */
    public static <T extends JavaInfo> T createJavaInfo(String componentClassName) throws Exception {
        return createJavaInfo(componentClassName, null);
    }

    /**
     * @return the new instance of {@link JavaInfo} for given fully qualified class name.
     */
    @SuppressWarnings("unchecked")
    public static <T extends JavaInfo> T createJavaInfo(String componentClassName, String creationId)
            throws Exception {
        AstEditor editor = EditorState.getActiveJavaInfo().getEditor();
        JavaInfo javaInfo = JavaInfoUtils.createJavaInfo(editor, componentClassName,
                new ConstructorCreationSupport(creationId, true));
        javaInfo.putArbitraryValue(JavaInfo.FLAG_MANUAL_COMPONENT, Boolean.TRUE);
        return (T) javaInfo;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Properties
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * @return the array of {@link ExpressionAccessor}'s for given {@link GenericProperty}.
     */
    protected static List<ExpressionAccessor> getGenericPropertyAccessors(GenericProperty property)
            throws Exception {
        return ((GenericPropertyImpl) property).getAccessors();
    }

    /**
     * @return sub {@link Property}'s of given Property with {@link IComplexPropertyEditor}.
     */
    protected static Property[] getSubProperties(Property property) throws Exception {
        return ((IComplexPropertyEditor) property.getEditor()).getProperties(property);
    }

    /**
     * @return {@link Property} with given name from array of {@link Property}'s.
     */
    protected static Property getPropertyByTitle(Property[] properties, String title) {
        for (int i = 0; i < properties.length; i++) {
            Property property = properties[i];
            if (title.equals(property.getTitle())) {
                return property;
            }
        }
        // not found
        return null;
    }

    /**
     * @return the text from {@link TextDisplayPropertyEditor} for given {@link Property}.
     */
    protected static String getPropertyText(Property property) throws Exception {
        return (String) ReflectionUtils.invokeMethod2(property.getEditor(), "getText", Property.class, property);
    }

    /**
     * Set value of {@link ITextValuePropertyEditor} using text.
     */
    protected static void setPropertyText(Property property, String text) throws Exception {
        ReflectionUtils.invokeMethod2(property.getEditor(), "setText", Property.class, String.class, property,
                text);
    }

    /**
     * @return the text of {@link PropertyTooltipTextProvider} that should implement given
     *         {@link IAdaptable}.
     */
    protected static String getPropertyTooltipText(IAdaptable adaptable, Property property) throws Exception {
        PropertyTooltipProvider provider = adaptable.getAdapter(PropertyTooltipProvider.class);
        assertInstanceOf(PropertyTooltipTextProvider.class, provider);
        PropertyTooltipTextProvider textProvider = (PropertyTooltipTextProvider) provider;
        return (String) ReflectionUtils.invokeMethod(textProvider,
                "getText(org.eclipse.wb.internal.core.model.property.Property)", property);
    }

    /**
     * @return the text for {@link AbstractTextPropertyEditor}.
     */
    public static String getTextEditorText(Property property) throws Exception {
        PropertyEditor editor = property.getEditor();
        return (String) ReflectionUtils.invokeMethod(editor,
                "getEditorText(org.eclipse.wb.internal.core.model.property.Property)", property);
    }

    /**
     * Updates {@link Property} by setting text for {@link AbstractTextPropertyEditor}.
     */
    public static void setTextEditorText(Property property, String text) throws Exception {
        PropertyEditor editor = property.getEditor();
        ReflectionUtils.invokeMethod(editor,
                "setEditorText(org.eclipse.wb.internal.core.model.property.Property,java.lang.String)", property,
                text);
    }

    /**
     * Opens dialog of {@link TextDialogPropertyEditor}.
     */
    protected static void openPropertyDialog(Property property) throws Exception {
        ReflectionUtils.invokeMethod(property.getEditor(),
                "openDialog(org.eclipse.wb.internal.core.model.property.Property)", property);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Combo property editor
    //
    ////////////////////////////////////////////////////////////////////////////
    private static final Shell TEST_COMBO_SHELL = new Shell();
    private static final CCombo3 TEST_COMBO = new CCombo3(TEST_COMBO_SHELL, SWT.NONE);

    /**
     * Fill combo with items.
     */
    protected static void addComboPropertyItems(Property property) {
        PropertyEditor propertyEditor = property.getEditor();
        String signature = "addItems(" + "org.eclipse.wb.internal.core.model.property.Property,"
                + "org.eclipse.wb.core.controls.CCombo3)";
        TEST_COMBO.removeAll();
        ReflectionUtils.invokeMethodEx(propertyEditor, signature, property, TEST_COMBO);
    }

    /**
     * @return items from combo.
     */
    protected static List<String> getComboPropertyItems() {
        List<String> items = Lists.newArrayList();
        int itemCount = TEST_COMBO.getItemCount();
        for (int i = 0; i < itemCount; i++) {
            items.add(TEST_COMBO.getItem(i));
        }
        return items;
    }

    /**
     * @return the selection index in combo.
     */
    protected static int getComboPropertySelection() {
        return TEST_COMBO.getSelectionIndex();
    }

    /**
     * Sets the selection index in combo, usually to use then
     * {@link #setComboPropertySelection(Property)} and validate result using
     * {@link #getComboPropertySelection()}.
     */
    protected static void setComboPropertySelection(int index) {
        TEST_COMBO.select(index);
    }

    /**
     * Sets selection which corresponds to the value of {@link Property}.
     */
    protected static void setComboPropertySelection(Property property) {
        PropertyEditor propertyEditor = property.getEditor();
        String signature = "selectItem(" + "org.eclipse.wb.internal.core.model.property.Property,"
                + "org.eclipse.wb.core.controls.CCombo3)";
        ReflectionUtils.invokeMethodEx(propertyEditor, signature, property, TEST_COMBO);
    }

    /**
     * Simulates user selection of item with given index, updates {@link Property}.
     */
    protected static void setComboPropertyValue(Property property, int index) {
        PropertyEditor propertyEditor = property.getEditor();
        String signature = "toPropertyEx(" + "org.eclipse.wb.internal.core.model.property.Property,"
                + "org.eclipse.wb.core.controls.CCombo3," + "int)";
        ReflectionUtils.invokeMethodEx(propertyEditor, signature, property, TEST_COMBO, index);
    }
}