All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.imsweb.validation.translation.language.entity.DeclarationStatement Maven / Gradle / Ivy

/*
 * Copyright (C) 2010 Information Management Services, Inc.
 */
package com.imsweb.validation.translation.language.entity;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.imsweb.validation.translation.EditTranslationContext;
import com.imsweb.validation.translation.metafile.MetafileColumnMetaData;
import com.imsweb.validation.translation.metafile.MetafileTable;

public class DeclarationStatement extends Statement {

    private static final Logger _LOG = LogManager.getLogger(DeclarationStatement.class);

    private String _type;

    private final List _variables;

    private final String _endOfLineComment;

    /**
     * Keep track of the special table variables
     */
    private static final Set _TABLE_VARS = new HashSet<>();
    private static final Set _CHAR_ARRAY_VARS = new HashSet<>();

    public DeclarationStatement(String type, List variables, String endOfLineComment) {
        _LOG.debug("new DeclarationStatement() for " + variables.size() + " variables of type " + type);

        _type = type.toLowerCase();
        if ("long".equals(_type))
            _type = "int";
        if ("tablevar".equals(_type))
            for (VariableDeclaration decl : variables)
                _TABLE_VARS.add(decl.getIdentifier());
        if ("char".equals(_type))
            for (VariableDeclaration decl : variables)
                _CHAR_ARRAY_VARS.add(decl.getIdentifier());
        _variables = variables;
        _endOfLineComment = endOfLineComment;
    }

    @Override
    public void generateGroovy(StringBuilder buf, EditTranslationContext tContext, String indentation) {
        StringBuilder tmpBuf = new StringBuilder(indentation);

        int numVariablesAdded = 0;

        Set dejaVue = new HashSet<>();

        // keep track of "boolean" int variables that need to be written after the other ones
        List delayedBooleanVariables = new ArrayList<>();

        // add the type declaration
        if ("tablevar".equals(_type))
            tmpBuf.append("char[]");
        else {
            // handle the array declarations; make sure they are either all arrays, or none are arrays
            boolean oneVarIsArray = false, allVarAreArrays = true;
            for (VariableDeclaration var : _variables) {
                if (var.getSize() != null)
                    oneVarIsArray = true;
                else
                    allVarAreArrays = false;
            }
            if (oneVarIsArray) {
                if (!allVarAreArrays)
                    throw new RuntimeException("Error translating " + tContext.getEdit().getName() + ": found a mix of arrays and non arrays!");
                tmpBuf.append(_type).append("[]");
            }
            else if ("int".equals(_type)) {
                // special case: some "int" variables are assigned the result of a call to a boolean method, let's define those as boolean
                List booleanVar = new ArrayList<>(), nonBooleanVar = new ArrayList<>();
                for (VariableDeclaration var : _variables) {
                    if (AssignmentStatement.isBooleanVariable(var))
                        booleanVar.add(var);
                    else
                        nonBooleanVar.add(var);
                }

                tContext.getBooleanVariables().addAll(booleanVar.stream().map(VariableDeclaration::getIdentifier).collect(Collectors.toSet()));
                tContext.getIntVariables().addAll(nonBooleanVar.stream().map(VariableDeclaration::getIdentifier).collect(Collectors.toSet()));

                if (!booleanVar.isEmpty()) {
                    if (!nonBooleanVar.isEmpty()) {
                        // the declaration contains a mix of what needs to be "int" and "boolean" variable; let's put the int now and add the boolean later
                        tmpBuf.append(_type);
                        delayedBooleanVariables.addAll(booleanVar);
                    }
                    else
                        tmpBuf.append("boolean");
                }
                else
                    tmpBuf.append(_type);
            }
            else
                tmpBuf.append(_type);
        }
        tmpBuf.append(" ");

        // now that the type has been written, let's right the variable name(s)
        for (VariableDeclaration var : _variables) {
            // Genedit allows multiple variable declaration, which doesn't make any sense; Groovy does not allow that
            if (!dejaVue.contains(var.getIdentifier().toUpperCase()) && !delayedBooleanVariables.contains(var)) {
                dejaVue.add(var.getIdentifier().toUpperCase());
                numVariablesAdded++;

                // this is where the variable name is added
                tmpBuf.append(var.getIdentifier(true));
                if (FunctionStatement.isVariableDeclaredInFunction(var.getIdentifier(), tContext))
                    tmpBuf.append("_").append(tContext.getCurrentVariableSuffix());

                // deal with arrays...
                if (var.getSize() != null)
                    tmpBuf.append(" = new ").append(_type).append("[").append(var.getSize()).append("]");
                else if ("tablevar".equals(_type)) {
                    int maxLength = -1;
                    for (String usedTable : MethodInvocationExpression.getParsedUsedTables()) {
                        MetafileTable table = tContext.getTables() == null ? null : tContext.getTables().get(usedTable);
                        if (table != null) {
                            for (MetafileColumnMetaData data : table.getMetaData().values()) {
                                if (data.getColumnName().equalsIgnoreCase(var.getIdentifier())) {
                                    // this really sucks, but the metafile doesn't report correct column size for triggered-maintained columns (it always returns 1)
                                    if (table.getTriggeredMaintainedIndexes().contains(data.getColumnName()) && data.getColumnSize() == 1)
                                        maxLength = Math.max(maxLength, 100);
                                    else
                                        maxLength = Math.max(maxLength, data.getColumnSize() + 1); // plus one to take into account the end-of-string character
                                    break;
                                }
                            }
                        }
                    }
                    if (maxLength == -1)
                        maxLength = 100; // best we can do...
                    tmpBuf.append(" = new char[").append(maxLength).append("]"); // an optimization here would be to get the maximum possible size from the table...
                }
                tmpBuf.append(", ");
            }
        }
        tmpBuf.setLength(tmpBuf.length() - 2);

        // deal with pending comments
        if (_endOfLineComment != null)
            tmpBuf.append(" ").append(_endOfLineComment);

        tmpBuf.append("\n");

        // deal with the delay variables
        if (!delayedBooleanVariables.isEmpty()) {
            tmpBuf.append("boolean ");
            for (VariableDeclaration var : delayedBooleanVariables) {
                tmpBuf.append(var.getIdentifier()).append(", ");
                numVariablesAdded++;
            }
            tmpBuf.setLength(tmpBuf.length() - 2);
            tmpBuf.append("\n");
        }

        if (numVariablesAdded > 0)
            buf.append(tmpBuf.toString());
    }

    public List getVariableDeclarations() {
        return _variables;
    }

    @Override
    public boolean isOneLineStatementOnly() {
        return true;
    }

    public static Set getDeclaredTableVars() {
        return _TABLE_VARS;
    }

    public static Set getDeclaredCharArrayVars() {
        return _CHAR_ARRAY_VARS;
    }

    public static void resetDeclaredVars() {
        _TABLE_VARS.clear();
        _CHAR_ARRAY_VARS.clear();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy