package org.sigmah.shared.computation;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.sigmah.shared.computation.instruction.Instructions;
import org.sigmah.shared.computation.value.ComputationError;
import org.sigmah.shared.dto.element.FlexibleElementDTO;
/**
* Parse and creates <code>Computation</code> objects.
*
* @author Raphaƫl Calabro (raphael.calabro@netapsys.fr)
* @since 2.1
*/
public final class Computations {
/**
* Parse the given rule.
*
* @param rule Rule to read.
* @param allElements Flexible element that can be used in the rule.
* @return A new <code>Computation</code> object.
*/
public static Computation parse(String rule, Collection<FlexibleElementDTO> allElements) {
try {
final ParserEnvironment environment = new ParserEnvironment(createReferenceMap(allElements));
final char[] array = rule.toCharArray();
int index = 0;
while (index < array.length) {
index = environment.getState().execute(index, array, environment);
}
environment.popEverythingFromStackToInstructions();
final Computation computation = new Computation(environment.getInstructions());
// Check if everything is alright.
computation.toString();
return computation;
} catch (RuntimeException e) {
// Exception is ignored.
e.printStackTrace();
return new Computation(Collections.singletonList(
Instructions.getConstantWithValue(ComputationError.BAD_FORMULA)));
}
}
/**
* Parse the given rule and format it as a human readable rule.
*
* @param rule Rule to format.
* @param allElements Elements.
* @return Formatted rule or <code>null</code> if the given rule is invalid.
*/
public static String formatRuleForEdition(String rule, Collection<FlexibleElementDTO> allElements) {
if (rule == null || rule.trim().isEmpty()) {
return null;
}
final Computation computation = parse(rule, allElements);
return computation.toHumanReadableString();
}
/**
* Parse the given rule and format it with ids.
*
* @param rule Rule to format.
* @param allElements Elements.
* @return Formatted rule or <code>null</code> if the given rule is invalid.
*/
public static String formatRuleForServer(String rule, Collection<FlexibleElementDTO> allElements) {
if (rule == null || rule.trim().isEmpty()) {
return null;
}
final Computation computation = parse(rule, allElements);
return computation.toString();
}
/**
* Creates a map associating the identifier and the code of every element
* to its element.
*
* @param allElements Flexible element that can be used in the rule.
* @return A map of id/code to its flexible element.
*/
private static Map<String, FlexibleElementDTO> createReferenceMap(Collection<FlexibleElementDTO> allElements) {
final HashMap<String, FlexibleElementDTO> references = new HashMap<String, FlexibleElementDTO>();
for (final FlexibleElementDTO element : allElements) {
// fields in iterative groups cannot be part of formula
if(element.getGroup() != null && element.getGroup().getHasIterations()) {
continue;
}
references.put(Instructions.ID_PREFIX + element.getId().toString(), element);
references.put(element.getCode(), element);
}
return references;
}
/**
* Private constructor.
*/
private Computations() {
// Nothing.
}
}