org.splevo.jamopp.refactoring.java.ifelse.IfStaticConfigClassField.java Source code

Java tutorial

Introduction

Here is the source code for org.splevo.jamopp.refactoring.java.ifelse.IfStaticConfigClassField.java

Source

/*******************************************************************************
 * Copyright (c) 2014
 * 
 * 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:
 *    Daniel Kojic - initial API and implementation and initial documentation
 *******************************************************************************/
package org.splevo.jamopp.refactoring.java.ifelse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.resource.Resource;
import org.emftext.language.java.classifiers.Class;
import org.emftext.language.java.commons.Commentable;
import org.emftext.language.java.expressions.AssignmentExpression;
import org.emftext.language.java.expressions.Expression;
import org.emftext.language.java.expressions.ExpressionsFactory;
import org.emftext.language.java.members.Field;
import org.emftext.language.java.members.MemberContainer;
import org.emftext.language.java.modifiers.Modifier;
import org.emftext.language.java.modifiers.ModifiersFactory;
import org.emftext.language.java.modifiers.Static;
import org.emftext.language.java.operators.OperatorsFactory;
import org.emftext.language.java.references.IdentifierReference;
import org.emftext.language.java.references.ReferencesFactory;
import org.emftext.language.java.statements.Block;
import org.emftext.language.java.statements.Condition;
import org.emftext.language.java.statements.ExpressionStatement;
import org.emftext.language.java.statements.StatementsFactory;
import org.splevo.jamopp.refactoring.java.JaMoPPFullyAutomatedVariabilityRefactoring;
import org.splevo.jamopp.refactoring.java.ifelse.util.IfElseRefactoringUtil;
import org.splevo.jamopp.refactoring.util.RefactoringUtil;
import org.splevo.jamopp.vpm.software.JaMoPPJavaSoftwareElement;
import org.splevo.vpm.realization.RealizationFactory;
import org.splevo.vpm.realization.VariabilityMechanism;
import org.splevo.vpm.software.SoftwareElement;
import org.splevo.vpm.variability.Variant;
import org.splevo.vpm.variability.VariationPoint;

import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * The code base class must contain all fields from the variants. Therefore, this refactoring merges
 * the fields from all variants into the base.
 */
public class IfStaticConfigClassField extends JaMoPPFullyAutomatedVariabilityRefactoring
        implements RequiresIfRefactoringUtil {

    private static final String REFACTORING_NAME = "IF with Static Configuration Class: Field";
    private static final String REFACTORING_ID = "org.splevo.jamopp.refactoring.java.ifelse.IfStaticConfigClassField";

    private final IfElseRefactoringUtil ifElseRefactoringUtil;

    /**
     * Constructs the refactoring.
     * 
     * @param ifElseRefactoringUtil
     *            The refactoring util to be used.
     */
    public IfStaticConfigClassField(IfElseRefactoringUtil ifElseRefactoringUtil) {
        this.ifElseRefactoringUtil = ifElseRefactoringUtil;
    }

    @Override
    public VariabilityMechanism getVariabilityMechanism() {
        VariabilityMechanism variabilityMechanism = RealizationFactory.eINSTANCE.createVariabilityMechanism();
        variabilityMechanism.setName(REFACTORING_NAME);
        variabilityMechanism.setRefactoringID(REFACTORING_ID);
        return variabilityMechanism;
    }

    @Override
    protected List<Resource> refactorFullyAutomated(VariationPoint variationPoint,
            Map<String, Object> refactoringOptions) {
        Map<String, List<Field>> fieldToFieldName = Maps.newHashMap();
        Map<String, List<Integer>> positionToFieldName = Maps.newHashMap();
        Map<String, List<Expression>> initialValuesToFieldName = new HashMap<String, List<Expression>>();
        Map<Expression, String> variantIDToInitialValue = new HashMap<Expression, String>();

        Class vpLocation = (Class) ((JaMoPPJavaSoftwareElement) variationPoint.getLocation()).getJamoppElement();

        fillMaps(variationPoint, fieldToFieldName, initialValuesToFieldName, variantIDToInitialValue,
                positionToFieldName);

        RefactoringUtil.deleteVariableMembersFromLeading(variationPoint);

        Block nonStaticBlock = StatementsFactory.eINSTANCE.createBlock();
        Block staticBlock = StatementsFactory.eINSTANCE.createBlock();
        staticBlock.getModifiers().add(ModifiersFactory.eINSTANCE.createStatic());

        for (String fieldName : fieldToFieldName.keySet()) {
            List<Field> fields = fieldToFieldName.get(fieldName);
            List<Expression> initialValues = initialValuesToFieldName.get(fieldName);
            List<Integer> fieldPositions = positionToFieldName.get(fieldName);

            Field field = Iterables.getLast(fields);
            int fieldPos = Iterables.getLast(fieldPositions);

            registerReplacement(fields, field);

            vpLocation.getMembers().add(fieldPos, field);

            if (initialValues.size() > 1) {
                RefactoringUtil.removeFinalIfApplicable(field);

                field.setInitialValue(null);

                for (Expression value : initialValues) {
                    String variantId = variantIDToInitialValue.get(value);

                    ExpressionStatement fieldAssignment = createFieldAssignment(field, value);

                    Condition condition = this.ifElseRefactoringUtil.createVariabilityCondition(variationPoint,
                            variantId);
                    Block ifBlock = (Block) condition.getStatement();
                    ifBlock.getStatements().add(fieldAssignment);

                    if (isStatic(field)) {
                        staticBlock.getStatements().add(condition);
                        registerVariantSpecificNewEObject(condition, variantId);
                    } else {
                        nonStaticBlock.getStatements().add(condition);
                        registerVariantSpecificNewEObject(condition, variantId);
                    }
                }
            }
        }
        if (staticBlock.getStatements().size() > 0) {
            vpLocation.getMembers().add(0, staticBlock);
        }
        if (nonStaticBlock.getStatements().size() > 0) {
            vpLocation.getMembers().add(0, nonStaticBlock);
        }

        ArrayList<Resource> resourceList = Lists.newArrayList(vpLocation.eResource());

        Optional<Resource> configClassResource = ifElseRefactoringUtil.createConfigurationClass(variationPoint,
                refactoringOptions);
        if (configClassResource.isPresent()) {
            resourceList.add(configClassResource.get());
        }

        return resourceList;
    }

    private ExpressionStatement createFieldAssignment(Field field, Expression value) {
        AssignmentExpression assignmentExpr = ExpressionsFactory.eINSTANCE.createAssignmentExpression();
        assignmentExpr.setValue(value);
        assignmentExpr.setAssignmentOperator(OperatorsFactory.eINSTANCE.createAssignment());
        IdentifierReference fieldRef = ReferencesFactory.eINSTANCE.createIdentifierReference();
        fieldRef.setTarget(field);
        assignmentExpr.setChild(fieldRef);
        ExpressionStatement expressionStatement = StatementsFactory.eINSTANCE.createExpressionStatement();
        expressionStatement.setExpression(assignmentExpr);
        return expressionStatement;
    }

    private boolean isStatic(Field field) {
        for (Modifier modifier : field.getModifiers()) {
            if (modifier instanceof Static) {
                return true;
            }
        }
        return false;
    }

    private void fillMaps(VariationPoint vp, Map<String, List<Field>> fieldToFieldName,
            Map<String, List<Expression>> initialValuesToFieldName, Map<Expression, String> variantIDToInitialValue,
            Map<String, List<Integer>> positionToFieldName) {
        for (Variant variant : vp.getVariants()) {
            for (SoftwareElement se : variant.getImplementingElements()) {
                Field field = (Field) ((JaMoPPJavaSoftwareElement) se).getJamoppElement();
                Field fieldCpy = clone(field);

                if (!fieldToFieldName.containsKey(fieldCpy.getName())) {
                    fieldToFieldName.put(fieldCpy.getName(), new ArrayList<Field>());
                }
                fieldToFieldName.get(fieldCpy.getName()).add(fieldCpy);

                int fieldPos = getFieldPosInContainer(field);
                if (!positionToFieldName.containsKey(fieldCpy.getName())) {
                    positionToFieldName.put(fieldCpy.getName(), new ArrayList<Integer>());
                }
                positionToFieldName.get(fieldCpy.getName()).add(fieldPos);

                if (!initialValuesToFieldName.containsKey(fieldCpy.getName())) {
                    initialValuesToFieldName.put(fieldCpy.getName(), new LinkedList<Expression>());
                }

                Expression initialValue = fieldCpy.getInitialValue();
                if (!containsExpression(initialValuesToFieldName.get(fieldCpy.getName()), initialValue)) {
                    initialValuesToFieldName.get(fieldCpy.getName()).add(initialValue);
                }

                variantIDToInitialValue.put(initialValue, variant.getId());
            }
        }
    }

    private boolean containsExpression(List<Expression> container, Expression expression) {
        for (Expression element : container) {
            if (RefactoringUtil.areEqual(element, expression)) {
                return true;
            }
        }
        return false;
    }

    private int getFieldPosInContainer(Field field) {
        MemberContainer fieldContainer = (MemberContainer) field.eContainer();
        int fieldPos;
        if (fieldContainer == null) {
            fieldPos = 0;
        } else {
            fieldPos = fieldContainer.getMembers().indexOf(field);
        }
        return fieldPos;
    }

    @Override
    public Diagnostic canBeAppliedTo(VariationPoint variationPoint) {
        Commentable jamoppElement = ((JaMoPPJavaSoftwareElement) variationPoint.getLocation()).getJamoppElement();

        boolean correctLocation = jamoppElement instanceof MemberContainer;
        boolean allImplementingElementsAreFields = RefactoringUtil.allImplementingElementsOfType(variationPoint,
                Field.class);
        boolean correctInput = correctLocation && allImplementingElementsAreFields;
        String error = "If with Static Configuration Class Field: ";
        if (!correctInput) {
            return new BasicDiagnostic(Diagnostic.ERROR, null, 0, error + "Wrong Input", null);
        }

        if (RefactoringUtil.hasConflictingFields(variationPoint)) {
            return new BasicDiagnostic(Diagnostic.ERROR, null, 0, error + "Has Conflicting Fields", null);
        }
        return new BasicDiagnostic(Diagnostic.OK, null, 0, "OK", null);
    }

    @Override
    public String getId() {
        return REFACTORING_ID;
    }

}