/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.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.pentaho.di.trans.steps.calculator; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.row.value.ValueMetaFactory; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.ObjectId; import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.kdr.KettleDatabaseRepository; import org.pentaho.metastore.api.IMetaStore; import org.w3c.dom.Node; public class CalculatorMetaFunction implements Cloneable { private static Class<?> PKG = CalculatorMeta.class; // for i18n purposes, needed by Translator2!! public static final String XML_TAG = "calculation"; public static final int CALC_NONE = 0; public static final int CALC_CONSTANT = 1; public static final int CALC_COPY_OF_FIELD = 2; public static final int CALC_ADD = 3; public static final int CALC_SUBTRACT = 4; public static final int CALC_MULTIPLY = 5; public static final int CALC_DIVIDE = 6; public static final int CALC_SQUARE = 7; public static final int CALC_SQUARE_ROOT = 8; public static final int CALC_PERCENT_1 = 9; public static final int CALC_PERCENT_2 = 10; public static final int CALC_PERCENT_3 = 11; public static final int CALC_COMBINATION_1 = 12; public static final int CALC_COMBINATION_2 = 13; public static final int CALC_ROUND_1 = 14; public static final int CALC_ROUND_2 = 15; public static final int CALC_ROUND_STD_1 = 16; public static final int CALC_ROUND_STD_2 = 17; public static final int CALC_CEIL = 18; public static final int CALC_FLOOR = 19; public static final int CALC_NVL = 20; public static final int CALC_ADD_DAYS = 21; public static final int CALC_YEAR_OF_DATE = 22; public static final int CALC_MONTH_OF_DATE = 23; public static final int CALC_DAY_OF_YEAR = 24; public static final int CALC_DAY_OF_MONTH = 25; public static final int CALC_DAY_OF_WEEK = 26; public static final int CALC_WEEK_OF_YEAR = 27; public static final int CALC_WEEK_OF_YEAR_ISO8601 = 28; public static final int CALC_YEAR_OF_DATE_ISO8601 = 29; public static final int CALC_BYTE_TO_HEX_ENCODE = 30; public static final int CALC_HEX_TO_BYTE_DECODE = 31; public static final int CALC_CHAR_TO_HEX_ENCODE = 32; public static final int CALC_HEX_TO_CHAR_DECODE = 33; public static final int CALC_CRC32 = 34; public static final int CALC_ADLER32 = 35; public static final int CALC_MD5 = 36; public static final int CALC_SHA1 = 37; public static final int CALC_LEVENSHTEIN_DISTANCE = 38; public static final int CALC_METAPHONE = 39; public static final int CALC_DOUBLE_METAPHONE = 40; public static final int CALC_ABS = 41; public static final int CALC_REMOVE_TIME_FROM_DATE = 42; public static final int CALC_DATE_DIFF = 43; public static final int CALC_ADD3 = 44; public static final int CALC_INITCAP = 45; public static final int CALC_UPPER_CASE = 46; public static final int CALC_LOWER_CASE = 47; public static final int CALC_MASK_XML = 48; public static final int CALC_USE_CDATA = 49; public static final int CALC_REMOVE_CR = 50; public static final int CALC_REMOVE_LF = 51; public static final int CALC_REMOVE_CRLF = 52; public static final int CALC_REMOVE_TAB = 53; public static final int CALC_GET_ONLY_DIGITS = 54; public static final int CALC_REMOVE_DIGITS = 55; public static final int CALC_STRING_LEN = 56; public static final int CALC_LOAD_FILE_CONTENT_BINARY = 57; public static final int CALC_ADD_TIME_TO_DATE = 58; public static final int CALC_QUARTER_OF_DATE = 59; public static final int CALC_SUBSTITUTE_VARIABLE = 60; public static final int CALC_UNESCAPE_XML = 61; public static final int CALC_ESCAPE_HTML = 62; public static final int CALC_UNESCAPE_HTML = 63; public static final int CALC_ESCAPE_SQL = 64; public static final int CALC_DATE_WORKING_DIFF = 65; public static final int CALC_ADD_MONTHS = 66; public static final int CALC_CHECK_XML_FILE_WELL_FORMED = 67; public static final int CALC_CHECK_XML_WELL_FORMED = 68; public static final int CALC_GET_FILE_ENCODING = 69; public static final int CALC_DAMERAU_LEVENSHTEIN = 70; public static final int CALC_NEEDLEMAN_WUNSH = 71; public static final int CALC_JARO = 72; public static final int CALC_JARO_WINKLER = 73; public static final int CALC_SOUNDEX = 74; public static final int CALC_REFINED_SOUNDEX = 75; public static final int CALC_ADD_HOURS = 76; public static final int CALC_ADD_MINUTES = 77; public static final int CALC_DATE_DIFF_MSEC = 78; public static final int CALC_DATE_DIFF_SEC = 79; public static final int CALC_DATE_DIFF_MN = 80; public static final int CALC_DATE_DIFF_HR = 81; public static final int CALC_HOUR_OF_DAY = 82; public static final int CALC_MINUTE_OF_HOUR = 83; public static final int CALC_SECOND_OF_MINUTE = 84; public static final int CALC_ROUND_CUSTOM_1 = 85; public static final int CALC_ROUND_CUSTOM_2 = 86; public static final int CALC_ADD_SECONDS = 87; public static final int CALC_REMAINDER = 88; public static final String[] calc_desc = { "-", "CONSTANT", "COPY_FIELD", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "SQUARE", "SQUARE_ROOT", "PERCENT_1", "PERCENT_2", "PERCENT_3", "COMBINATION_1", "COMBINATION_2", "ROUND_1", "ROUND_2", "ROUND_STD_1", "ROUND_STD_2", "CEIL", "FLOOR", "NVL", "ADD_DAYS", "YEAR_OF_DATE", "MONTH_OF_DATE", "DAY_OF_YEAR", "DAY_OF_MONTH", "DAY_OF_WEEK", "WEEK_OF_YEAR", "WEEK_OF_YEAR_ISO8601", "YEAR_OF_DATE_ISO8601", "BYTE_TO_HEX_ENCODE", "HEX_TO_BYTE_DECODE", "CHAR_TO_HEX_ENCODE", "HEX_TO_CHAR_DECODE", "CRC32", "ADLER32", "MD5", "SHA1", "LEVENSHTEIN_DISTANCE", "METAPHONE", "DOUBLE_METAPHONE", "ABS", "REMOVE_TIME_FROM_DATE", "DATE_DIFF", "ADD3", "INIT_CAP", "UPPER_CASE", "LOWER_CASE", "MASK_XML", "USE_CDATA", "REMOVE_CR", "REMOVE_LF", "REMOVE_CRLF", "REMOVE_TAB", "GET_ONLY_DIGITS", "REMOVE_DIGITS", "STRING_LEN", "LOAD_FILE_CONTENT_BINARY", "ADD_TIME_TO_DATE", "QUARTER_OF_DATE", "SUBSTITUTE_VARIABLE", "UNESCAPE_XML", "ESCAPE_HTML", "UNESCAPE_HTML", "ESCAPE_SQL", "DATE_WORKING_DIFF", "ADD_MONTHS", "CHECK_XML_FILE_WELL_FORMED", "CHECK_XML_WELL_FORMED", "GET_FILE_ENCODING", "DAMERAU_LEVENSHTEIN", "NEEDLEMAN_WUNSH", "JARO", "JARO_WINKLER", "SOUNDEX", "REFINED_SOUNDEX", "ADD_HOURS", "ADD_MINUTES", "DATE_DIFF_MSEC", "DATE_DIFF_SEC", "DATE_DIFF_MN", "DATE_DIFF_HR", "HOUR_OF_DAY", "MINUTE_OF_HOUR", "SECOND_OF_MINUTE", "ROUND_CUSTOM_1", "ROUND_CUSTOM_2", "ADD_SECONDS", "REMAINDER" }; public static final String[] calcLongDesc = { "-", BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SetFieldToConstant" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.CreateCopyOfField" ), "A + B", "A - B", "A * B", "A / B", "A * A", BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SQRT" ), "100 * A / B", "A - ( A * B / 100 )", "A + ( A * B / 100 )", "A + B * C", BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Hypotenuse" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Round" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Round2" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RoundStd" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RoundStd2" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Ceil" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Floor" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.NVL" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DatePlusDays" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.YearOfDate" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.MonthOfDate" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DayOfYear" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DayOfMonth" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DayOfWeek" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.WeekOfYear" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.WeekOfYearISO8601" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.YearOfDateISO8601" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.ByteToHexEncode" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.HexToByteDecode" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.CharToHexEncode" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.HexToCharDecode" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.CRC32" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Adler32" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.MD5" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SHA1" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.LevenshteinDistance" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Metaphone" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DoubleMetaphone" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Abs" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveTimeFromDate" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiff" ), "A + B + C", BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.InitCap" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.UpperCase" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.LowerCase" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.MaskXML" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.UseCDATA" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveCR" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveLF" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveCRLF" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveTAB" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.GetOnlyDigits" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RemoveDigits" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.StringLen" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.LoadFileContentInBinary" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.AddTimeToDate" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.QuarterOfDate" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SubstituteVariable" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.UnescapeXML" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.EscapeHTML" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.UnescapeHTML" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.EscapeSQL" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiffWorking" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DatePlusMonths" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.CheckXmlFileWellFormed" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.CheckXmlWellFormed" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.GetFileEncoding" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DamerauLevenshtein" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.NeedlemanWunsch" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Jaro" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.JaroWinkler" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SoundEx" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RefinedSoundEx" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DatePlusHours" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DatePlusMinutes" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiffMsec" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiffSec" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiffMn" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.DateDiffHr" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.HourOfDay" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.MinuteOfHour" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.SecondOfMinute" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RoundCustom" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.RoundCustom2" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.AddSeconds" ), BaseMessages.getString( PKG, "CalculatorMetaFunction.CalcFunctions.Remainder" ), }; public static final int[] calcDefaultResultType = new int[ calc_desc.length ]; static { calcDefaultResultType[ CalculatorMetaFunction.CALC_NONE ] = ValueMetaInterface.TYPE_NONE; // Set field to constant value... calcDefaultResultType[ CalculatorMetaFunction.CALC_CONSTANT ] = ValueMetaInterface.TYPE_STRING; calcDefaultResultType[ CalculatorMetaFunction.CALC_COPY_OF_FIELD ] = ValueMetaInterface.TYPE_NONE; // A + B calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD ] = ValueMetaInterface.TYPE_NUMBER; // A - B calcDefaultResultType[ CalculatorMetaFunction.CALC_SUBTRACT ] = ValueMetaInterface.TYPE_NUMBER; // A * B calcDefaultResultType[ CalculatorMetaFunction.CALC_MULTIPLY ] = ValueMetaInterface.TYPE_NUMBER; // A / B calcDefaultResultType[ CalculatorMetaFunction.CALC_DIVIDE ] = ValueMetaInterface.TYPE_NUMBER; // A * A calcDefaultResultType[ CalculatorMetaFunction.CALC_SQUARE ] = ValueMetaInterface.TYPE_NUMBER; // SQRT( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_SQUARE_ROOT ] = ValueMetaInterface.TYPE_NUMBER; // 100 * A / B calcDefaultResultType[ CalculatorMetaFunction.CALC_PERCENT_1 ] = ValueMetaInterface.TYPE_NUMBER; // A - ( A * B / 100 ) calcDefaultResultType[ CalculatorMetaFunction.CALC_PERCENT_2 ] = ValueMetaInterface.TYPE_NUMBER; // A + ( A * B / 100 ) calcDefaultResultType[ CalculatorMetaFunction.CALC_PERCENT_3 ] = ValueMetaInterface.TYPE_NUMBER; // A + B * C calcDefaultResultType[ CalculatorMetaFunction.CALC_COMBINATION_1 ] = ValueMetaInterface.TYPE_NUMBER; // SQRT( A*A + B*B ) calcDefaultResultType[ CalculatorMetaFunction.CALC_COMBINATION_2 ] = ValueMetaInterface.TYPE_NUMBER; // ROUND( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_1 ] = ValueMetaInterface.TYPE_INTEGER; // ROUND( A , B ) calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_2 ] = ValueMetaInterface.TYPE_NUMBER; // STDROUND( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_STD_1 ] = ValueMetaInterface.TYPE_INTEGER; // STDROUND( A , B ) calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_STD_2 ] = ValueMetaInterface.TYPE_NUMBER; // CEIL( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_CEIL ] = ValueMetaInterface.TYPE_INTEGER; // FLOOR( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_FLOOR ] = ValueMetaInterface.TYPE_INTEGER; // Replace null values with another value calcDefaultResultType[ CalculatorMetaFunction.CALC_NVL ] = ValueMetaInterface.TYPE_NONE; // Add B days to date field A calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_DAYS ] = ValueMetaInterface.TYPE_DATE; // What is the year (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_YEAR_OF_DATE ] = ValueMetaInterface.TYPE_INTEGER; // What is the month (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_MONTH_OF_DATE ] = ValueMetaInterface.TYPE_INTEGER; // What is the day of year (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_DAY_OF_YEAR ] = ValueMetaInterface.TYPE_INTEGER; // What is the day of month (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_DAY_OF_MONTH ] = ValueMetaInterface.TYPE_INTEGER; // What is the day of week (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_DAY_OF_WEEK ] = ValueMetaInterface.TYPE_INTEGER; // What is the week of year (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_WEEK_OF_YEAR ] = ValueMetaInterface.TYPE_INTEGER; // What is the week of year (Integer) of a date ISO8601 style? calcDefaultResultType[ CalculatorMetaFunction.CALC_WEEK_OF_YEAR_ISO8601 ] = ValueMetaInterface.TYPE_INTEGER; // What is the year (Integer) of a date ISO8601 style? calcDefaultResultType[ CalculatorMetaFunction.CALC_YEAR_OF_DATE_ISO8601 ] = ValueMetaInterface.TYPE_INTEGER; // Byte to Hex encode string field A calcDefaultResultType[ CalculatorMetaFunction.CALC_BYTE_TO_HEX_ENCODE ] = ValueMetaInterface.TYPE_STRING; // Hex to Byte decode string field A calcDefaultResultType[ CalculatorMetaFunction.CALC_HEX_TO_BYTE_DECODE ] = ValueMetaInterface.TYPE_STRING; // Char to Hex encode string field A calcDefaultResultType[ CalculatorMetaFunction.CALC_CHAR_TO_HEX_ENCODE ] = ValueMetaInterface.TYPE_STRING; // Hex to Char decode string field A calcDefaultResultType[ CalculatorMetaFunction.CALC_HEX_TO_CHAR_DECODE ] = ValueMetaInterface.TYPE_STRING; // CRC32 of a file A calcDefaultResultType[ CalculatorMetaFunction.CALC_CRC32 ] = ValueMetaInterface.TYPE_INTEGER; // ADLER32 of a file A calcDefaultResultType[ CalculatorMetaFunction.CALC_ADLER32 ] = ValueMetaInterface.TYPE_INTEGER; // MD5 of a file A calcDefaultResultType[ CalculatorMetaFunction.CALC_MD5 ] = ValueMetaInterface.TYPE_STRING; // SHA1 of a file Al calcDefaultResultType[ CalculatorMetaFunction.CALC_SHA1 ] = ValueMetaInterface.TYPE_STRING; // LEVENSHTEIN_DISTANCE of string A and string B calcDefaultResultType[ CalculatorMetaFunction.CALC_LEVENSHTEIN_DISTANCE ] = ValueMetaInterface.TYPE_INTEGER; // METAPHONE of string A calcDefaultResultType[ CalculatorMetaFunction.CALC_METAPHONE ] = ValueMetaInterface.TYPE_STRING; // Double METAPHONE of string A calcDefaultResultType[ CalculatorMetaFunction.CALC_DOUBLE_METAPHONE ] = ValueMetaInterface.TYPE_STRING; // ABS( A ) calcDefaultResultType[ CalculatorMetaFunction.CALC_ABS ] = ValueMetaInterface.TYPE_INTEGER; // Remove time from field A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_TIME_FROM_DATE ] = ValueMetaInterface.TYPE_DATE; // DateA - DateB calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_DIFF ] = ValueMetaInterface.TYPE_INTEGER; // A + B +C calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD3 ] = ValueMetaInterface.TYPE_NUMBER; // InitCap(A) calcDefaultResultType[ CalculatorMetaFunction.CALC_INITCAP ] = ValueMetaInterface.TYPE_STRING; // UpperCase(A) calcDefaultResultType[ CalculatorMetaFunction.CALC_UPPER_CASE ] = ValueMetaInterface.TYPE_STRING; // LowerCase(A) calcDefaultResultType[ CalculatorMetaFunction.CALC_LOWER_CASE ] = ValueMetaInterface.TYPE_STRING; // MaskXML(A) calcDefaultResultType[ CalculatorMetaFunction.CALC_MASK_XML ] = ValueMetaInterface.TYPE_STRING; // CDATA(A) calcDefaultResultType[ CalculatorMetaFunction.CALC_USE_CDATA ] = ValueMetaInterface.TYPE_STRING; // REMOVE CR FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_CR ] = ValueMetaInterface.TYPE_STRING; // REMOVE LF FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_LF ] = ValueMetaInterface.TYPE_STRING; // REMOVE CRLF FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_CRLF ] = ValueMetaInterface.TYPE_STRING; // REMOVE TAB FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_TAB ] = ValueMetaInterface.TYPE_STRING; // GET ONLY DIGITS FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_GET_ONLY_DIGITS ] = ValueMetaInterface.TYPE_STRING; // REMOVE DIGITS FROM string A calcDefaultResultType[ CalculatorMetaFunction.CALC_REMOVE_DIGITS ] = ValueMetaInterface.TYPE_STRING; // LENGTH OF string A calcDefaultResultType[ CalculatorMetaFunction.CALC_STRING_LEN ] = ValueMetaInterface.TYPE_INTEGER; // LOAD FILE CONTENT IN BLOB calcDefaultResultType[ CalculatorMetaFunction.CALC_LOAD_FILE_CONTENT_BINARY ] = ValueMetaInterface.TYPE_BINARY; // ADD TIME TO A DATE calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_TIME_TO_DATE ] = ValueMetaInterface.TYPE_DATE; // What is the quarter (Integer) of a date? calcDefaultResultType[ CalculatorMetaFunction.CALC_QUARTER_OF_DATE ] = ValueMetaInterface.TYPE_INTEGER; // variable substitution in string calcDefaultResultType[ CalculatorMetaFunction.CALC_SUBSTITUTE_VARIABLE ] = ValueMetaInterface.TYPE_STRING; // unEscape XML calcDefaultResultType[ CalculatorMetaFunction.CALC_UNESCAPE_XML ] = ValueMetaInterface.TYPE_STRING; // escape HTML calcDefaultResultType[ CalculatorMetaFunction.CALC_ESCAPE_HTML ] = ValueMetaInterface.TYPE_STRING; // unEscape HTML calcDefaultResultType[ CalculatorMetaFunction.CALC_UNESCAPE_HTML ] = ValueMetaInterface.TYPE_STRING; // escape SQL calcDefaultResultType[ CalculatorMetaFunction.CALC_ESCAPE_SQL ] = ValueMetaInterface.TYPE_STRING; // Date A - Date B calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_WORKING_DIFF ] = ValueMetaInterface.TYPE_INTEGER; // Date A - B Months calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_MONTHS ] = ValueMetaInterface.TYPE_DATE; // XML file A well formed calcDefaultResultType[ CalculatorMetaFunction.CALC_CHECK_XML_FILE_WELL_FORMED ] = ValueMetaInterface.TYPE_BOOLEAN; // XML string A well formed calcDefaultResultType[ CalculatorMetaFunction.CALC_CHECK_XML_WELL_FORMED ] = ValueMetaInterface.TYPE_BOOLEAN; // get file encoding calcDefaultResultType[ CalculatorMetaFunction.CALC_GET_FILE_ENCODING ] = ValueMetaInterface.TYPE_STRING; calcDefaultResultType[ CalculatorMetaFunction.CALC_DAMERAU_LEVENSHTEIN ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_NEEDLEMAN_WUNSH ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_JARO ] = ValueMetaInterface.TYPE_NUMBER; calcDefaultResultType[ CalculatorMetaFunction.CALC_JARO_WINKLER ] = ValueMetaInterface.TYPE_NUMBER; calcDefaultResultType[ CalculatorMetaFunction.CALC_SOUNDEX ] = ValueMetaInterface.TYPE_STRING; calcDefaultResultType[ CalculatorMetaFunction.CALC_REFINED_SOUNDEX ] = ValueMetaInterface.TYPE_STRING; calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_HOURS ] = ValueMetaInterface.TYPE_DATE; calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_MINUTES ] = ValueMetaInterface.TYPE_DATE; calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_DIFF_MSEC ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_DIFF_SEC ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_DIFF_MN ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_DATE_DIFF_HR ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_HOUR_OF_DAY ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_MINUTE_OF_HOUR ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_SECOND_OF_MINUTE ] = ValueMetaInterface.TYPE_INTEGER; calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_CUSTOM_1 ] = ValueMetaInterface.TYPE_NUMBER; calcDefaultResultType[ CalculatorMetaFunction.CALC_ROUND_CUSTOM_2 ] = ValueMetaInterface.TYPE_NUMBER; calcDefaultResultType[ CalculatorMetaFunction.CALC_ADD_SECONDS] = ValueMetaInterface.TYPE_DATE; calcDefaultResultType[ CalculatorMetaFunction.CALC_REMAINDER ] = ValueMetaInterface.TYPE_NUMBER; } private String fieldName; private int calcType; private String fieldA; private String fieldB; private String fieldC; private int valueType; private int valueLength; private int valuePrecision; private String conversionMask; private String decimalSymbol; private String groupingSymbol; private String currencySymbol; private boolean removedFromResult; /** * @param fieldName out field name * @param calcType calculation type, see CALC_* set of constants defined * @param fieldA name of field "A" * @param fieldB name of field "B" * @param fieldC name of field "C" * @param valueType out value type * @param valueLength out value length * @param valuePrecision out value precision * @param conversionMask out value conversion mask * @param decimalSymbol out value decimal symbol * @param groupingSymbol out value grouping symbol * @param currencySymbol out value currency symbol */ public CalculatorMetaFunction( String fieldName, int calcType, String fieldA, String fieldB, String fieldC, int valueType, int valueLength, int valuePrecision, boolean removedFromResult, String conversionMask, String decimalSymbol, String groupingSymbol, String currencySymbol ) { this.fieldName = fieldName; this.calcType = calcType; this.fieldA = fieldA; this.fieldB = fieldB; this.fieldC = fieldC; this.valueType = valueType; this.valueLength = valueLength; this.valuePrecision = valuePrecision; this.removedFromResult = removedFromResult; this.conversionMask = conversionMask; this.decimalSymbol = decimalSymbol; this.groupingSymbol = groupingSymbol; this.currencySymbol = currencySymbol; } public CalculatorMetaFunction() { // all null } @Override public boolean equals( Object obj ) { if ( obj != null && ( obj.getClass().equals( this.getClass() ) ) ) { CalculatorMetaFunction mf = (CalculatorMetaFunction) obj; return ( getXML().equals( mf.getXML() ) ); } return false; } @Override public Object clone() { try { CalculatorMetaFunction retval = (CalculatorMetaFunction) super.clone(); return retval; } catch ( CloneNotSupportedException e ) { return null; } } public String getXML() { StringBuilder xml = new StringBuilder(); xml.append( " " ).append( XMLHandler.openTag( XML_TAG ) ).append( Const.CR ); xml.append( " " ).append( XMLHandler.addTagValue( "field_name", fieldName ) ); xml.append( " " ).append( XMLHandler.addTagValue( "calc_type", getCalcTypeDesc() ) ); xml.append( " " ).append( XMLHandler.addTagValue( "field_a", fieldA ) ); xml.append( " " ).append( XMLHandler.addTagValue( "field_b", fieldB ) ); xml.append( " " ).append( XMLHandler.addTagValue( "field_c", fieldC ) ); xml.append( " " ).append( XMLHandler.addTagValue( "value_type", ValueMetaFactory.getValueMetaName( valueType ) ) ); xml.append( " " ).append( XMLHandler.addTagValue( "value_length", valueLength ) ); xml.append( " " ).append( XMLHandler.addTagValue( "value_precision", valuePrecision ) ); xml.append( " " ).append( XMLHandler.addTagValue( "remove", removedFromResult ) ); xml.append( " " ).append( XMLHandler.addTagValue( "conversion_mask", conversionMask ) ); xml.append( " " ).append( XMLHandler.addTagValue( "decimal_symbol", decimalSymbol ) ); xml.append( " " ).append( XMLHandler.addTagValue( "grouping_symbol", groupingSymbol ) ); xml.append( " " ).append( XMLHandler.addTagValue( "currency_symbol", currencySymbol ) ); xml.append( " " ).append( XMLHandler.closeTag( XML_TAG ) ).append( Const.CR ); return xml.toString(); } public CalculatorMetaFunction( Node calcnode ) { fieldName = XMLHandler.getTagValue( calcnode, "field_name" ); calcType = getCalcFunctionType( XMLHandler.getTagValue( calcnode, "calc_type" ) ); fieldA = XMLHandler.getTagValue( calcnode, "field_a" ); fieldB = XMLHandler.getTagValue( calcnode, "field_b" ); fieldC = XMLHandler.getTagValue( calcnode, "field_c" ); valueType = ValueMetaFactory.getIdForValueMeta( XMLHandler.getTagValue( calcnode, "value_type" ) ); valueLength = Const.toInt( XMLHandler.getTagValue( calcnode, "value_length" ), -1 ); valuePrecision = Const.toInt( XMLHandler.getTagValue( calcnode, "value_precision" ), -1 ); removedFromResult = "Y".equalsIgnoreCase( XMLHandler.getTagValue( calcnode, "remove" ) ); conversionMask = XMLHandler.getTagValue( calcnode, "conversion_mask" ); decimalSymbol = XMLHandler.getTagValue( calcnode, "decimal_symbol" ); groupingSymbol = XMLHandler.getTagValue( calcnode, "grouping_symbol" ); currencySymbol = XMLHandler.getTagValue( calcnode, "currency_symbol" ); // Fix 2.x backward compatibility // The conversion mask was added in a certain revision. // Anything that we load from before then should get masks set to retain backward compatibility // if ( XMLHandler.getSubNode( calcnode, "conversion_mask" ) == null ) { fixBackwardCompatibility(); } } private void fixBackwardCompatibility() { if ( valueType == ValueMetaInterface.TYPE_INTEGER ) { if ( Utils.isEmpty( conversionMask ) ) { conversionMask = "0"; } if ( Utils.isEmpty( decimalSymbol ) ) { decimalSymbol = "."; } if ( Utils.isEmpty( groupingSymbol ) ) { groupingSymbol = ","; } } if ( valueType == ValueMetaInterface.TYPE_NUMBER ) { if ( Utils.isEmpty( conversionMask ) ) { conversionMask = "0.0"; } if ( Utils.isEmpty( decimalSymbol ) ) { decimalSymbol = "."; } if ( Utils.isEmpty( groupingSymbol ) ) { groupingSymbol = ","; } } } public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step, int nr ) throws KettleException { rep.saveStepAttribute( id_transformation, id_step, nr, "field_name", fieldName ); rep.saveStepAttribute( id_transformation, id_step, nr, "calc_type", getCalcTypeDesc() ); rep.saveStepAttribute( id_transformation, id_step, nr, "field_a", fieldA ); rep.saveStepAttribute( id_transformation, id_step, nr, "field_b", fieldB ); rep.saveStepAttribute( id_transformation, id_step, nr, "field_c", fieldC ); rep.saveStepAttribute( id_transformation, id_step, nr, "value_type", ValueMetaFactory.getValueMetaName( valueType ) ); rep.saveStepAttribute( id_transformation, id_step, nr, "value_length", valueLength ); rep.saveStepAttribute( id_transformation, id_step, nr, "value_precision", valuePrecision ); rep.saveStepAttribute( id_transformation, id_step, nr, "remove", removedFromResult ); rep.saveStepAttribute( id_transformation, id_step, nr, "conversion_mask", conversionMask ); rep.saveStepAttribute( id_transformation, id_step, nr, "decimal_symbol", decimalSymbol ); rep.saveStepAttribute( id_transformation, id_step, nr, "grouping_symbol", groupingSymbol ); rep.saveStepAttribute( id_transformation, id_step, nr, "currency_symbol", currencySymbol ); } public CalculatorMetaFunction( Repository rep, ObjectId id_step, int nr ) throws KettleException { fieldName = rep.getStepAttributeString( id_step, nr, "field_name" ); calcType = getCalcFunctionType( rep.getStepAttributeString( id_step, nr, "calc_type" ) ); fieldA = rep.getStepAttributeString( id_step, nr, "field_a" ); fieldB = rep.getStepAttributeString( id_step, nr, "field_b" ); fieldC = rep.getStepAttributeString( id_step, nr, "field_c" ); valueType = ValueMetaFactory.getIdForValueMeta( rep.getStepAttributeString( id_step, nr, "value_type" ) ); valueLength = (int) rep.getStepAttributeInteger( id_step, nr, "value_length" ); valuePrecision = (int) rep.getStepAttributeInteger( id_step, nr, "value_precision" ); removedFromResult = rep.getStepAttributeBoolean( id_step, nr, "remove" ); conversionMask = rep.getStepAttributeString( id_step, nr, "conversion_mask" ); decimalSymbol = rep.getStepAttributeString( id_step, nr, "decimal_symbol" ); groupingSymbol = rep.getStepAttributeString( id_step, nr, "grouping_symbol" ); currencySymbol = rep.getStepAttributeString( id_step, nr, "currency_symbol" ); // Fix 2.x backward compatibility // The conversion mask was added in a certain revision. // Anything that we load from before then should get masks set to retain backward compatibility // if ( rep instanceof KettleDatabaseRepository ) { KettleDatabaseRepository repository = (KettleDatabaseRepository) rep; if ( repository.findStepAttributeID( id_step, nr, "conversion_mask" ) != null ) { fixBackwardCompatibility(); } } } public static int getCalcFunctionType( String desc ) { for ( int i = 1; i < calc_desc.length; i++ ) { if ( calc_desc[ i ].equalsIgnoreCase( desc ) ) { return i; } } for ( int i = 1; i < calcLongDesc.length; i++ ) { if ( calcLongDesc[ i ].equalsIgnoreCase( desc ) ) { return i; } } return CALC_NONE; } public static String getCalcFunctionDesc( int type ) { if ( type < 0 || type >= calc_desc.length ) { return null; } return calc_desc[ type ]; } public static String getCalcFunctionLongDesc( int type ) { if ( type < 0 || type >= calcLongDesc.length ) { return null; } return calcLongDesc[ type ]; } public static int getCalcFunctionDefaultResultType( int type ) { if ( type < 0 || type >= calcDefaultResultType.length ) { return ValueMetaInterface.TYPE_NONE; } return calcDefaultResultType[ type ]; } /** * @return Returns the calcType. */ public int getCalcType() { return calcType; } /** * @param calcType The calcType to set. */ public void setCalcType( int calcType ) { this.calcType = calcType; } public String getCalcTypeDesc() { return getCalcFunctionDesc( calcType ); } public String getCalcTypeLongDesc() { return getCalcFunctionLongDesc( calcType ); } /** * @return Returns the fieldA. */ public String getFieldA() { return fieldA; } /** * @param fieldA The fieldA to set. */ public void setFieldA( String fieldA ) { this.fieldA = fieldA; } /** * @return Returns the fieldB. */ public String getFieldB() { return fieldB; } /** * @param fieldB The fieldB to set. */ public void setFieldB( String fieldB ) { this.fieldB = fieldB; } /** * @return Returns the fieldC. */ public String getFieldC() { return fieldC; } /** * @param fieldC The fieldC to set. */ public void setFieldC( String fieldC ) { this.fieldC = fieldC; } /** * @return Returns the fieldName. */ public String getFieldName() { return fieldName; } /** * @param fieldName The fieldName to set. */ public void setFieldName( String fieldName ) { this.fieldName = fieldName; } /** * @return Returns the valueLength. */ public int getValueLength() { return valueLength; } /** * @param valueLength The valueLength to set. */ public void setValueLength( int valueLength ) { this.valueLength = valueLength; } /** * @return Returns the valuePrecision. */ public int getValuePrecision() { return valuePrecision; } /** * @param valuePrecision The valuePrecision to set. */ public void setValuePrecision( int valuePrecision ) { this.valuePrecision = valuePrecision; } /** * @return Returns the valueType. */ public int getValueType() { return valueType; } /** * @param valueType The valueType to set. */ public void setValueType( int valueType ) { this.valueType = valueType; } /** * @return Returns the removedFromResult. */ public boolean isRemovedFromResult() { return removedFromResult; } /** * @param removedFromResult The removedFromResult to set. */ public void setRemovedFromResult( boolean removedFromResult ) { this.removedFromResult = removedFromResult; } /** * @return the conversionMask */ public String getConversionMask() { return conversionMask; } /** * @param conversionMask the conversionMask to set */ public void setConversionMask( String conversionMask ) { this.conversionMask = conversionMask; } /** * @return the decimalSymbol */ public String getDecimalSymbol() { return decimalSymbol; } /** * @param decimalSymbol the decimalSymbol to set */ public void setDecimalSymbol( String decimalSymbol ) { this.decimalSymbol = decimalSymbol; } /** * @return the groupingSymbol */ public String getGroupingSymbol() { return groupingSymbol; } /** * @param groupingSymbol the groupingSymbol to set */ public void setGroupingSymbol( String groupingSymbol ) { this.groupingSymbol = groupingSymbol; } /** * @return the currencySymbol */ public String getCurrencySymbol() { return currencySymbol; } /** * @param currencySymbol the currencySymbol to set */ public void setCurrencySymbol( String currencySymbol ) { this.currencySymbol = currencySymbol; } }