org.wso2.developerstudio.datamapper.diagram.custom.generator.DifferentLevelArrayMappingConfigGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.developerstudio.datamapper.diagram.custom.generator.DifferentLevelArrayMappingConfigGenerator.java

Source

/*
 * Copyright 2016 WSO2, Inc. (http://wso2.com)
 *
 * 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.wso2.developerstudio.datamapper.diagram.custom.generator;

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

import org.apache.commons.lang.StringUtils;
import org.wso2.developerstudio.datamapper.SchemaDataType;
import org.wso2.developerstudio.datamapper.diagram.custom.configuration.operator.DMOperatorTransformerFactory;
import org.wso2.developerstudio.datamapper.diagram.custom.configuration.operator.transformers.DMOperatorTransformer;
import org.wso2.developerstudio.datamapper.diagram.custom.exception.DataMapperException;
import org.wso2.developerstudio.datamapper.diagram.custom.model.DMVariable;
import org.wso2.developerstudio.datamapper.diagram.custom.model.DMVariableType;
import org.wso2.developerstudio.datamapper.diagram.custom.model.DataMapperDiagramModel;
import org.wso2.developerstudio.datamapper.diagram.custom.util.ScriptGenerationUtil;

/**
 * This class extends abstract class {@link AbstractMappingConfigGenerator} and
 * generates mapping configuration from a {@link DataMapperDiagramModel} for
 * simple same level record and array type schema's
 *
 */
public class DifferentLevelArrayMappingConfigGenerator extends AbstractMappingConfigGenerator {

    private static final String ROOT_TAG = "root";
    private static final int FIRST_ELEMENT_INDEX = 0;

    private static final String SCHEMA_ATTRIBUTE_PREFIX = "@";

    /**
     * 
     */
    private Map<String, Integer> forLoopBeanMap;

    /**
     * forLoopBeanList contains the list of forLoopBeans in the generated script
     */
    private List<ForLoopBean> forLoopBeanList;

    /**
     * This is the root/parent bean and it will not be under a for loop in the generated script. Every operation and for
     * loops should be under this rootBean
     */
    private ForLoopBean rootBean;

    private Map<String, Integer> outputArrayVariableForLoopMap;
    private Map<String, Integer> outputObjectVariableForLoopMap;

    @Override
    public String generateMappingConfig(DataMapperDiagramModel model) throws DataMapperException {
        initializeAlgorithmFields();
        List<MappingOperation> mappingOperationList = populateOperationListFromModel(model);
        String mainFunction = generateMainFunction(mappingOperationList, model);
        return mainFunction;
    }

    private void initializeAlgorithmFields() {
        forLoopBeanMap = new HashMap<>();
        outputArrayVariableForLoopMap = new HashMap<>();
        outputObjectVariableForLoopMap = new HashMap<>();
        forLoopBeanList = new ArrayList<>();
        rootBean = new ForLoopBean(ROOT_TAG, ROOT_TAG);
        rootBean.setParentIndex(-1);
        getForLoopBeanList().add(rootBean);
        getForLoopBeanMap().put(ROOT_TAG, 0);
    }

    private String generateMainFunction(List<MappingOperation> mappingOperationList, DataMapperDiagramModel model)
            throws DataMapperException {
        String inRoot = model.getInputRootName();
        String outRoot = model.getOutputRootName();
        StringBuilder functionBuilder = new StringBuilder();
        String ouputVariableRootName = model.getVariablesArray().get(FIRST_ELEMENT_INDEX).getName();
        functionBuilder.append(getMainFunctionDefinition(inRoot, outRoot, ouputVariableRootName));
        functionBuilder.append(getJSCommandsForOperations(mappingOperationList, model));
        functionBuilder.append(getFunctionReturnString(ouputVariableRootName));
        return functionBuilder.toString();
    }

    private String getJSCommandsForOperations(List<MappingOperation> mappingOperationList,
            DataMapperDiagramModel model) throws DataMapperException {
        Map<String, SchemaDataType> variableMap = model.getVariableTypeMap();
        int mappingOperationIndex = 0;
        StringBuilder functionBuilder = new StringBuilder();
        for (MappingOperation mappingOperation : mappingOperationList) {
            List<DMVariable> inputVariables = mappingOperation.getInputVariables();
            List<DMVariable> outputVariables = mappingOperation.getOutputVariables();
            List<Integer> operationForLoopBeansList = new ArrayList<>();
            List<String> operationElementsParentList = new ArrayList<>();
            for (DMVariable dmVariable : inputVariables) {
                String mostChildVariableName = "";
                if (DMVariableType.INTERMEDIATE.equals(dmVariable.getType())
                        || DMVariableType.OUTPUT.equals(dmVariable.getType())) {
                    List<DMVariable> variableArray = model.getVariablesArray();
                    int mostChildVariableIndex = getMostChildAssociatedVariableIndex(
                            model.getInputAdjList().get(dmVariable.getparentVariableOrOperationIndex()),
                            variableArray);
                    mostChildVariableName = variableArray.get(mostChildVariableIndex).getName();
                    dmVariable.setMostChildVariableIndex(mostChildVariableIndex);
                } else {
                    mostChildVariableName = dmVariable.getName();
                }
                String[] variableNameArray = mostChildVariableName.split("\\.");
                String variableName = "";
                String parentVariableName = "";
                String parentArrayVariable = "";
                boolean firstIteration = true;
                for (String nextName : variableNameArray) {
                    if (!firstIteration) {
                        parentVariableName = variableName.substring(0, variableName.length() - 1);
                    }
                    variableName += nextName;
                    if (variableMap.containsKey(variableName)) {
                        SchemaDataType variableType = variableMap.get(variableName);
                        if (SchemaDataType.ARRAY.equals(variableType)) {
                            if (forLoopBeanNotCreated(variableName)) {
                                int indexOfForLoopBean = addForLoopInToMap(variableName,
                                        new ForLoopBean("i_" + nextName, variableName));
                                addForLoopBeanIndexToParent(variableName, indexOfForLoopBean, parentArrayVariable);
                                parentArrayVariable = variableName;
                            } else {
                                parentArrayVariable = variableName;
                            }
                        } else if (ScriptGenerationUtil.isVariableTypePrimitive(variableType)) {
                            // leaf variable element
                        } else if (SchemaDataType.RECORD.equals(variableType)) {
                            // record variable element
                        } else {
                            throw new DataMapperException(
                                    "Unsupported schemaDataType in WSO2 Data Mapper found : " + variableType);
                        }
                    } else {
                        throw new IllegalArgumentException("Unknown variable name found : " + variableName);
                    }
                    variableName += ".";
                    firstIteration = false;
                }
                // add most parent array for operationForLoopBeansList
                if (StringUtils.isEmpty(parentArrayVariable)) {
                    // root bean value
                    operationForLoopBeansList.add(0);
                } else {
                    operationForLoopBeansList.add(getForLoopBeanMap().get(parentArrayVariable));
                }
                // add parent Element of the variable to
                // operationElementsParentList
                operationElementsParentList.add(parentVariableName);
            }
            // validate the for loop beans of the variables. They should be in
            // one branch.
            int indexOfMostInnerForLoopBean = -1;
            if (isValidOperationWithInputVariables(operationElementsParentList)) {
                indexOfMostInnerForLoopBean = getMostInnerForLoopBeanFromList(operationForLoopBeansList);
            }
            // find the most inner for loop bean to assign this operation
            getForLoopBeanList().get(indexOfMostInnerForLoopBean).getOperationList().add(mappingOperationIndex);
            mappingOperationIndex++;
            for (DMVariable outputVariable : outputVariables) {
                if (DMVariableType.INTERMEDIATE.equals(outputVariable.getType())) {
                    functionBuilder.append("var " + outputVariable.getName() + " = [];");
                    functionBuilder.append("\n");
                } else if (DMVariableType.OUTPUT.equals(outputVariable.getType())) {
                    updateOutputVariableForLoopMap(outputVariable, variableMap, indexOfMostInnerForLoopBean);
                }
            }
        }
        // All operations are now assign to ForLoopBean map. Transform
        // forLoopBean map for JS script.
        functionBuilder
                .append(transformForLoopBeansToJS(getRootBean(), mappingOperationList, model.getVariableTypeMap()));
        return functionBuilder.toString();
    }

    private void updateOutputVariableForLoopMap(DMVariable outputVariable, Map<String, SchemaDataType> variableMap,
            int indexOfMostInnerForLoopBean) throws DataMapperException {
        String outputVariableName = outputVariable.getName();
        String[] variableNameArray = outputVariableName.split("\\.");
        String variableName = "";
        String parentVariableName = "";
        String parentArrayVariable = "";
        boolean firstIteration = true;
        int previousForLoopIndex = 0;
        int previousObjectForLoopIndex = 0;
        for (String nextName : variableNameArray) {
            if (!firstIteration) {
                parentVariableName = variableName.substring(0, variableName.length() - 1);
            }
            variableName += nextName;
            if (variableMap.containsKey(variableName)) {
                SchemaDataType variableType = variableMap.get(variableName);
                if (SchemaDataType.ARRAY.equals(variableType)) {
                    if (!outputArrayVariableForLoopMap.containsKey(variableName)) {
                        int targetForLoopIndex = getParentForLoopBeanIndex(previousForLoopIndex,
                                indexOfMostInnerForLoopBean);
                        outputArrayVariableForLoopMap.put(variableName, targetForLoopIndex);
                        getForLoopBeanList().get(targetForLoopIndex).getArrayVariableListToInstantiate()
                                .add(variableName);
                        previousForLoopIndex = targetForLoopIndex;
                    } else {
                        previousForLoopIndex = outputArrayVariableForLoopMap.get(variableName);
                    }
                } else if (ScriptGenerationUtil.isVariableTypePrimitive(variableType)) {
                    // leaf variable element
                } else if (SchemaDataType.RECORD.equals(variableType)) {
                    if (!outputObjectVariableForLoopMap.containsKey(variableName)) {
                        int targetForLoopIndex = previousForLoopIndex;
                        outputObjectVariableForLoopMap.put(variableName, targetForLoopIndex);
                        getForLoopBeanList().get(targetForLoopIndex).getObjectVariableListToInstantiate()
                                .add(variableName);
                        previousObjectForLoopIndex = targetForLoopIndex;
                    } else {
                        previousObjectForLoopIndex = outputObjectVariableForLoopMap.get(variableName);
                    }
                } else {
                    throw new DataMapperException(
                            "Unsupported schemaDataType in WSO2 Data Mapper found : " + variableType);
                }
            } else {
                throw new IllegalArgumentException("Unknown variable name found : " + variableName);
            }
            variableName += ".";
            firstIteration = false;
        }
    }

    /**
     * Method for retrieve the first child for loop of targetRootForLoopIndex which is a parent ForLoopBean of
     * mostChildForLoopBean.
     * 
     * @param targetRootForLoopIndex
     * @param mostChildForLoopBean
     * @return
     */
    private int getParentForLoopBeanIndex(int targetRootForLoopIndex, int mostChildForLoopBean) {
        ForLoopBean childForLoopBean = getForLoopBeanList().get(mostChildForLoopBean);
        int forLoopBeanIndex = mostChildForLoopBean;
        while (childForLoopBean.getParentIndex() != targetRootForLoopIndex) {
            forLoopBeanIndex = childForLoopBean.getParentIndex();
            childForLoopBean = getForLoopBeanList().get(forLoopBeanIndex);
            if (forLoopBeanIndex == rootBean.getParentIndex()) {
                throw new IllegalArgumentException("ForLoopBean "
                        + getForLoopBeanList().get(mostChildForLoopBean).getVariableName() + " is not a child of "
                        + getForLoopBeanList().get(mostChildForLoopBean).getVariableName());
            }
        }
        return forLoopBeanIndex;
    }

    private int getMostChildAssociatedVariableIndex(ArrayList<Integer> inputVariableIndexList,
            List<DMVariable> variableList) {
        String mostChildVariableName = "";
        int mostChildVariableIndex = -1;
        for (Integer variableIndex : inputVariableIndexList) {
            DMVariable variable = variableList.get(variableIndex);
            String variableName = "";
            if (DMVariableType.INTERMEDIATE.equals(variable.getType())) {
                variableName = variableList.get(variable.getMostChildVariableIndex()).getName();
                if (mostChildVariableName.split("\\.").length < variableName.split("\\.").length) {
                    mostChildVariableName = variableName;
                    mostChildVariableIndex = variable.getMostChildVariableIndex();
                }
            } else {
                variableName = variableList.get(variableIndex).getName();
                if (mostChildVariableName.split("\\.").length < variableName.split("\\.").length) {
                    mostChildVariableName = variableName;
                    mostChildVariableIndex = variableIndex;
                }
            }
        }
        return mostChildVariableIndex;
    }

    @SuppressWarnings("unchecked")
    private String transformForLoopBeansToJS(ForLoopBean forLoopBean, List<MappingOperation> mappingOperationList,
            Map<String, SchemaDataType> variableTypeMap) {
        StringBuilder functionBuilder = new StringBuilder();
        functionBuilder.append("\n");
        Stack<ForLoopBean> forLoopBeanParentStack = getParentForLoopBeanStack(forLoopBean);
        Stack<ForLoopBean> tempForLoopBeanParentStack = new Stack<ForLoopBean>();
        tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
        List<String> arrayTypeVariableList = getArrayTypeVariablesList(forLoopBean, mappingOperationList,
                variableTypeMap);
        // Initiating objects of Array type variables"
        functionBuilder
                .append(initiateArrayTypeVariables(forLoopBean, tempForLoopBeanParentStack, variableTypeMap));
        functionBuilder.append("\n");

        if (!ROOT_TAG.equals(forLoopBean.getVariableName())) {
            String forLoopVariableName = ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                    new DMVariable(forLoopBean.getVariableName(), "", DMVariableType.INPUT, SchemaDataType.ARRAY,
                            -1),
                    variableTypeMap, tempForLoopBeanParentStack);
            functionBuilder.append("for(" + forLoopBean.getIterativeName() + " in "
                    + forLoopVariableName.substring(0, forLoopVariableName.lastIndexOf("[")) + "){");
            functionBuilder.append("\n");
        }
        tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
        // Initiating arrays of the output variable going to instantiate in below for loop
        functionBuilder.append(
                initiateArrayTypeVariablesObjects(forLoopBean, tempForLoopBeanParentStack, variableTypeMap));
        functionBuilder.append("\n");

        tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
        // Initiating objects of the output variable
        functionBuilder
                .append(initiateRecordTypeVariables(forLoopBean, tempForLoopBeanParentStack, variableTypeMap));
        functionBuilder.append("\n");
        // Initiating Attribute objects of the output variable
        functionBuilder.append(getJSInitializationForArrayVariableObjects(arrayTypeVariableList));

        // call operations and nested for loops
        List<Integer> operationsInForLoopList = forLoopBean.getOperationList();
        for (Integer operationIndex : operationsInForLoopList) {
            functionBuilder.append(getJSCommandForOperation(mappingOperationList.get(operationIndex),
                    variableTypeMap, forLoopBean));
        }
        List<Integer> nestedForLoopList = forLoopBean.getNestedForLoopList();
        for (Integer nestedForLoopIndex : nestedForLoopList) {
            functionBuilder.append(transformForLoopBeansToJS(getForLoopBeanList().get(nestedForLoopIndex),
                    mappingOperationList, variableTypeMap));
        }

        if (!ROOT_TAG.equals(forLoopBean.getVariableName())) {
            functionBuilder.append("\n");
            functionBuilder.append("}");
            functionBuilder.append("\n");
        }
        return functionBuilder.toString();
    }

    private Object initiateRecordTypeVariables(ForLoopBean forLoopBean,
            Stack<ForLoopBean> tempForLoopBeanParentStack, Map<String, SchemaDataType> variableTypeMap) {
        StringBuilder functionBuilder = new StringBuilder();
        for (String variableName : forLoopBean.getObjectVariableListToInstantiate()) {
            functionBuilder.append("\n");
            variableName = ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                    new DMVariable(variableName, "", DMVariableType.INPUT, SchemaDataType.RECORD, -1),
                    variableTypeMap, tempForLoopBeanParentStack);
            functionBuilder.append(variableName + " = {};");
        }
        functionBuilder.append("\n");
        return functionBuilder.toString();
    }

    private String initiateArrayTypeVariablesObjects(ForLoopBean forLoopBean,
            Stack<ForLoopBean> tempForLoopBeanParentStack, Map<String, SchemaDataType> variableTypeMap) {
        StringBuilder functionBuilder = new StringBuilder();
        for (String variableName : forLoopBean.getArrayVariableListToInstantiate()) {
            functionBuilder.append("\n");
            variableName = ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                    new DMVariable(variableName, "", DMVariableType.INPUT, SchemaDataType.ARRAY, -1),
                    variableTypeMap, tempForLoopBeanParentStack);
            functionBuilder.append(variableName + " = {};");
        }
        functionBuilder.append("\n");
        return functionBuilder.toString();
    }

    private String initiateArrayTypeVariables(ForLoopBean forLoopBean,
            Stack<ForLoopBean> tempForLoopBeanParentStack, Map<String, SchemaDataType> variableTypeMap) {
        StringBuilder functionBuilder = new StringBuilder();
        for (String variableName : forLoopBean.getArrayVariableListToInstantiate()) {
            functionBuilder.append("\n");
            variableName = ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                    new DMVariable(variableName, "", DMVariableType.INPUT, SchemaDataType.ARRAY, -1),
                    variableTypeMap, tempForLoopBeanParentStack);
            functionBuilder.append(variableName.substring(0, variableName.lastIndexOf('[')) + " = [];");
        }
        functionBuilder.append("\n");
        return functionBuilder.toString();
    }

    private String getJSInitializationForArrayVariableObjects(List<String> arrayTypeVariableList) {
        StringBuilder functionBuilder = new StringBuilder();
        for (String variableName : arrayTypeVariableList) {
            functionBuilder.append("\n");
            functionBuilder.append(variableName + " = {};");
        }
        functionBuilder.append("\n");
        return functionBuilder.toString();
    }

    @SuppressWarnings("unchecked")
    private List<String> getArrayTypeVariablesList(ForLoopBean forLoopBean,
            List<MappingOperation> mappingOperationList, Map<String, SchemaDataType> variableTypeMap) {
        List<String> initializedVariableList = new ArrayList<>();
        Stack<ForLoopBean> forLoopBeanParentStack = getParentForLoopBeanStack(forLoopBean);
        Stack<ForLoopBean> tempForLoopBeanParentStack = new Stack<ForLoopBean>();
        tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
        for (int operationIndex : forLoopBean.getOperationList()) {
            MappingOperation mappingOperation = mappingOperationList.get(operationIndex);
            for (DMVariable outputVariable : mappingOperation.getOutputVariables()) {
                tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
                if (DMVariableType.OUTPUT.equals(outputVariable.getType())) {
                    String outputVariableName = outputVariable.getName();
                    String[] outputVariableArray = outputVariableName.split("\\.");
                    String fieldName = outputVariableArray[outputVariableArray.length - 1];
                    String variableName = removeLastElementNameFromVariable(outputVariableName);
                    if (variableTypeMap.containsKey(variableName)) {
                        if (fieldName.contains(SCHEMA_ATTRIBUTE_PREFIX) && ScriptGenerationUtil
                                .isVariableTypePrimitive(variableTypeMap.get(variableName))) {
                            String variableString = ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                                    outputVariable, variableTypeMap, tempForLoopBeanParentStack);
                            variableString = removeLastElementNameFromVariable(variableString);
                            if (!initializedVariableList.contains(variableString)) {
                                initializedVariableList.add(variableString);
                            }
                        }
                    } else {
                        throw new IllegalArgumentException(
                                "Illegal variable name found" + outputVariable.getName());
                    }
                }
            }
        }
        return initializedVariableList;
    }

    private String removeLastElementNameFromVariable(String variableString) {
        String targetVariable = variableString;
        if (variableString.contains(".")) {
            int lastElementIndex = variableString.lastIndexOf(".");
            targetVariable = variableString.substring(0, lastElementIndex);
        }
        return targetVariable;
    }

    @SuppressWarnings("unchecked")
    private String getJSCommandForOperation(MappingOperation mappingOperation,
            Map<String, SchemaDataType> variableTypeMap, ForLoopBean forLoopBean) {
        StringBuilder operationBuilder = new StringBuilder();
        List<DMVariable> outputVariables = mappingOperation.getOutputVariables();
        if (outputVariables.size() > 1) {
            operationBuilder.append("[ ");
        }
        Stack<ForLoopBean> forLoopBeanParentStack = getParentForLoopBeanStack(forLoopBean);
        Stack<ForLoopBean> tempForLoopBeanParentStack = new Stack<ForLoopBean>();
        tempForLoopBeanParentStack = (Stack<ForLoopBean>) forLoopBeanParentStack.clone();
        int numOfOutputVariables = outputVariables.size();
        for (int variableIndex = 0; variableIndex < numOfOutputVariables; variableIndex++) {
            operationBuilder.append(ScriptGenerationUtil.getPrettyVariableNameInForOperation(
                    outputVariables.get(variableIndex), variableTypeMap, tempForLoopBeanParentStack));
            if (variableIndex < (numOfOutputVariables - 1)) {
                operationBuilder.append(",");
            } else if (numOfOutputVariables > 1) {
                operationBuilder.append(" ] ");
            }
        }
        operationBuilder.append(" = ");
        DMOperatorTransformer operatorTransformer = DMOperatorTransformerFactory
                .getDMOperatorTransformer(mappingOperation.getOperation().getOperatorType());

        operationBuilder.append(
                operatorTransformer.generateScriptForOperation(DifferentLevelArrayMappingConfigGenerator.class,
                        mappingOperation.getInputVariables(), variableTypeMap, forLoopBeanParentStack));
        operationBuilder.append("\n");
        return operationBuilder.toString();
    }

    private Stack<ForLoopBean> getParentForLoopBeanStack(ForLoopBean forLoopBean) {
        Stack<ForLoopBean> parentForLoopStack = new Stack<>();
        if (forLoopBean.getParentIndex() < 0) {
            return parentForLoopStack;
        } else {
            parentForLoopStack = getParentForLoopBeanStack(getForLoopBeanList().get(forLoopBean.getParentIndex()));
            parentForLoopStack.push(forLoopBean);
            return parentForLoopStack;
        }
    }

    public ForLoopBean getRootBean() {
        return rootBean;
    }

    public void setRootBean(ForLoopBean rootBean) {
        this.rootBean = rootBean;
    }

    private boolean isValidOperationWithInputVariables(List<String> operationElementsParentList)
            throws DataMapperException {
        // parent variables should be in a same branch
        String mostChildParentName = operationElementsParentList.get(0);
        for (int i = 1; i < operationElementsParentList.size(); i++) {
            String parentName = operationElementsParentList.get(i);
            if (mostChildParentName.length() > parentName.length()) {
                checkTwoParentsInTheSameBranch(mostChildParentName, parentName);
            } else {
                checkTwoParentsInTheSameBranch(parentName, mostChildParentName);
                mostChildParentName = parentName;
            }
        }
        return true;
    }

    private void checkTwoParentsInTheSameBranch(String mostChildParentName, String parentName)
            throws DataMapperException {
        if (!mostChildParentName.startsWith(parentName)) {
            throw new DataMapperException(
                    "Cannot use varibales in different parent elements in different branches");
        }
    }

    private int getMostInnerForLoopBeanFromList(List<Integer> operationForLoopBeansList) {
        int mostChildForLoopIndex = operationForLoopBeansList.get(0);
        for (int i = 1; i < operationForLoopBeansList.size(); i++) {
            int thisForLoopBeanIndex = operationForLoopBeansList.get(i);
            if (getForLoopBeanList().get(mostChildForLoopIndex).getVariableName().length() < getForLoopBeanList()
                    .get(thisForLoopBeanIndex).getVariableName().length()) {
                mostChildForLoopIndex = thisForLoopBeanIndex;
            }
        }
        return mostChildForLoopIndex;
    }

    private void addForLoopBeanIndexToParent(String variableName, int indexOfForLoopBean, String parentVariable) {
        if (!StringUtils.isEmpty(parentVariable)) {
            int parentIndex = getForLoopBeanMap().get(parentVariable);
            getForLoopBeanList().get(indexOfForLoopBean).setParentIndex(parentIndex);
            getForLoopBeanList().get(parentIndex).getNestedForLoopList().add(indexOfForLoopBean);
        } else {
            // root bean
            getForLoopBeanList().get(0).getNestedForLoopList().add(indexOfForLoopBean);
        }
    }

    private boolean forLoopBeanNotCreated(String variableName) {
        return !getForLoopBeanMap().containsKey(variableName);
    }

    @Override
    public boolean validate(DataMapperDiagramModel model) {
        return true;
    }

    public Map<String, Integer> getForLoopBeanMap() {
        return forLoopBeanMap;
    }

    public void setForLoopBeanMap(Map<String, Integer> forLoopBeanMap) {
        this.forLoopBeanMap = forLoopBeanMap;
    }

    public List<ForLoopBean> getForLoopBeanList() {
        return forLoopBeanList;
    }

    public void setForLoopBeanList(List<ForLoopBean> forLoopBeanList) {
        this.forLoopBeanList = forLoopBeanList;
    }

    private int addForLoopInToMap(String variableName, ForLoopBean forLoopBean) {
        getForLoopBeanList().add(forLoopBean);
        int indexOfForLoopBean = getForLoopBeanList().size() - 1;
        forLoopBeanMap.put(variableName, indexOfForLoopBean);
        return indexOfForLoopBean;
    }

}