com.imsweb.validation.functions.MetafileContextFunctions Maven / Gradle / Ivy
/*
* Copyright (C) 2010 Information Management Services, Inc.
*/
package com.imsweb.validation.functions;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import groovy.lang.Binding;
import com.imsweb.staging.Staging;
import com.imsweb.validation.ValidationEngine;
import com.imsweb.validation.entities.ContextTable;
import com.imsweb.validation.entities.ContextTableIndex;
/**
* Metafile-related helper methods made available to the edits. If you want to execute translated edits in your project, you need to initialize
* the context functions with an instance of this class.
*
* None of these methods should be called from regular (non-translated) edits.
*
* As of version 5.3 of the engine, it is now possible to treat WARNINGS in translated edits as a failing state. To do that, just call
* the setFailWarnings() method with an argument of "true" after instanciating this class.
*/
@SuppressWarnings("ALL")
public class MetafileContextFunctions extends StagingContextFunctions {
// Special Geneedits constant
public static final int DT_VALID = 1342177279;
// Special Geneedits constant
public static final int DT_MISSING = 1610612735;
// Special Geneedits constant
public static final int DT_ERROR = 1879048191;
// Special Geneedits constant
public static final int DT_UNKNOWN = 2147483647;
// Special Geneedits constant
public static final int DT_EMPTY = 1073741823;
// Special Geneedits constant
public static final int DT_DAY_EMPTY = 805306367;
// Special Geneedits constant
public static final int DT_MONTH_EMPTY = 536870911;
// sentinel threshold, no sentinel value should be lower than this!
public static final int SENTINEL_TRESHOLD = DT_MONTH_EMPTY;
// Special Geneedits constant
public static final int DT_MIN = 1;
// Special Geneedits constant
public static final int DT_MAX = 2;
// Special Geneedits constant
public static final int DT_EXACT = 3;
// Special Geneedits constant
public static final int TRIM_RIGHT = 0;
// Special Geneedits constant
public static final int TRIM_LEFT = 1;
// Special Geneedits constant
public static final int TRIM_BOTH = 2;
// Special Geneedits constant
public static final int JUSTIFIED_RIGHT = 0;
// Special Geneedits constant
public static final int JUSTIFIED_LEFT = 1;
// Special genedits binding keys
public static final String BINDING_KEY_FUTURE_DATE = "__years_into_future";
// Special genedits binding keys
public static final String BINDING_KEY_DATE_COMPONENT = "__date_component";
// Pre-compiled regex and formatters...
private static final Pattern _GEN_VAL_P1 = Pattern.compile("(-?\\d+)(.*)");
private static final Pattern _GEN_VALID_DATE_IOP_P1 = Pattern.compile("(\\d{8}|\\d{6}\\s{2}|\\d{4}\\s{4})");
private static final DateTimeFormatter _GEN_DATECMP_IOP_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
private static final Pattern _GEN_TRIM_P1 = Pattern.compile("^\\s+");
private static final Pattern _GEN_TRIM_P2 = Pattern.compile("\\s+$");
private static final Pattern _GEN_TRIM_P3 = Pattern.compile("(^\\s+|\\s+$)");
private static final Pattern _GEN_MATCH_P1 = Pattern.compile("\\s");
private static final Pattern _GEN_MATCH_P2 = Pattern.compile("(\\\\s)+");
private static final Pattern _GEN_MATCH_P3 = Pattern.compile("((\\\\s)+)\\)$");
private static final Pattern _GEN_MATCH_P4 = Pattern.compile("((\\\\s)+)$");
private static final Pattern _GEN_FMTSTR_P1 = Pattern.compile("%(.*)ld");
private static final Pattern _GEN_INLIST_P1 = Pattern.compile("(\\d+)\\D*.*");
// I don't love giving a state to this class, but I am not sure how else to do it since we already have multiple flavors for the constructor...
private boolean _failWarnings = false;
/**
* Minimal constructor. The metafile context methods use the CS staging client and therefore require a staging algorithm to be registered with this constructor.
*
* Note that this class can also be initialized with an instance of a TNM and EDO staging client, but no metafile conext methods need those. Historically, Genedits
* relied on the CS DLL, but not on any TNM or EOD DLL.
*
* You may provide null for the CS staging object, but any CS-related context methods won't work correctly.
*
* Here is an example of how to create the required CS staging object:
*
* Staging csStaging = Staging.getInstance(CsDataProvider.getInstance(CsDataProvider.CsVersion.v020550));
*
* You will also need to add a dependency to the CS algorithm in your project, see https://github.com/imsweb/staging-algorithm-cs
*/
public MetafileContextFunctions(Staging csStaging) {
super(csStaging, null, null);
}
/**
* Constructor.
* @param csStaging Staging instance to use for Collaboriative-Stage-related operations.
* @param tnmStaging Staging instance to use for TNM-related operations.
* @param eodStaging Staging instance to use for EOD-related operations.
*/
public MetafileContextFunctions(Staging csStaging, Staging tnmStaging, Staging eodStaging) {
super(csStaging, tnmStaging, eodStaging);
}
/**
* If set to true, then warnings in translated edits will make the edit fail.
*/
public void setFailWarnings(boolean failWarnings) {
_failWarnings = failWarnings;
}
/**
* @return whether warnings in translated edits are considered as failures.
*/
public boolean isFailWarnings() {
return _failWarnings;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
*/
public void GEN_NOOP() {
return;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
*/
public void GEN_RESET_LOCAL_CONTEXT(Binding binding) {
binding.setVariable(BINDING_KEY_FUTURE_DATE, null);
binding.setVariable(BINDING_KEY_DATE_COMPONENT, null);
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @return - internal use only -
*/
public boolean GEN_EMPTY(Object value) {
if (value == null)
return true;
return StringUtils.isBlank(GEN_TO_STRING(value));
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @return - internal use only -
*/
public int GEN_VAL(Object value) {
int result = 0;
String val = value == null ? "" : GEN_TO_STRING(value).trim();
Matcher match = _GEN_VAL_P1.matcher(val);
if (match.matches())
result = Integer.parseInt(match.group(1));
return result;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value
* @return - internal use only -
*/
public boolean GEN_VALID_DATE_IOP(Binding binding, Object value) {
String val = GEN_TO_STRING(value);
if (val == null || val.isEmpty()) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "date is an empty string");
return false;
}
if (!_GEN_VALID_DATE_IOP_P1.matcher(val).matches()) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "date format must be CCYYMMDD");
return false;
}
LocalDate currentTime = LocalDate.now();
int maxYear = currentTime.getYear();
Integer futureYears = null;
if (binding.hasVariable(BINDING_KEY_FUTURE_DATE))
futureYears = (Integer)binding.getVariable(BINDING_KEY_FUTURE_DATE);
if (futureYears != null)
maxYear += futureYears;
int year = Integer.parseInt(val.substring(0, 4));
if (year < 1850 || year > maxYear) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "invalid as to year");
return false;
}
int month = val.trim().length() >= 6 ? Integer.parseInt(val.substring(4, 6)) : 1;
if (month <= 0 || month > 12) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "invalid as to month");
return false;
}
try {
int day = val.trim().length() == 8 ? Integer.parseInt(val.substring(6, 8)) : 1;
LocalDate toCheck = LocalDate.of(year, month, day);
int actualMaxDay = YearMonth.of(year, month).lengthOfMonth();
if (day <= 0 || day > actualMaxDay) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "invalid as to day");
return false;
}
if (futureYears != null)
currentTime = currentTime.plusYears(futureYears);
if (toCheck.compareTo(currentTime) > 0) {
binding.setVariable(BINDING_KEY_DATE_COMPONENT, "future date");
return false;
}
}
catch (DateTimeException e) {
return false; // Invalid date. Like Feb 29th 2010.
}
return true;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param yearsIntoFuture
*/
public void GEN_ALLOW_FUTURE_DATE_IOP(Binding binding, Object yearsIntoFuture) {
binding.setVariable(BINDING_KEY_FUTURE_DATE, yearsIntoFuture);
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value
* @return - internal use only -
*/
public int GEN_DATE_YEAR_IOP(Binding binding, Object value) {
String val = GEN_TO_STRING(value);
if (val == null || val.trim().isEmpty())
return DT_EMPTY;
if (!GEN_VALID_DATE_IOP(binding, value))
return DT_ERROR;
return Integer.parseInt(val.substring(0, 4));
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value
* @return - internal use only -
*/
public int GEN_DATE_MONTH_IOP(Binding binding, Object value) {
String val = GEN_TO_STRING(value);
if (val == null || val.length() < 5 || (val.length() >= 6 && val.substring(4, 6).trim().isEmpty()))
return DT_MONTH_EMPTY;
if (!GEN_VALID_DATE_IOP(binding, value))
return DT_ERROR;
return Integer.parseInt(val.substring(4, 6));
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value
* @return - internal use only -
*/
public int GEN_DATE_DAY_IOP(Binding binding, Object value) {
String val = GEN_TO_STRING(value);
if (val == null || val.length() < 7 || val.substring(6).trim().isEmpty())
return DT_DAY_EMPTY;
if (!GEN_VALID_DATE_IOP(binding, value))
return DT_ERROR;
return Integer.parseInt(val.substring(6));
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_DATECMP_IOP(Binding binding, Object value1, Object value2, Object minMaxFlagObj) {
StringBuilder buf1 = new StringBuilder();
StringBuilder buf2 = new StringBuilder();
int minMaxFlag = (Integer)minMaxFlagObj;
if (minMaxFlag == DT_MIN && !runMinFlagLogic(binding, value1, value2, minMaxFlag, value1, value2))
return 0;
int result = applyMinMaxFlag(binding, value1, value2, minMaxFlag, buf1, buf2);
if (result != 0)
return result;
LocalDate date1 = LocalDate.parse(buf1.toString(), _GEN_DATECMP_IOP_FORMAT);
LocalDate date2 = LocalDate.parse(buf2.toString(), _GEN_DATECMP_IOP_FORMAT);
if (date1.compareTo(date2) > 0)
return 1;
else if (date1.compareTo(date2) < 0)
return -1;
else
return 0;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_YEARDIFF_IOP(Binding binding, String value1, String value2, Object minMaxFlagObj) {
int dayDiff = GEN_DAYDIFF_IOP(binding, value1, value2, minMaxFlagObj);
if (dayDiff > SENTINEL_TRESHOLD)
return dayDiff;
return (int)Math.floor((double)dayDiff / (double)365);
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minInt
* @param maxInt
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_YEARINTERNAL_IOP(Binding binding, String value1, String value2, Integer minInt, Integer maxInt, Object minMaxFlagObj) {
int yearDiff = GEN_YEARDIFF_IOP(binding, value1, value2, minMaxFlagObj);
if (yearDiff > SENTINEL_TRESHOLD)
return yearDiff;
return yearDiff >= minInt && yearDiff <= maxInt ? 1 : 0;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_MONTHDIFF_IOP(Binding binding, String value1, String value2, Object minMaxFlagObj) {
int dayDiff = GEN_DAYDIFF_IOP(binding, value1, value2, minMaxFlagObj);
if (dayDiff > SENTINEL_TRESHOLD)
return dayDiff;
return dayDiff < 0 ? (int)Math.ceil((double)dayDiff / (double)30) : (int)Math.floor((double)dayDiff / (double)30);
}
/**
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minInt
* @param maxInt
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_MONTHINTERNAL_IOP(Binding binding, String value1, String value2, Integer minInt, Integer maxInt, Object minMaxFlagObj) {
int monthDiff = GEN_MONTHDIFF_IOP(binding, value1, value2, minMaxFlagObj);
if (monthDiff > SENTINEL_TRESHOLD)
return monthDiff;
return monthDiff >= minInt && monthDiff <= maxInt ? 1 : 0;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_DAYDIFF_IOP(Binding binding, String value1, String value2, Object minMaxFlagObj) {
StringBuilder buf1 = new StringBuilder();
StringBuilder buf2 = new StringBuilder();
int minMaxFlag = (Integer)minMaxFlagObj;
int result = applyMinMaxDayDiffFlag(binding, value1, value2, minMaxFlag, buf1, buf2);
if (result != 0)
return result;
LocalDate date1 = LocalDate.parse(buf1.toString(), _GEN_DATECMP_IOP_FORMAT);
LocalDate date2 = LocalDate.parse(buf2.toString(), _GEN_DATECMP_IOP_FORMAT);
return (int)ChronoUnit.DAYS.between(date1, date2);
}
/**
* Created on Apr 5, 2011 by depryf
* @param binding
* @param value1
* @param value2
* @param minInt
* @param maxInt
* @param minMaxFlagObj
* @return - internal use only -
*/
public int GEN_DAYINTERNAL_IOP(Binding binding, String value1, String value2, Integer minInt, Integer maxInt, Object minMaxFlagObj) {
int dayDiff = GEN_DAYDIFF_IOP(binding, value1, value2, minMaxFlagObj);
if (dayDiff > SENTINEL_TRESHOLD)
return dayDiff;
return dayDiff >= minInt && dayDiff <= maxInt ? 1 : 0;
}
// helper
private boolean runMinFlagLogic(Binding binding, Object value1, Object value2, Object minMaxFlagObj, Object date1, Object date2) {
String val1 = GEN_TO_STRING(value1);
String val2 = GEN_TO_STRING(value2);
if (val1 == null || val1.trim().isEmpty() || val2 == null || val2.trim().isEmpty())
return true;
if (!GEN_VALID_DATE_IOP(binding, val1) || !GEN_VALID_DATE_IOP(binding, val2))
return true;
int y1 = GEN_DATE_YEAR_IOP(binding, val1);
int y2 = GEN_DATE_YEAR_IOP(binding, val2);
int m1 = GEN_DATE_MONTH_IOP(binding, val1);
int m2 = GEN_DATE_MONTH_IOP(binding, val2);
int d1 = GEN_DATE_DAY_IOP(binding, val1);
int d2 = GEN_DATE_DAY_IOP(binding, val2);
if (y1 == y2 && (m1 == DT_MONTH_EMPTY || m2 == DT_MONTH_EMPTY))
return false;
if (y1 == y2 && m1 == m2 && (d1 == DT_DAY_EMPTY || d2 == DT_DAY_EMPTY))
return false;
return true;
}
// helper
private int applyMinMaxDayDiffFlag(Binding binding, Object value1, Object value2, Object minMaxFlagObj, StringBuilder date1Buf, StringBuilder date2Buf) {
String val1 = GEN_TO_STRING(value1);
String val2 = GEN_TO_STRING(value2);
if (val1 == null || val1.trim().isEmpty() || val2 == null || val2.trim().isEmpty())
return DT_EMPTY;
if (!GEN_VALID_DATE_IOP(binding, val1) || !GEN_VALID_DATE_IOP(binding, val2))
return DT_ERROR;
int y1 = GEN_DATE_YEAR_IOP(binding, val1);
int y2 = GEN_DATE_YEAR_IOP(binding, val2);
int m1 = GEN_DATE_MONTH_IOP(binding, val1);
int m2 = GEN_DATE_MONTH_IOP(binding, val2);
int d1 = GEN_DATE_DAY_IOP(binding, val1);
int d2 = GEN_DATE_DAY_IOP(binding, val2);
date1Buf.append(pad(String.valueOf(y1), 4, "0", true));
date2Buf.append(pad(String.valueOf(y2), 4, "0", true));
int minMaxFlag = (Integer)minMaxFlagObj;
// handle month of first value
int safeBeginningMonth = m1;
if (m1 == DT_MONTH_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2 && m2 != DT_MONTH_EMPTY)
safeBeginningMonth = m2;
else if (y1 < y2)
safeBeginningMonth = 12; // December
else
safeBeginningMonth = 1; // January
}
else if (minMaxFlag == DT_MAX)
safeBeginningMonth = 1; // January
else
return DT_UNKNOWN;
}
date1Buf.append(pad(String.valueOf(safeBeginningMonth), 2, "0", true));
// handle month of second value
int safeEndMonth = m2;
if (m2 == DT_MONTH_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2)
safeEndMonth = safeBeginningMonth;
else if (m1 == DT_MONTH_EMPTY && m2 == DT_MONTH_EMPTY && y1 > y2)
safeEndMonth = 12;
else if (y1 > y2)
safeEndMonth = 12;
else
safeEndMonth = 1; // January
}
else if (minMaxFlag == DT_MAX)
safeEndMonth = 12; // December
else
return DT_UNKNOWN;
}
date2Buf.append(pad(String.valueOf(safeEndMonth), 2, "0", true));
int numDaysInBeginningMonth = YearMonth.of(y1, safeBeginningMonth).lengthOfMonth();
int numDaysInEndMonth = YearMonth.of(y2, safeEndMonth).lengthOfMonth();
// handle day of first value
int safeBeginningDay = d1;
if (d1 == DT_DAY_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2 && m1 != DT_MONTH_EMPTY && m2 != DT_MONTH_EMPTY && d2 != DT_DAY_EMPTY)
safeBeginningDay = 1;
else if (y1 == y2 && m1 == DT_MONTH_EMPTY && d2 != DT_DAY_EMPTY)
safeBeginningDay = d2;
else if (y1 < y2)
safeBeginningDay = numDaysInBeginningMonth; // last day
else if (y1 > y2 || m1 == DT_MONTH_EMPTY)
safeBeginningDay = 1; // first day
else
safeBeginningDay = numDaysInBeginningMonth; // last day
}
else if (minMaxFlag == DT_MAX)
safeBeginningDay = 1; // first day
else
return DT_UNKNOWN;
}
date1Buf.append(pad(String.valueOf(safeBeginningDay), 2, "0", true));
// handle day of second value
int safeEndDay = d2;
if (d2 == DT_DAY_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2 && safeBeginningMonth == safeEndMonth)
safeEndDay = safeBeginningDay;
else if (m1 == DT_MONTH_EMPTY && m2 == DT_MONTH_EMPTY && y1 > y2)
safeEndDay = numDaysInEndMonth;
else if (y1 > y2)
safeEndDay = numDaysInEndMonth;
else
safeEndDay = 1; // first day
}
else if (minMaxFlag == DT_MAX)
safeEndDay = numDaysInEndMonth; // last day
else
return DT_UNKNOWN;
}
date2Buf.append(pad(String.valueOf(safeEndDay), 2, "0", true));
return 0;
}
// helper
private int applyMinMaxFlag(Binding binding, Object value1, Object value2, Object minMaxFlagObj, StringBuilder date1Buf, StringBuilder date2Buf) {
String val1 = GEN_TO_STRING(value1);
String val2 = GEN_TO_STRING(value2);
if (val1 == null || val1.trim().isEmpty() || val2 == null || val2.trim().isEmpty())
return DT_EMPTY;
if (!GEN_VALID_DATE_IOP(binding, val1) || !GEN_VALID_DATE_IOP(binding, val2))
return DT_ERROR;
int y1 = GEN_DATE_YEAR_IOP(binding, val1);
int y2 = GEN_DATE_YEAR_IOP(binding, val2);
int m1 = GEN_DATE_MONTH_IOP(binding, val1);
int m2 = GEN_DATE_MONTH_IOP(binding, val2);
int d1 = GEN_DATE_DAY_IOP(binding, val1);
int d2 = GEN_DATE_DAY_IOP(binding, val2);
date1Buf.append(pad(String.valueOf(y1), 4, "0", true));
date2Buf.append(pad(String.valueOf(y2), 4, "0", true));
int minMaxFlag = (Integer)minMaxFlagObj;
// handle month of first value
int safeBeginningMonth = m1;
if (m1 == DT_MONTH_EMPTY) {
if (minMaxFlag == DT_MIN)
safeBeginningMonth = 12; // December
else if (minMaxFlag == DT_MAX)
safeBeginningMonth = 1; // January
else
return DT_UNKNOWN;
}
date1Buf.append(pad(String.valueOf(safeBeginningMonth), 2, "0", true));
// handle month of second value
int safeEndMonth = m2;
if (m2 == DT_MONTH_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2)
safeEndMonth = safeBeginningMonth;
else
safeEndMonth = 1; // January
}
else if (minMaxFlag == DT_MAX)
safeEndMonth = 12; // December
else
return DT_UNKNOWN;
}
date2Buf.append(pad(String.valueOf(safeEndMonth), 2, "0", true));
int numDaysInBeginningMonth = YearMonth.of(y1, safeBeginningMonth).lengthOfMonth();
int numDaysInEndMonth = YearMonth.of(y2, safeEndMonth).lengthOfMonth();
// handle day of first value
int safeBeginningDay = d1;
if (d1 == DT_DAY_EMPTY) {
if (minMaxFlag == DT_MIN)
safeBeginningDay = numDaysInBeginningMonth; // last day
else if (minMaxFlag == DT_MAX)
safeBeginningDay = 1; // first day
else
return DT_UNKNOWN;
}
date1Buf.append(pad(String.valueOf(safeBeginningDay), 2, "0", true));
// handle day of second value
int safeEndDay = d2;
if (d2 == DT_DAY_EMPTY) {
if (minMaxFlag == DT_MIN) {
if (y1 == y2 && safeBeginningMonth == safeEndMonth)
safeEndDay = safeBeginningDay;
else
safeEndDay = 1; // first day
}
else if (minMaxFlag == DT_MAX)
safeEndDay = numDaysInEndMonth; // last day
else
return DT_UNKNOWN;
}
date2Buf.append(pad(String.valueOf(safeEndDay), 2, "0", true));
return 0;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @param typeObj
* @return - internal use only -
*/
public String GEN_TRIM(Object value, Object typeObj) {
String val = GEN_TO_STRING(value);
if (val == null || val.isEmpty())
return val;
int type = (Integer)typeObj;
String result;
switch (type) {
case TRIM_LEFT:
result = _GEN_TRIM_P1.matcher(val).replaceAll("");
break;
case TRIM_RIGHT:
result = _GEN_TRIM_P2.matcher(val).replaceAll("");
break;
case TRIM_BOTH:
result = _GEN_TRIM_P3.matcher(val).replaceAll("");
break;
default:
throw new RuntimeException("Unsupported type: " + type);
}
return result;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @return - internal use only -
*/
public int GEN_STRLEN(Object value) {
String val = GEN_TO_STRING(value);
return val == null ? 0 : val.length();
}
// helper
private boolean isValInList2(String val, String list) {
// if the value has trailing non-numeric values, trim off those non-numeric values first
String numericVal = removeTrailingNonNumerics(val);
if (" ".equals(list))
return " ".equals(val);
for (String term : StringUtils.split(list, ',')) {
String[] parts = StringUtils.split(term, '-');
// term is single value
if (parts.length == 1 && val.equals(term.trim()))
return true;
// term is a range
else if (parts.length == 2) {
// if the input value is a digit
if (numericVal != null) {
String low = parts[0].trim(), high = parts[1].trim();
//remove trailing non-numeric values from range numbers
low = removeTrailingNonNumerics(low);
high = removeTrailingNonNumerics(high);
// if both the low and high values are numeric
if (low != null && high != null) {
int iVal = Integer.parseInt(numericVal);
int iLow = Integer.parseInt(low);
int iHigh = Integer.parseInt(high);
if (iVal >= iLow && iVal <= iHigh)
return true;
}// if low is numeric but the high value is non-numeric
else if (low != null && high == null) {
int iVal = Integer.parseInt(numericVal);
int iLow = Integer.parseInt(low);
if (iVal >= iLow)
return true;
}// if low is non-numeric but the high value is numeric
else if (low == null && high != null) {
int iVal = Integer.parseInt(numericVal);
int iHigh = Integer.parseInt(high);
if (iVal <= iHigh)
return true;
}
else
return true;
}
}
}
return false;
}
// helper
private String removeTrailingNonNumerics(String input) {
String newString = null;
Matcher m4 = _GEN_INLIST_P1.matcher(input);
if (m4.matches())
newString = m4.group(1);
return newString;
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @param list
* @return - internal use only -
*/
public boolean GEN_INLIST(Object value, Object list) {
return GEN_INLIST(value, list, null, null, null);
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @param list
* @param regex
* @return - internal use only -
*/
public boolean GEN_INLIST(Object value, Object list, Object regex) {
return GEN_INLIST(value, list, regex, null, null);
}
/**
* Special genedit method. Internal use only.
*
* Created on Apr 5, 2011 by depryf
* @param value
* @param list
* @param regex
* @param startPos
* @param length
* @return - internal use only -
*/
public boolean GEN_INLIST(Object value, Object list, Object regex, Integer startPos, Integer length) {
String val = GEN_TO_STRING(value), l = GEN_TO_STRING(list);
if (val == null || val.isEmpty() || l == null || l.isEmpty())
return false;
if (regex != null && !GEN_MATCH(val, regex))
return false;
// weird corner case
if (StringUtils.isBlank(l))
return list.equals(val);
// another weird corner case
if (StringUtils.isBlank(val) && regex != null)
return true;
if (startPos != null && length != null) {
int start = startPos - 1; // Genedits uses 1-based index...
int end = Math.min(startPos - 1 + length, val.length()); // Gendits allows a length going past the end of the string...
if (start >= end)
return false;
val = val.substring(start, end);
}
for (String term : StringUtils.split(StringUtils.replace(l, " ", ""), ',')) {
String[] parts = StringUtils.split(term, '-');
if ((parts.length == 1 && val.equals(term)) || (parts.length == 2 && val.compareTo(parts[0]) >= 0 && val.compareTo(parts[1]) <= 0))
return true;
// value "1 " is found in list "1"; my best guess is that the trailing spaces are removed...
val = StringUtils.stripEnd(val, null);
if ((parts.length == 1 && val.equals(term)) || (parts.length == 2 && val.compareTo(parts[0]) >= 0 && val.compareTo(parts[1]) <= 0))
return true;
}
return false;
}
public boolean GEN_MATCH(Object value, Object regex) {
return matches(GEN_TO_STRING(value), GEN_TO_STRING(regex));
}
@SuppressWarnings("unchecked")
public boolean GEN_LOOKUP(Object value, Object tableObj, Object indexObj, Map, char[]> tableVars) {
String val = GEN_TO_STRING(value);
if (val == null || (tableObj == null && indexObj == null))
return false;
if (tableObj instanceof ContextTable || indexObj instanceof ContextTableIndex)
return GEN_LOOKUP_V5(val, (ContextTable)tableObj, (ContextTableIndex)indexObj, (Map)tableVars);
else
return GEN_LOOKUP_V4(val, (List>)tableObj, indexObj, (Map)tableVars);
}
// this is the old engine (v4) implementation
@SuppressWarnings("unchecked")
private boolean GEN_LOOKUP_V4(String val, List> table, Object indexObj, Map tableVars) {
// index values are trimmed, so the incoming one also need to be trimmed...
String trimmedVal = trimRight(val);
// if an index exists, use it!
boolean found = false;
Integer valIndex = null;
if (indexObj != null) {
if (indexObj instanceof List) {
for (Object elem : (List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy