/** * loadCache is called automatically on startup of the cache factory, as a result of implementing * the CacheLoader interface. This should be used to load any data that needs loading, and to set * up variables. * * @throws InitializationException */ @Override public void loadCache(String ResourceName, String CacheName) throws InitializationException { // Variable definitions String tmpValue; // Get the number of key fields (the rest are treated as results) tmpValue = PropertyUtils.getPropertyUtils() .getDataCachePropertyValueDef(ResourceName, CacheName, "KeyFields", "None"); if (tmpValue.equals("None")) { // We will use calculate the default assuming 1 result field KeyFormFactor = 0; } else { try { KeyFormFactor = Integer.parseInt(tmpValue); } catch (NumberFormatException nfe) { message = "KeyFields entry for cache <" + getSymbolicName() + "> not numeric. Found value <" + tmpValue + ">"; OpenRate.getOpenRateFrameworkLog().error(message); throw new InitializationException(message, getSymbolicName()); } } // Now perform the base initialisation super.loadCache(ResourceName, CacheName); }
/** * Add a CPI (CustomerProductInstance) value into the CustomerCache * * @param custId The customer ID to add the product to * @param service The service of the product * @param subscription The subscription ID * @param prodID The product identifier * @param validFrom The start of the product validity * @param validTo The end of the product validity * @param orderId The JBilling order ID * @param orderLineId The JBilling order line ID * @param quantity The order line quantity */ public void addCPI( int custId, String service, String subscription, String prodID, long validFrom, long validTo, int orderId, int orderLineId, int quantity) { CustInfo tmpCustInfo; CustProductInfo tmpCPI; // See if we already have ID for this customer if (custIDCache.containsKey(custId)) { // Create the new entry for the customer ID tmpCustInfo = custIDCache.get(custId); tmpCPI = new CustProductInfo(); tmpCPI.Service = service; tmpCPI.Subscription = subscription; tmpCPI.ProductID = prodID; tmpCPI.UTCValidFrom = validFrom; tmpCPI.UTCValidTo = validTo - 1; // exclude the last second tmpCPI.OrderId = orderId; tmpCPI.OrderLineId = orderLineId; tmpCPI.Quantity = quantity; tmpCustInfo.CPI.add(tmpCustInfo.productCount, tmpCPI); tmpCustInfo.productCount++; } else { // Otherwise write an error and ignore it OpenRate.getOpenRateFrameworkLog() .error("Customer ID <" + custId + "> not found. Add CPI failed."); } }
/** Dumps the entire contents of the cache to the Log. */ protected void DumpMapData() { String Helper; Iterator<String> GroupIter; Iterator<SearchMap> PatternIterator; Iterator<String> CDIterator; SearchGroup tmpSearchGroup; SearchMap tmpSearchMap; String PrintHelper; int counter = 0; OpenRate.getOpenRateFrameworkLog() .info("Dumping Map Data for RegexMatchCache <" + getSymbolicName() + ">"); OpenRate.getOpenRateFrameworkLog().info("Groups:"); // Iterate thorough the entries in the group GroupIter = GroupCache.keySet().iterator(); while (GroupIter.hasNext()) { Helper = GroupIter.next(); OpenRate.getOpenRateFrameworkLog().info(" " + Helper); } // Now dump the data GroupIter = GroupCache.keySet().iterator(); while (GroupIter.hasNext()) { Helper = GroupIter.next(); OpenRate.getOpenRateFrameworkLog().info("Dumping group map data for <" + Helper + ">"); tmpSearchGroup = GroupCache.get(Helper); PatternIterator = tmpSearchGroup.SearchGroup.iterator(); while (PatternIterator.hasNext()) { OpenRate.getOpenRateFrameworkLog().info("===ENTRY " + counter + "==="); counter++; PrintHelper = " ("; tmpSearchMap = PatternIterator.next(); for (int i = 0; i < tmpSearchMap.matchPattern.length; i++) { PrintHelper = PrintHelper + "[" + tmpSearchMap.matchType[i] + ":" + tmpSearchMap.matchPattern[i] + ":" + tmpSearchMap.matchValue[i] + "] "; } // dump the result array PrintHelper += ") --> ("; CDIterator = tmpSearchMap.Results.iterator(); while (CDIterator.hasNext()) { PrintHelper = PrintHelper + CDIterator.next() + ","; } PrintHelper += ")"; OpenRate.getOpenRateFrameworkLog().info(PrintHelper); } } }
/** * Return the value of the balance group so that we are able to update it during the logic * processing. This is to make sure that we have all the information necessary when we start the * calculation. * * @param CustId The customer ID * @return The balance group */ public int getBalanceGroup(int CustId) { CustInfo tmpCustInfo; // See if we already have ID for this customer if (custIDCache.containsKey(CustId)) { // Get the product information tmpCustInfo = custIDCache.get(CustId); return tmpCustInfo.balanceGroup; } else { // Otherwise write an error and ignore it OpenRate.getOpenRateFrameworkLog() .error("Customer ID <" + CustId + "> not found. Lookup failed."); } return 0; }
/** * processControlEvent is the method that will be called when an event is received for a module * that has registered itself as a client of the External Control Interface * * @param Command - command that is understand by the client module * @param Init - we are performing initial configuration if true * @param Parameter - parameter for the command * @return The result string of the operation */ @Override public String processControlEvent(String Command, boolean Init, String Parameter) { SearchGroup tmpSearchGroup; Collection<String> tmpGroups; Iterator<String> GroupIter; String tmpGroupName; int Objects = 0; int ResultCode = -1; // Return the number of objects in the cache if (Command.equalsIgnoreCase(SERVICE_GROUP_COUNT)) { return Integer.toString(GroupCache.size()); } if (Command.equalsIgnoreCase(SERVICE_OBJECT_COUNT)) { tmpGroups = GroupCache.keySet(); GroupIter = tmpGroups.iterator(); while (GroupIter.hasNext()) { tmpGroupName = GroupIter.next(); tmpSearchGroup = GroupCache.get(tmpGroupName); Objects += tmpSearchGroup.SearchGroup.size(); } return Integer.toString(Objects); } // Return the number of objects in the cache if (Command.equalsIgnoreCase(SERVICE_DUMP_MAP)) { // onl< dump on a positive command if (Parameter.equalsIgnoreCase("true")) { DumpMapData(); } ResultCode = 0; } if (ResultCode == 0) { OpenRate.getOpenRateFrameworkLog() .debug(LogUtil.LogECICacheCommand(getSymbolicName(), Command, Parameter)); return "OK"; } else { return super.processControlEvent(Command, Init, Parameter); } }
/** * Get the products that are attached to the customer account, using the alias to locate the * account * * @param alias The alias to the customer account * @param service The service * @param subscription The subscription to get products for * @param CDRDate The date to retrieve the products for * @return The product list */ public ProductList getProducts(String alias, String service, String subscription, long CDRDate) { int custID; // See if we already have ID for this customer if (aliasCache.containsKey(alias)) { // Get the poid from the Alias custID = getCustId(alias, CDRDate); // Get the products return getProducts(custID, service, subscription, CDRDate); } else { // We could find no alias OpenRate.getOpenRateFrameworkLog().error("Alias <" + alias + "> not found. Lookup failed."); // Just return null return null; } }
/** * processControlEvent is the method that will be called when an event is received for a module * that has registered itself as a client of the External Control Interface * * @param Command - command that is understand by the client module * @param Init - we are performing initial configuration if true * @param Parameter - parameter for the command * @return The result string of the operation */ @Override public String processControlEvent(String Command, boolean Init, String Parameter) { int ResultCode = -1; // Set the status of the invalidate duplicates if (Command.equalsIgnoreCase(SERVICE_INVALIDATE_DUPLICATE)) { if (Parameter.equalsIgnoreCase("true")) { // Set the value invalidateOnDuplicate = true; // done ResultCode = 0; } else if (Parameter.equalsIgnoreCase("false")) { // Set the value invalidateOnDuplicate = false; // done ResultCode = 0; } else if (Parameter.equals("")) { // return the current state if (invalidateOnDuplicate) { return "true"; } else { return "false"; } } } if (ResultCode == 0) { OpenRate.getOpenRateFrameworkLog() .debug(LogUtil.LogECICacheCommand(getSymbolicName(), Command, Parameter)); return "OK"; } else { return super.processControlEvent(Command, Init, Parameter); } }
/** * Add an alias to the customer cache. An alias is a representation of any identifier that can be * used to locate the account. Note that we exclude the last second of the validity period to * avoid issues with overlapping periods that end and start on the same second (e.g. old validity * ends on 1st Sept @ 00:00 and the new one starts on 1st Sept @ 00:00) * * @param alias The identifier that should be used to locate the account * @param custId The account that should be located * @param validFrom The start date of the validity * @param validTo The end date of the validity */ public void addAlias(String alias, int custId, long validFrom, long validTo) { validityNode NewNode; validityNode tmpValidityNode; validityNode tmpValidityNextNode; boolean insertedEntry = false; // Check that the valid to is after the valid from if (validFrom > validTo) { // Otherwise write an error and ignore it OpenRate.getOpenRateFrameworkLog() .error( "Alias ID <" + alias + "> validity period from <" + validFrom + "> is after validity period to <" + validTo + ">. Ignoring."); return; } // Now add the validity segment into the ArrayList if (!aliasCache.containsKey(alias)) { // We do not know this alias - Create the new ArrayList tmpValidityNode = new validityNode(); // tmpValidityNode.ID = ID; tmpValidityNode.TimeFrom = validFrom; tmpValidityNode.TimeTo = validTo - 1; // Exlude the last second tmpValidityNode.Result = custId; tmpValidityNode.child = null; // NewNode.SubId = subID; // Add in the new node aliasCache.put(alias, tmpValidityNode); // mark that we have done the work insertedEntry = true; } else { // Recover the validity map that there is tmpValidityNode = aliasCache.get(alias); // now run down the validity periods until we find the right position while (tmpValidityNode != null) { tmpValidityNextNode = tmpValidityNode.child; // Search for the place that will accommodate the start of the segment if (validFrom > tmpValidityNode.TimeTo) { if (tmpValidityNextNode == null) { // Insert at the end of the list NewNode = new validityNode(); // tmpValidityNode.ID = ID; tmpValidityNode.child = NewNode; NewNode.TimeFrom = validFrom; NewNode.TimeTo = validTo - 1; // Exclude the last second NewNode.Result = custId; // NewNode.SubId = subID; // mark that we have done the work insertedEntry = true; } else { if (validTo < tmpValidityNextNode.TimeFrom) { // insert into the middle of the list NewNode = new validityNode(); NewNode.child = tmpValidityNode.child; tmpValidityNode.child = NewNode; // tmpValidityNode.ID = ID; NewNode.TimeFrom = validFrom; NewNode.TimeTo = validTo; NewNode.Result = custId; // NewNode.SubId = subID; // mark that we have done the work insertedEntry = true; } } } // Move down the map tmpValidityNode = tmpValidityNode.child; } } // see if we inserted correctly if (!insertedEntry) { if (invalidateOnDuplicate) { // remove the whole key that we couldn't add. aliasCache.remove(alias); OpenRate.getOpenRateFrameworkLog() .error( "Alias ID <" + alias + "> already exists for time <" + validFrom + "-" + validTo + ">. Removed key."); } else { // Otherwise write an error and ignore it OpenRate.getOpenRateFrameworkLog() .error( "Alias ID <" + alias + "> already exists for time <" + validFrom + "-" + validTo + ">"); } } }
/** Load the data from the defined Data Source DB */ @Override public void loadDataFromDB() throws InitializationException { int custId; String orderId; String orderLineId; String alias; String description; String prodName; String service; String subscription; int custLoaded = 0; String tmpStartDate; String tmpEndDate; long startDate = 0; long endDate = 0; String tmpQuantity; int quantity; // Log that we are starting the loading OpenRate.getOpenRateFrameworkLog() .info("Starting Customer Cache Loading from DB for <" + getSymbolicName() + ">"); // Try to open the DS JDBCcon = DBUtil.getConnection(cacheDataSourceName); // Now prepare the statements prepareStatements(); // Execute the query try { mrs = StmtCustomerDataSelectQuery.executeQuery(); } catch (SQLException ex) { message = "Error performing SQL for retieving Customer data. message <" + ex.getMessage() + ">"; throw new InitializationException(message, ex, getSymbolicName()); } // loop through the results for the customer alias cache try { mrs.beforeFirst(); while (mrs.next()) { custLoaded++; orderId = mrs.getString(1); custId = mrs.getInt(2); orderLineId = mrs.getString(3); description = mrs.getString(4); tmpStartDate = mrs.getString(5); tmpEndDate = mrs.getString(6); tmpQuantity = mrs.getString(7); // parse the description prodName = getProduct(description); alias = getAlias(description); service = getService(description); subscription = getSubscription(description); if ((prodName == null) | (alias == null) | (service == null) | (subscription == null)) { OpenRate.getOpenRateFrameworkLog() .warning( "Record <" + description + "> skipped for customer <" + custId + "> order <" + orderId + ">."); continue; } // parse the start date try { if (tmpStartDate == null) { startDate = CommonConfig.LOW_DATE; } else { startDate = conv.convertInputDateToUTC(tmpStartDate); } } catch (ParseException ex) { OpenRate.getOpenRateFrameworkLog() .error( "Start Date format for record <" + custLoaded + "> are not correct. Date <" + tmpStartDate + ">, format <" + conv.getInputDateFormat() + "> order <" + orderId + ">. Data discarded."); } // parse the end date try { if (tmpEndDate == null) { endDate = CommonConfig.HIGH_DATE; } else { endDate = conv.convertInputDateToUTC(tmpEndDate); } } catch (ParseException ex) { OpenRate.getOpenRateFrameworkLog() .error( "End Date format for record <" + custLoaded + "> are not correct. Date <" + tmpEndDate + ">, format <" + conv.getInputDateFormat() + "> order <" + orderId + ">. Data discarded."); } // parse the Quantity quantity = Integer.parseInt(tmpQuantity); // print the information to the log OpenRate.getOpenRateFrameworkLog() .info( "Adding service ID <" + alias + "> to account <" + custId + "> with product <" + prodName + "> validity <" + tmpStartDate + " (" + startDate + ") - " + tmpEndDate + " (" + endDate + ")>, Qty: <" + quantity + "> order <" + orderId + ">."); // Add the map addAlias(alias, custId, startDate, endDate); addCustId(custId, CommonConfig.LOW_DATE, CommonConfig.HIGH_DATE, 0); addCPI( custId, service, subscription, prodName, startDate, endDate, Integer.parseInt(orderId), Integer.parseInt(orderLineId), quantity); } } catch (SQLException ex) { message = "Error opening Customer Data for <" + cacheDataSourceName + ">"; throw new InitializationException(message, ex, getSymbolicName()); } // Close down stuff try { mrs.close(); StmtCustomerDataSelectQuery.close(); JDBCcon.close(); } catch (SQLException ex) { message = "Error closing Result Set for Customer information from <" + cacheDataSourceName + ">"; throw new InitializationException(message, ex, getSymbolicName()); } OpenRate.getOpenRateFrameworkLog() .info("Customer Cache Data Loading completed from <" + cacheDataSourceName + ">"); OpenRate.getOpenRateFrameworkLog().info("Products Loaded: " + custLoaded); }
/** * Load the data from the defined Data Source * * @throws OpenRate.exception.InitializationException */ @Override public void loadDataFromDB() throws InitializationException { int ColumnIdx; int ColumnCount; int ConfigsLoaded = 0; String Group; ResultSetMetaData Rsmd; String[] SearchMapFields; int ResultFormFactor = 0; ArrayList<String> tmpResultList; // Find the location of the zone configuration file OpenRate.getOpenRateFrameworkLog() .info("Starting Regex Match Cache Loading from DB for <" + getSymbolicName() + ">"); // Try to open the DS JDBCcon = DBUtil.getConnection(cacheDataSourceName); // Now prepare the statements prepareStatements(); // Execute the query try { mrs = StmtCacheDataSelectQuery.executeQuery(); } catch (SQLException ex) { message = "Error performing SQL for retrieving Regex Match data in module <" + getSymbolicName() + ">. message <" + ex.getMessage() + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } // loop through the results for the customer login cache try { Rsmd = mrs.getMetaData(); ColumnCount = Rsmd.getColumnCount(); // Read the form factor from the first entry, and then make sure // that we always get this if (ResultFormFactor == 0) { // Check that this is a form factor we are able to use. There // must be at least 3 fields for us to be able to work with // the record: // - Group identifier // - Some fields to compare (min 1) // - a result if (ColumnCount < 3) { // we're not going to be able to use this message = "You must define at least 3 entries in the record, you have defined <" + ColumnCount + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } // Do we have a defined form factor? if (KeyFormFactor == 0) { // If we have not been given a key form factor, assume the result factor is 1 ResultFormFactor = 1; KeyFormFactor = ColumnCount - ResultFormFactor - 1; message = "Using default key factor for regex cache <" + cacheDataSourceName + ">. Assuming Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } else { // Use the given factor ResultFormFactor = ColumnCount - KeyFormFactor - 1; if (ResultFormFactor < 1) { // Makes no sense to start if we don't give any results message = "Error in module <" + cacheDataSourceName + ">. Key fields >= total columns. Got KeyFields <" + KeyFormFactor + "> and columns <" + ColumnCount + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } message = "Using defined key factor for regex cache <" + getSymbolicName() + ">. Using Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } // Start the loading mrs.beforeFirst(); while (mrs.next()) { ConfigsLoaded++; Group = mrs.getString(1); SearchMapFields = new String[KeyFormFactor]; // create the array to transfer the columns into the map for (ColumnIdx = 1; ColumnIdx < KeyFormFactor + 1; ColumnIdx++) { SearchMapFields[ColumnIdx - 1] = mrs.getString(ColumnIdx + 1); } tmpResultList = new ArrayList<>(); for (ColumnIdx = KeyFormFactor + 1; ColumnIdx < (ResultFormFactor + KeyFormFactor + 1); ColumnIdx++) { tmpResultList.add(mrs.getString(ColumnIdx + 1)); } // Add the map addEntry(Group.intern(), SearchMapFields, tmpResultList); // Update to the log file if ((ConfigsLoaded % loadingLogNotificationStep) == 0) { message = "Regex Map Data Loading: <" + ConfigsLoaded + "> configurations loaded for <" + getSymbolicName() + "> from <" + cacheDataSourceName + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } } catch (SQLException ex) { message = "Error opening Search Map Data for <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, ex, getSymbolicName()); } catch (NullPointerException ex) { message = "Error opening Search Map Data for <" + getSymbolicName() + "> in config <" + ConfigsLoaded + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, ex, getSymbolicName()); } // Close down stuff try { mrs.close(); StmtCacheDataSelectQuery.close(); JDBCcon.close(); } catch (SQLException ex) { message = "Error closing Search Map Data connection for <" + cacheDataSourceName + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } message = "Regex Map Data Loading completed. <" + ConfigsLoaded + "> configuration lines loaded for <" + getSymbolicName() + "> from <" + cacheDataSourceName + ">"; OpenRate.getOpenRateFrameworkLog().info(message); }
/** * Load the data from the defined file * * @throws OpenRate.exception.InitializationException */ @Override public void loadDataFromFile() throws InitializationException { // Variable declarations BufferedReader inFile; int MapsLoaded = 0; String[] MapEntryFields; String[] SearchMapFields; String tmpFileRecord; String Group; int ColumnCount; int ColumnIdx; int ResultFormFactor = 0; ArrayList<String> tmpResultList; // Find the location of the configuration file OpenRate.getOpenRateFrameworkLog() .info("Starting Regex Match Cache Loading from file for <" + getSymbolicName() + ">"); // Try to open the file try { inFile = new BufferedReader(new FileReader(cacheDataFile)); } catch (FileNotFoundException ex) { message = "Application is not able to read file : <" + cacheDataFile + ">"; OpenRate.getOpenRateFrameworkLog().error(message); throw new InitializationException(message, ex, getSymbolicName()); } // File open, now get the stuff try { while (inFile.ready()) { tmpFileRecord = inFile.readLine(); if ((tmpFileRecord.startsWith("#")) | tmpFileRecord.trim().equals("")) { // comment do not load } else { MapsLoaded++; MapEntryFields = tmpFileRecord.split(";"); ColumnCount = MapEntryFields.length; // Read the form factor from the first entry, and then make sure // that we always get this if (ResultFormFactor == 0) { // Check that this is a form factor we are able to use. There // must be at least 3 fields for us to be able to work with // the record: // - Group identifier // - Some fields to compare (min 1) // - a result if (ColumnCount < 3) { // we're not going to be able to use this message = "You must define at least 3 entries in the record, you have defined <" + ColumnCount + "> in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } // Do we have a defined form factor? if (KeyFormFactor == 0) { // If we have not been given a key form factor, assume the result factor is 1 ResultFormFactor = 1; KeyFormFactor = ColumnCount - ResultFormFactor - 1; message = "Using default key factor for regex cache <" + cacheDataFile + ">. Assuming Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + "> in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } else { // Use the given factor ResultFormFactor = ColumnCount - KeyFormFactor - 1; message = "Using defined key factor for regex cache <" + cacheDataFile + ">. Using Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + "> in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } // Check that we are always getting the same form factor if (MapEntryFields.length == (KeyFormFactor + ResultFormFactor + 1)) { // Add the row, after extracting the group and the result Group = MapEntryFields[0]; SearchMapFields = new String[KeyFormFactor]; for (ColumnIdx = 0; ColumnIdx < KeyFormFactor; ColumnIdx++) { SearchMapFields[ColumnIdx] = MapEntryFields[ColumnIdx + 1]; } tmpResultList = new ArrayList<>(); for (ColumnIdx = KeyFormFactor; ColumnIdx < (ResultFormFactor + KeyFormFactor); ColumnIdx++) { tmpResultList.add(MapEntryFields[ColumnIdx + 1]); } // Add the map addEntry(Group.intern(), SearchMapFields, tmpResultList); } else { // Error because the form factor changed message = "Form Factor should be Key = <" + Integer.toString(KeyFormFactor) + "> + Payload = <" + Integer.toString(ResultFormFactor) + ">, but received <" + MapEntryFields.length + "> in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().error(message); throw new InitializationException(message, getSymbolicName()); } // Update to the log file if ((MapsLoaded % loadingLogNotificationStep) == 0) { message = "Regex Map Data Loading: <" + MapsLoaded + "> configurations loaded for <" + getSymbolicName() + "> from <" + cacheDataFile + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } } } catch (IOException ex) { message = "Error reading input file <" + cacheDataFile + "> in record <" + MapsLoaded + ">. IO Error."; OpenRate.getOpenRateFrameworkLog().fatal(message); } catch (ArrayIndexOutOfBoundsException ex) { message = "Error reading input file <" + cacheDataFile + "> in record <" + MapsLoaded + ">. Malformed Record."; OpenRate.getOpenRateFrameworkLog().fatal(message); } catch (NullPointerException npe) { message = "Error reading input file <" + cacheDataFile + "> in record <" + MapsLoaded + ">. Malformed Record in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); } finally { try { inFile.close(); } catch (IOException ex) { message = "Error closing input file <" + cacheDataFile + "> in module <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().error(message, ex); } } message = "Regex Map Data Loading completed. <" + MapsLoaded + "> configuration lines loaded for <" + getSymbolicName() + "> from <" + cacheDataFile + ">"; OpenRate.getOpenRateFrameworkLog().info(message); }
/** * Evaluate an input against the search group. This is the generalised from which you may want to * create specialised versions for a defined number of parameters, for reasons of performance. * * <p>This function returns only the first match. * * @param Group The Regular expression group to search * @param Parameters The list of fields to search * @return Result The result of the search as a SearchMap object */ private SearchMap getMatchingSearchResult(String Group, String[] Parameters) { int i; SearchGroup tmpSearchGroup; SearchMap tmpSearchMap; Pattern tmpPattern; boolean Found; double tmpParamValue; // recover the object tmpSearchGroup = GroupCache.get(Group); if (tmpSearchGroup == null) { // Return a default value return null; } else { // Iterate thorough the entries in the group Iterator<SearchMap> GroupIter = tmpSearchGroup.SearchGroup.listIterator(); while (GroupIter.hasNext()) { tmpSearchMap = GroupIter.next(); // Initialise the found flag and the counter Found = true; i = 0; // Now check the elements of the map while ((i < Parameters.length) & Found) { switch (tmpSearchMap.matchType[i]) { // Regex inclusion case case 0: { tmpPattern = tmpSearchMap.matchPattern[i]; if (Parameters[i] == null) { // we cannot match on null values - warn once and out... OpenRate.getOpenRateFrameworkLog() .warning( "Null value found in regex match on parameter <" + i + "> in module <" + getSymbolicName() + ">"); return null; } if (!tmpPattern.matcher(Parameters[i]).matches()) { // We did not get a match, move on Found = false; } break; } // Regex exclusion case case 6: { tmpPattern = tmpSearchMap.matchPattern[i]; if (tmpPattern.matcher(Parameters[i]).matches()) { // We did not get a match, move on Found = false; } break; } // "=" case case 1: { tmpParamValue = Double.parseDouble(Parameters[i]); if (tmpSearchMap.matchValue[i] != tmpParamValue) { // We did not get a match, move on Found = false; } break; } // ">" case case 2: { tmpParamValue = Double.parseDouble(Parameters[i]); if (tmpParamValue <= tmpSearchMap.matchValue[i]) { // We did not get a match, move on Found = false; } break; } // "<" case case 3: { tmpParamValue = Double.parseDouble(Parameters[i]); if (tmpParamValue >= tmpSearchMap.matchValue[i]) { // We did not get a match, move on Found = false; } break; } // ">=" case case 4: { tmpParamValue = Double.parseDouble(Parameters[i]); if (tmpParamValue < tmpSearchMap.matchValue[i]) { // We did not get a match, move on Found = false; } break; } // "<=" case case 5: { tmpParamValue = Double.parseDouble(Parameters[i]); if (tmpParamValue > tmpSearchMap.matchValue[i]) { // We did not get a match, move on Found = false; } break; } } // Increment the loop counter i++; } if (Found) { return tmpSearchMap; } } // Return a default value - we found nothing return null; } }
/** * Add a value into the Regex Map Cache, defining the result value that should be returned in the * case of a match. The order of evaluation of the items in the group is the order that they are * defined, but it would be a simple task to order them by some value after loading. * * @param Group The Regex group to add this pattern to * @param fields The list of fields to add to the group * @param ResultList The list of result fields to add * @throws OpenRate.exception.InitializationException */ private void addEntry(String Group, String[] fields, ArrayList<String> ResultList) throws InitializationException { int i; SearchMap tmpSearchMap; SearchGroup tmpSearchGroup; String Helper; String FirstChar; String SecondChar; String valueToParse; String[] checkedFields; ArrayList<String> checkedResultList; // Allow the user to check the input fields checkedFields = validateSearchMap(fields); // Allow the user to check the return fields checkedResultList = validateResultList(ResultList); // See if we already know this group, if not add it if (GroupCache.containsKey(Group)) { // Get the existing value tmpSearchGroup = GroupCache.get(Group); } else { // We don't know it, so add it tmpSearchGroup = new SearchGroup(); tmpSearchGroup.SearchGroup = new ArrayList<>(); GroupCache.put(Group, tmpSearchGroup); } // Create the new search Object. tmpSearchMap = new SearchMap(); // Compile and add the search map tmpSearchMap.matchPattern = new Pattern[checkedFields.length]; tmpSearchMap.matchType = new int[checkedFields.length]; tmpSearchMap.matchValue = new double[checkedFields.length]; for (i = 0; i < fields.length; i++) { // get the short version of the string for understanding what it is Helper = fields[i].replaceAll(" ", "") + " "; FirstChar = Helper.substring(0, 1); SecondChar = Helper.substring(1, 2); if ((FirstChar.equals("<")) | (FirstChar.equals(">")) | (FirstChar.equals("="))) { // try to parse for simple numerical comparison if (FirstChar.equals("=")) { tmpSearchMap.matchType[i] = 1; valueToParse = Helper.substring(1).trim(); try { tmpSearchMap.matchValue[i] = Double.parseDouble(valueToParse); } catch (NumberFormatException ex) { throw new InitializationException( "Could not parse value <" + valueToParse + "> as a double value", getSymbolicName()); } continue; } if (FirstChar.equals(">")) { if (SecondChar.equals("=")) { tmpSearchMap.matchType[i] = 4; valueToParse = Helper.substring(2).trim(); try { tmpSearchMap.matchValue[i] = Double.parseDouble(valueToParse); } catch (NumberFormatException ex) { throw new InitializationException( "Could not parse value <" + valueToParse + "> as a double value", getSymbolicName()); } continue; } else { // we got this far, must be just ">" tmpSearchMap.matchType[i] = 2; valueToParse = Helper.substring(1).trim(); try { tmpSearchMap.matchValue[i] = Double.parseDouble(valueToParse); } catch (NumberFormatException ex) { throw new InitializationException( "Could not parse value <" + valueToParse + "> as a double value", getSymbolicName()); } continue; } } if (FirstChar.equals("<")) { if (SecondChar.equals("=")) { tmpSearchMap.matchType[i] = 5; valueToParse = Helper.substring(2).trim(); try { tmpSearchMap.matchValue[i] = Double.parseDouble(valueToParse); } catch (NumberFormatException ex) { throw new InitializationException( "Could not parse value <" + valueToParse + "> as a double value", getSymbolicName()); } } else { // we got this far, must be just "<" tmpSearchMap.matchType[i] = 3; valueToParse = Helper.substring(1).trim(); try { tmpSearchMap.matchValue[i] = Double.parseDouble(valueToParse); } catch (NumberFormatException ex) { throw new InitializationException( "Could not parse value <" + valueToParse + "> as a double value", getSymbolicName()); } } } } else { if (FirstChar.equals("!")) { // This is a regex negation, remove the ! and set the flag and regex // for the rest tmpSearchMap.matchPattern[i] = Pattern.compile(fields[i].substring(1)); tmpSearchMap.matchType[i] = 6; } else { // if we got this far it is Real Regex inclusion try { tmpSearchMap.matchPattern[i] = Pattern.compile(fields[i]); } catch (PatternSyntaxException pse) { message = "Error compiling regex pattern <" + fields[i] + "> in module <" + getSymbolicName() + ">. message <" + pse.getMessage() + ">"; OpenRate.getOpenRateFrameworkLog().error(message); throw new InitializationException(message, getSymbolicName()); } tmpSearchMap.matchType[i] = 0; } } } tmpSearchMap.Results = checkedResultList; tmpSearchGroup.SearchGroup.add(tmpSearchMap); }
/** * Load the data from the defined Data Source Method * * @throws OpenRate.exception.InitializationException */ @Override public void loadDataFromMethod() throws InitializationException { int ColumnIdx; int ColumnCount; int ConfigsLoaded = 0; String Group; String[] SearchMapFields; int ResultFormFactor = 0; ArrayList<String> tmpMethodResult; ArrayList<String> tmpResultList; // Find the location of the zone configuration file OpenRate.getOpenRateFrameworkLog() .info("Starting Regex Match Cache Loading from Method for <" + getSymbolicName() + ">"); // Execute the user domain method Collection<ArrayList<String>> methodLoadResultSet; methodLoadResultSet = getMethodData(getSymbolicName(), CacheMethodName); if (methodLoadResultSet == null) { OpenRate.getOpenRateFrameworkLog() .warning( "No cache data returned by method <" + CacheMethodName + "> in cache <" + getSymbolicName() + ">"); } else { Iterator<ArrayList<String>> methodDataToLoadIterator = methodLoadResultSet.iterator(); while (methodDataToLoadIterator.hasNext()) { tmpMethodResult = methodDataToLoadIterator.next(); ConfigsLoaded++; ColumnCount = tmpMethodResult.size(); // Read the form factor from the first entry, and then make sure // that we always get this if (ResultFormFactor == 0) { // Check that this is a form factor we are able to use. There // must be at least 3 fields for us to be able to work with // the record: // - Group identifier // - Some fields to compare (min 1) // - a result if (ColumnCount < 3) { // we're not going to be able to use this message = "You must define at least 3 entries in the record, you have defined <" + ColumnCount + ">"; OpenRate.getOpenRateFrameworkLog().fatal(message); throw new InitializationException(message, getSymbolicName()); } // Do we have a defined form factor? if (KeyFormFactor == 0) { // If we have not been given a key form factor, assume the result factor is 1 ResultFormFactor = 1; KeyFormFactor = ColumnCount - ResultFormFactor - 1; message = "Using default key factor for regex cache <" + cacheDataSourceName + ">. Assuming Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } else { // Use the given factor ResultFormFactor = ColumnCount - KeyFormFactor - 1; message = "Using defined key factor for regex cache <" + cacheDataSourceName + ">. Using Key = <" + Integer.toString(KeyFormFactor) + "> and Result = <" + Integer.toString(ResultFormFactor) + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } // Check that we are always getting the same form factor if (ColumnCount == (KeyFormFactor + ResultFormFactor + 1)) { // Add the row, after extracting the group and the result Group = tmpMethodResult.get(0); // Get the search map fields SearchMapFields = new String[KeyFormFactor]; for (ColumnIdx = 0; ColumnIdx < KeyFormFactor; ColumnIdx++) { SearchMapFields[ColumnIdx] = tmpMethodResult.get(ColumnIdx + 1); } tmpResultList = new ArrayList<>(); for (ColumnIdx = KeyFormFactor; ColumnIdx < (ResultFormFactor + KeyFormFactor); ColumnIdx++) { tmpResultList.add(tmpMethodResult.get(ColumnIdx + 1)); } // Add the map addEntry(Group.intern(), SearchMapFields, tmpResultList); // Update to the log file if ((ConfigsLoaded % loadingLogNotificationStep) == 0) { message = "Regex Map Data Loading: <" + ConfigsLoaded + "> configurations loaded for <" + getSymbolicName() + "> from <" + cacheDataSourceName + ">"; OpenRate.getOpenRateFrameworkLog().info(message); } } else { // Error because the form factor changed message = "Form Factor should be Key = <" + Integer.toString(KeyFormFactor) + "> + Payload = <" + Integer.toString(ResultFormFactor) + ">, but received <" + tmpMethodResult.size() + ">"; OpenRate.getOpenRateFrameworkLog().error(message); throw new InitializationException(message, getSymbolicName()); } } } message = "Regex Map Data Loading completed. " + ConfigsLoaded + " configuration lines loaded for <" + getSymbolicName() + ">"; OpenRate.getOpenRateFrameworkLog().info(message); }