/* ====================================================================
* Limited Evaluation License:
*
* This software is open source, but licensed. The license with this package
* is an evaluation license, which may not be used for productive systems. If
* you want a full license, please contact us.
*
* The exclusive owner of this work is the OpenRate project.
* This work, including all associated documents and components
* is Copyright of the OpenRate project 2006-2015.
*
* The following restrictions apply unless they are expressly relaxed in a
* contractual agreement between the license holder or one of its officially
* assigned agents and you or your organisation:
*
* 1) This work may not be disclosed, either in full or in part, in any form
* electronic or physical, to any third party. This includes both in the
* form of source code and compiled modules.
* 2) This work contains trade secrets in the form of architecture, algorithms
* methods and technologies. These trade secrets may not be disclosed to
* third parties in any form, either directly or in summary or paraphrased
* form, nor may these trade secrets be used to construct products of a
* similar or competing nature either by you or third parties.
* 3) This work may not be included in full or in part in any application.
* 4) You may not remove or alter any proprietary legends or notices contained
* in or on this work.
* 5) This software may not be reverse-engineered or otherwise decompiled, if
* you received this work in a compiled form.
* 6) This work is licensed, not sold. Possession of this software does not
* imply or grant any right to you.
* 7) You agree to disclose any changes to this work to the copyright holder
* and that the copyright holder may include any such changes at its own
* discretion into the work
* 8) You agree not to derive other works from the trade secrets in this work,
* and that any such derivation may make you liable to pay damages to the
* copyright holder
* 9) You agree to use this software exclusively for evaluation purposes, and
* that you shall not use this software to derive commercial profit or
* support your business or personal activities.
*
* This software is provided "as is" and any expressed or impled warranties,
* including, but not limited to, the impled warranties of merchantability
* and fitness for a particular purpose are disclaimed. In no event shall
* The OpenRate Project or its officially assigned agents be liable to any
* direct, indirect, incidental, special, exemplary, or consequential damages
* (including but not limited to, procurement of substitute goods or services;
* Loss of use, data, or profits; or any business interruption) however caused
* and on theory of liability, whether in contract, strict liability, or tort
* (including negligence or otherwise) arising in any way out of the use of
* this software, even if advised of the possibility of such damage.
* This software contains portions by The Apache Software Foundation, Robert
* Half International.
* ====================================================================
*/
package OpenRate.cache;
import OpenRate.OpenRate;
import OpenRate.db.DBUtil;
import OpenRate.exception.InitializationException;
import OpenRate.lang.ProductList;
import OpenRate.utils.PropertyUtils;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* This class implements a cache of customer information for use in
* rating based on product instances. No product history is kept, and therefore
* rating can only be done at the current state of the information. This means
* that this class is of limited value for rating delayed usage, as it is not
* guaranteed that the record will be rated using the products that were in
* use at the time of the record creation. If you need a fully historicised
* version, use the "CustomerCacheAudited" cache instead.
*
* The customer information can be recovered from either files or DataBase
* data sources.
*
* There are some limitations in this cache implementation for simplicity, which
* are not present in the CustomerCacheAudited module:
* - Aliases are not time bound. This means that an alias can only ever be
* attached to one account and no re-use can be permitted. A common way of
* overcoming this limitation is to lookup the external key in an instance
* of a "ValiditySegmentCache" to perform a translation from the external
* key to the internal key, and then use the internal key as the alias.
* - Subscriptions are not supported. That means that for instance, you cannot
* own more than one instance of a real-life level product, as there is
* no way of partitioning products to aliases. This has the effect of "mixing"
* all the products that an account has for all of the aliases. The only
* level of partitioning that is available is at Service level. This means
* that a product can be assigned a "Service", and for rating purposes, only
* products matching a particular service are recovered.
*
* ------------------------------ File Interface -------------------------------
*
* The verbs in the file are:
*
* 01 = Add Customer Account
* 02 = Add Customer Product
* 03 = Modify Customer Product
* 04 = Change Customer Identifier
* 05 = Add Alias
* 06 = Add/Modify ERA
*
* Verb descriptions:
*
* 01, Add Customer Account
* Record format:
* 01;CustomerIdentifier;ValidFrom;ValidTo;BalanceGroup
*
* 02, Add Customer Product
* Record format:
* 02;CustomerIdentifier;Service;ProductIdentifier;ValidFrom;ValidTo
*
* 03, Modify Customer Product
* Record format:
* 03;CustomerIdentifier;Service;ProductIdentifier;ValidFrom*;ValidTo*
* (* means that the field is optional, filling it will change the
* value, leaving it blank leaves the previous value)
*
* 04, Change Customer Identifier
* Record format:
* 04;CustomerIdentifierOld;CustomerIdentifierNew
*
* 05, Add Alias
* Record format:
* 05;Alias;CustomerIdentifier
*
* 06, Add/Modify ERA
* Record format:
* 06;CustomerIdentifier;ERA_ID;Value
*
* ------------------------------- DB Interface --------------------------------
*
* If the loading is done from a DB, the queries that are executed are:
*
* AliasSelectQuery: This query should return a list of the aliases that are
* to be associated with each account. The query should return:
*
* 1) ALIAS
* 2) CUSTOMER_IDENTIFIER
*
* CustomerSelectStatement: This query returns a list of all of the customer
* accounts that the system should handle. The query should return:
*
* 1) CUSTOMER_IDENTIFIER
* 2) VALID_FROM (YYYYMMDDHHMMSS)
* 3) VALID_TO (YYYYMMDDHHMMSS)
* 4) BALANCE_GROUP
*
* ProductSelectQuery: This query returns a list of all the products that are
* associated with a customer account. The query should return:
*
* 1) CUSTOMER_IDENTIFIER
* 2) SERVICE
* 3) PRODUCT_NAME
* 4) VALID_FROM (YYYYMMDDHHMMSS)
* 5) VALID_TO (YYYYMMDDHHMMSS)
*
* ERASelectQuery: This query returns a list of the ERAs (Extended Rating
* Attributes) associated with the account. The query should return:
*
* 1) CUSTOMER_IDENTIFIER
* 2) ERA_NAME
* 3) ERA_VALUE
*
* @author i.sparkes
*/
public class CustomerCache
extends AbstractSyncLoaderCache
{
// Used to allow alias maps - takes a alias and maps to a poid.
private ConcurrentHashMap<String, String> aliasCache;
// The CustIDCache holds the aliases for the account
private ConcurrentHashMap<String, CustInfo> CustIDCache;
/**
* The alias data select query is used to recover alias information from the
* database. Aliases are the keys used to locate the customer account to use
* for rating the traffic
*/
protected static String aliasSelectQuery;
/**
* prepared statement for the alias query
*/
protected static PreparedStatement stmtAliasSelectQuery;
/**
* The customer data select query is used to recover customer information
* from the database
*/
protected static String customerSelectQuery;
/**
* prepared statement for the customer data query
*/
protected static PreparedStatement stmtCustomerSelectQuery;
/**
* The product data select query is used to recover the product infromation
* from the database and associate it to the account
*/
protected static String productSelectQuery;
/**
* prepared statement for the product query
*/
protected static PreparedStatement stmtProductSelectQuery;
/**
* The ERA data select query is used to recover the "Extended Rating
* Attribute" information from the database and associate it to the account
*/
protected static String eraSelectQuery;
/**
* prepared statement for the ERA query
*/
protected static PreparedStatement stmtERASelectQuery;
/**
* The internal date format is the format that by default will be used when
* interpreting dates that come in the queries. The value here is the default
* value, but this can be changed.
*/
protected String internalDateFormat = "yyyyMMddHHmmss";
/**
* The CustInfo structure holds the information about the customer account,
* including the validity dates, the product list and the balance group
* reference. Note that we are using the dates as long integers to reduce
* the total amount of storage that is required.
*/
private class CustInfo
{
private long UTCValidFrom;
private long UTCValidTo;
private ArrayList<CustProductInfo> CPI = null;
private int ProductCount = 0;
private int BalanceGroup = 0;
private ConcurrentHashMap<String, String> ERAList = null;
}
/**
* The CustProductInfo structure holds the information about the products the,
* customer has, including the validity dates. Note that we are using long integers
* for the dates to reduce storage requirements.
*/
private class CustProductInfo
{
private String ProductID=null;
private String Service=null;
private long UTCValidFrom;
private long UTCValidTo;
}
/** Constructor
* Creates a new instance of the Customer Cache. The Cache
* contains all of the Customer IDs that have been cached.
*/
public CustomerCache()
{
super();
CustIDCache = new ConcurrentHashMap<>(5000);
aliasCache = new ConcurrentHashMap<>(5000);
}
/**
* Add an alias to the customer cache. An alias is a representation of any
* identifier that can be used to locate the account
*
* @param alias The identifier that should be used to locate the account
* @param CustId The account that should be located
*/
public void addAlias(String alias, String CustId)
{
// Update the alias list
if (!aliasCache.containsKey(alias))
{
aliasCache.put(alias,CustId);
}
else
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Alias ID <" + alias + "> already exists.");
}
}
/**
* Add a Customer object into the CustomerCache.
*
* @param CustId The customer identifier
* @param ValidFrom Valid from date of the customer relationship
* @param ValidTo Valid to date of the customer relationship
* @param BalanceGroup The ID of the counter balance group
*/
public void addCustId(String CustId,long ValidFrom,long ValidTo,int BalanceGroup)
{
CustInfo tmpCustInfo;
// See if we already have ID for this customer
if (!CustIDCache.containsKey(CustId))
{
// Check validity dates
if (ValidTo <= ValidFrom)
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Customer ID <" + CustId + "> valid from <" + ValidFrom + "> is after valid to <" + ValidTo + ">. Add failed.");
return;
}
// Create the new entry for the customer ID
tmpCustInfo = new CustInfo();
tmpCustInfo.CPI = new ArrayList<>();
tmpCustInfo.ERAList = new ConcurrentHashMap<>(10);
tmpCustInfo.UTCValidFrom = ValidFrom;
tmpCustInfo.UTCValidTo = ValidTo;
tmpCustInfo.BalanceGroup = BalanceGroup;
CustIDCache.put(CustId,tmpCustInfo);
}
else
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Customer ID <" + CustId + "> already exists. Add failed.");
}
}
/**
* Set the date format we are using
*
* @param newDateFormat The new format of the date
*/
public void setDateFormat(String newDateFormat)
{
internalDateFormat = newDateFormat;
}
/**
* 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 ProdID The product identifier
* @param ValidFrom The start of the product validity
* @param ValidTo The end of the product validity
*/
public void addCPI(String CustId, String Service, String ProdID, long ValidFrom, long ValidTo)
{
CustInfo tmpCustInfo;
CustProductInfo tmpCPI;
// See if we already have ID for this customer
if (CustIDCache.containsKey(CustId))
{
// Check validity dates
if (ValidTo <= ValidFrom)
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Customer ID <" + CustId + "> product <" + ProdID + "> valid from <" + ValidFrom + "> is after valid to <" + ValidTo + ">. Add failed.");
return;
}
// Create the new entry for the customer ID
tmpCustInfo = CustIDCache.get(CustId);
tmpCPI = new CustProductInfo();
tmpCPI.Service = Service;
tmpCPI.ProductID = ProdID;
tmpCPI.UTCValidFrom = ValidFrom;
tmpCPI.UTCValidTo = ValidTo;
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.");
}
}
/**
* Add an ERA (Extended Rating Attribute) object to the account. ERAs are
* used to control rating, for example Closed User Groups are modelled using
* these.
*
* @param CustId The customer to add the ERA to
* @param ERA_ID The key of the ERA
* @param Value The value of the ERA
*/
public void addERA(String CustId, String ERA_ID, String Value)
{
CustInfo tmpCustInfo;
// 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);
tmpCustInfo.ERAList.put(ERA_ID,Value);
}
else
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Customer ID <" + CustId + "> not found. Add/modify ERA failed.");
}
}
/**
* Recover a customer ID from the cache using the alias.
*
* @param alias The alias to lookup
* @return The internal customer ID
*/
public String getCustId(String alias)
{
String CustPoid;
// See if we already have ID for this customer
if (aliasCache.containsKey(alias))
{
// Get the poid from the alias
CustPoid = aliasCache.get(alias);
return CustPoid;
}
else
{
return null;
}
}
/**
* 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 CDRDate The date to retrieve the products for
* @return The product list
*/
public ProductList getProducts(String alias, String Service, long CDRDate)
{
ProductList tmpProductList;
String CustPoid;
CustInfo tmpCustInfo;
CustProductInfo tmpCPI;
boolean FirstProduct = true;
// Prepare the result
tmpProductList = new ProductList();
// See if we already have ID for this customer
if (aliasCache.containsKey(alias))
{
// Get the poid from the alias
CustPoid = aliasCache.get(alias);
// Get the product information
tmpCustInfo = CustIDCache.get(CustPoid);
// See if the CDR is within the period of validitysetRawProductList
if ( tmpCustInfo.UTCValidFrom <= CDRDate )
{
if (tmpCustInfo.UTCValidTo > CDRDate)
{
// We have validity, get back the product list
for ( int i = 0 ; i < tmpCustInfo.ProductCount ; i ++ )
{
tmpCPI = tmpCustInfo.CPI.get(i);
if (tmpCPI.Service.equals(Service))
{
if ( tmpCPI.UTCValidFrom <= CDRDate )
{
if ( tmpCPI.UTCValidTo > CDRDate )
{
if (FirstProduct)
{
tmpProductList.addProduct(0,tmpCPI.ProductID,null,tmpCPI.Service,tmpCPI.UTCValidFrom,tmpCPI.UTCValidTo,1);
FirstProduct = false;
}
else
{
tmpProductList.addProduct(0,tmpCPI.ProductID,null,tmpCPI.Service,tmpCPI.UTCValidFrom,tmpCPI.UTCValidTo,1);
}
}
}
}
}
tmpProductList.setBalanceGroup(tmpCustInfo.BalanceGroup);
return tmpProductList;
}
}
return null;
}
else
{
// Otherwise write an error and ignore it
OpenRate.getOpenRateFrameworkLog().error("Alias <" + alias + "> not found. Lookup failed.");
}
return null;
}
/**
* 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(String 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;
}
/**
* Recover an ERA value from the customer cache.
*
* @param CustId The customer ID to recover the ERA for
* @param ERA_ID The key of the ERA to recover
* @return The ERA value
*/
public String getERA(String CustId, String ERA_ID)
{
CustInfo tmpCustInfo;
// 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);
return tmpCustInfo.ERAList.get(ERA_ID);
}
else
{
// Otherwise we don't know the customer ID, return null
return null;
}
}
/**
* Recover an ERA value from the customer cache.
*
* @param CustId The customer ID to recover the ERA for
* @return The ERA value
*/
public List<String> getERAKeys(String CustId)
{
CustInfo tmpCustInfo;
ArrayList<String> keyList = new ArrayList<>();
// 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);
keyList.addAll(tmpCustInfo.ERAList.keySet());
return keyList;
}
else
{
// Otherwise we don't know the customer ID, return null
return null;
}
}
/**
* load the data from a file
*
* @throws InitializationException
*/
@Override
public void loadDataFromFile()
throws InitializationException
{
// Variable declarations
int custLoaded = 0;
int CPILoaded = 0;
int aliasLoaded = 0;
int ERALoaded = 0;
int lineCounter = 0;
BufferedReader inFile;
String tmpFileRecord;
String[] recordFields ;
long tmpFromDate = 0;
long tmpToDate = 0;
SimpleDateFormat sdfInput = new SimpleDateFormat (internalDateFormat);
// Log that we are starting the loading
OpenRate.getOpenRateFrameworkLog().info("Starting Customer Cache Loading from File");
// Try to open the file
try
{
inFile = new BufferedReader(new FileReader(cacheDataFile));
}
catch (FileNotFoundException exFileNotFound)
{
message = "Application is not able to read file <" + cacheDataFile + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,
exFileNotFound,
getSymbolicName());
}
// File open, now get the stuff
try
{
while (inFile.ready())
{
tmpFileRecord = inFile.readLine();
lineCounter++;
if ((tmpFileRecord.startsWith("#")) |
tmpFileRecord.trim().equals(""))
{
// Comment line, ignore
}
else
{
recordFields = tmpFileRecord.split(";");
// Work on the different types of records in the file
if ( recordFields[0].equals("01") )
{
// Customer data - prepare the fields
try
{
tmpFromDate = sdfInput.parse(recordFields[2]).getTime()/1000;
tmpToDate = sdfInput.parse(recordFields[3]).getTime()/1000;
}
catch (ParseException ex)
{
OpenRate.getOpenRateFrameworkLog().error("Date formats for record <" + tmpFileRecord + "> on line <" + lineCounter + "> are not correct. Data discarded." );
}
addCustId(recordFields[1],tmpFromDate,tmpToDate,Integer.parseInt(recordFields[4]));
custLoaded++;
// Update status for long operations
if ( (custLoaded % loadingLogNotificationStep) == 0)
{
OpenRate.getOpenRateFrameworkLog().info("Customer Map Data Loaded " + custLoaded + " Customer Records");
}
}
if (recordFields[0].equals("02"))
{
// Customer product - prepare the fields
try
{
tmpFromDate = sdfInput.parse(recordFields[4]).getTime()/1000;
tmpToDate = sdfInput.parse(recordFields[5]).getTime()/1000;
}
catch (ParseException ex)
{
OpenRate.getOpenRateFrameworkLog().error("Date formats for record <" + tmpFileRecord + "> are not correct. Data discarded." );
}
addCPI(recordFields[1],recordFields[2],recordFields[3],tmpFromDate,tmpToDate);
CPILoaded++;
// Update status for long operations
if ( (CPILoaded % loadingLogNotificationStep) == 0)
{
OpenRate.getOpenRateFrameworkLog().info("Customer Map Data Loaded " + CPILoaded + " Product Records");
}
}
if ( recordFields[0].equals("05") )
{
addAlias(recordFields[1],recordFields[2]);
aliasLoaded++;
}
if ( recordFields[0].equals("06") )
{
addERA(recordFields[1],recordFields[2],recordFields[3]);
ERALoaded++;
}
// Other types of record
// ...
}
}
}
catch (IOException ex)
{
OpenRate.getOpenRateFrameworkLog().fatal(
"Error reading input file <" + cacheDataFile +
"> in record <" + lineCounter + ">. IO Error.");
}
catch (ArrayIndexOutOfBoundsException ex)
{
OpenRate.getOpenRateFrameworkLog().fatal(
"Error reading input file <" + cacheDataFile +
"> in record <" + lineCounter + ">. Malformed Record.");
}
finally
{
try
{
inFile.close();
}
catch (IOException ex)
{
OpenRate.getOpenRateFrameworkLog().error("Error closing input file <" + cacheDataFile +
">", ex);
}
}
OpenRate.getOpenRateFrameworkLog().info(
"Customer Cache Data Loading completed. " + lineCounter +
" configuration lines loaded from <" + cacheDataFile +
">");
OpenRate.getOpenRateFrameworkLog().info("Alias Loaded: " + aliasLoaded);
OpenRate.getOpenRateFrameworkLog().info("Customers Loaded: " + custLoaded);
OpenRate.getOpenRateFrameworkLog().info("Products Loaded: " + CPILoaded);
OpenRate.getOpenRateFrameworkLog().info("ERAs Loaded: " + ERALoaded);
}
/**
* Load the data from the defined Data Source DB
*
* @throws InitializationException
*/
@Override
public void loadDataFromDB()
throws InitializationException
{
String ERAValue;
String ERAName;
String prodName;
String service;
long validFrom = 0;
long validTo = 0;
int balGrp;
String tmpBalGrp;
String tmpValidTo;
String tmpValidFrom;
int custLoaded = 0;
int CPILoaded = 0;
int aliasLoaded = 0;
int ERALoaded = 0;
String custId;
String alias;
SimpleDateFormat sdfInput = new SimpleDateFormat (internalDateFormat);
// Log that we are starting the loading
OpenRate.getOpenRateFrameworkLog().info("Starting Customer Cache Loading from DB");
// The datasource property was added to allow database to database
// JDBC adapters to work properly using 1 configuration file.
if(DBUtil.initDataSource(cacheDataSourceName) == null)
{
message = "Could not initialise DB connection <" + cacheDataSourceName + "> to in module <" + getSymbolicName() + ">.";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
// Try to open the DS
JDBCcon = DBUtil.getConnection(cacheDataSourceName);
// Now prepare the statements
prepareStatements();
// Execute the query
try
{
mrs = stmtAliasSelectQuery.executeQuery();
}
catch (SQLException ex)
{
message = "Error performing SQL for retieving Alias data. message: <" + ex.getMessage() + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// loop through the results for the customer alias cache
try
{
mrs.beforeFirst();
while (mrs.next())
{
aliasLoaded++;
alias = mrs.getString(1);
custId = mrs.getString(2);
// Add the map
addAlias(alias,custId);
}
}
catch (SQLException ex)
{
message = "Error opening Alias Data for <" + cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Close down stuff
try
{
mrs.close();
}
catch (SQLException ex)
{
message = "Error closing Result Set for Alias information from <" +
cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Execute the query
try
{
mrs = stmtCustomerSelectQuery.executeQuery();
}
catch (SQLException ex)
{
message = "Error performing SQL for retieving Customer data. message: " + ex.getMessage();
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// loop through the results for the customer alias cache
try
{
mrs.beforeFirst();
while (mrs.next())
{
custLoaded++;
custId = mrs.getString(1);
tmpValidFrom = mrs.getString(2);
tmpValidTo = mrs.getString(3);
tmpBalGrp = mrs.getString(4);
// Customer data - prepare the fields
try
{
validFrom = sdfInput.parse(tmpValidFrom).getTime()/1000;
validTo = sdfInput.parse(tmpValidTo).getTime()/1000;
}
catch (ParseException ex)
{
OpenRate.getOpenRateFrameworkLog().error("Date formats for record <" + custLoaded + "> are not correct. Data discarded." );
}
balGrp = Integer.parseInt(tmpBalGrp);
// Add the map
addCustId(custId,validFrom,validTo,balGrp);
}
}
catch (SQLException ex)
{
message = "Error opening Customer Data for <" + cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Close down stuff
try
{
mrs.close();
}
catch (SQLException ex)
{
message = "Error closing Result Set for Customer information from <" +
cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Execute the query
try
{
mrs = stmtProductSelectQuery.executeQuery();
}
catch (SQLException ex)
{
message = "Error performing SQL for retieving Product data. message: " + ex.getMessage();
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// loop through the results for the customer alias cache
try
{
mrs.beforeFirst();
while (mrs.next())
{
CPILoaded++;
custId = mrs.getString(1);
service = mrs.getString(2);
prodName = mrs.getString(3);
tmpValidFrom = mrs.getString(4);
tmpValidTo = mrs.getString(5);
// Customer data - prepare the fields
try
{
validFrom = sdfInput.parse(tmpValidFrom).getTime()/1000;
validTo = sdfInput.parse(tmpValidTo).getTime()/1000;
}
catch (ParseException ex)
{
OpenRate.getOpenRateFrameworkLog().error("Date formats for record <" + custLoaded + "> are not correct. Data discarded." );
}
// Add the map
addCPI(custId,service,prodName,validFrom,validTo);
}
}
catch (SQLException ex)
{
message = "Error opening Product Data for <" + cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Close down stuff
try
{
mrs.close();
}
catch (SQLException ex)
{
message = "Error closing Result Set for Product information from <" +
cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Execute the query
try
{
mrs = stmtERASelectQuery.executeQuery();
}
catch (SQLException ex)
{
message = "Error performing SQL for retieving ERA data";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// loop through the results for the customer alias cache
try
{
mrs.beforeFirst();
while (mrs.next())
{
CPILoaded++;
custId = mrs.getString(1);
ERAName = mrs.getString(2);
ERAValue = mrs.getString(3);
// Add the map
addERA(custId,ERAName,ERAValue);
}
}
catch (SQLException ex)
{
message = "Error opening Product Data for <" + cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
// Close down stuff
try
{
mrs.close();
stmtAliasSelectQuery.close();
stmtCustomerSelectQuery.close();
stmtProductSelectQuery.close();
stmtERASelectQuery.close();
JDBCcon.close();
}
catch (SQLException ex)
{
message = "Error closing Search Map Data connection for <" + cacheDataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().fatal(message);
throw new InitializationException(message,ex,getSymbolicName());
}
OpenRate.getOpenRateFrameworkLog().info(
"Customer Cache Data Loading completed from <" + cacheDataSourceName +
">");
OpenRate.getOpenRateFrameworkLog().info("Alias Loaded: " + aliasLoaded);
OpenRate.getOpenRateFrameworkLog().info("Customers Loaded: " + custLoaded);
OpenRate.getOpenRateFrameworkLog().info("Products Loaded: " + CPILoaded);
OpenRate.getOpenRateFrameworkLog().info("ERAs Loaded: " + ERALoaded);
}
/**
* Load the data from the defined Data Source Method
*
* @throws InitializationException
*/
@Override
public void loadDataFromMethod()
throws InitializationException
{
throw new InitializationException("Not implemented yet",getSymbolicName());
}
/**
* Reset the cache
*/
@Override
public void clearCacheObjects()
{
CustIDCache.clear();
aliasCache.clear();
}
// -----------------------------------------------------------------------------
// ---------------- Start of data base data layer functions --------------------
// -----------------------------------------------------------------------------
/**
* get the select statement(s). Implemented as a separate function so that it can
* be overwritten in implementation classes. By default the cache picks up the
* statement with the name "SelectStatement".
*
* @param ResourceName The name of the resource to load for
* @param CacheName The name of the cache to load for
* @return True if the statements were found, otherwise false
* @throws InitializationException
*/
@Override
protected boolean getDataStatements(String ResourceName, String CacheName) throws InitializationException
{
// Get the Select statement
aliasSelectQuery = PropertyUtils.getPropertyUtils().getDataCachePropertyValueDef(ResourceName,
CacheName,
"AliasSelectStatement",
"None");
if (aliasSelectQuery.equalsIgnoreCase("None"))
{
message = "<AliasSelectStatement> for <" + getSymbolicName() + "> missing.";
throw new InitializationException(message,getSymbolicName());
}
customerSelectQuery = PropertyUtils.getPropertyUtils().getDataCachePropertyValueDef(ResourceName,
CacheName,
"CustomerSelectStatement",
"None");
if (customerSelectQuery.equalsIgnoreCase("None"))
{
message = "<CustomerSelectStatement> for <" + getSymbolicName() + "> missing.";
throw new InitializationException(message,getSymbolicName());
}
productSelectQuery = PropertyUtils.getPropertyUtils().getDataCachePropertyValueDef(ResourceName,
CacheName,
"ProductSelectStatement",
"None");
if (productSelectQuery.equalsIgnoreCase("None"))
{
message = "<ProductSelectStatement> for <" + getSymbolicName() + "> missing.";
throw new InitializationException(message,getSymbolicName());
}
eraSelectQuery = PropertyUtils.getPropertyUtils().getDataCachePropertyValueDef(ResourceName,
CacheName,
"ERASelectStatement",
"None");
if (eraSelectQuery.equalsIgnoreCase("None"))
{
message = "<ERASelectStatement> for <" + getSymbolicName() + "> missing.";
throw new InitializationException(message,getSymbolicName());
}
// Normally we should not get here - we should have thrown an exception already
// if anything was missing
if ((aliasSelectQuery.equals("None")) |
(customerSelectQuery.equals("None")) |
(productSelectQuery.equals("None")) |
(eraSelectQuery.equals("None")))
{
return false;
}
else
{
return true;
}
}
/**
* PrepareStatements creates the statements from the SQL expressions
* so that they can be run as needed.
* @throws InitializationException
*/
@Override
protected void prepareStatements()
throws InitializationException
{
try
{
// prepare the SQL for the TestStatement
stmtAliasSelectQuery = JDBCcon.prepareStatement(aliasSelectQuery,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
catch (SQLException ex)
{
message = "Error preparing the statement " + aliasSelectQuery;
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,ex,getSymbolicName());
}
try
{
// prepare the SQL for the TestStatement
stmtCustomerSelectQuery = JDBCcon.prepareStatement(customerSelectQuery,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
catch (SQLException ex)
{
message = "Error preparing the statement " + customerSelectQuery;
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,ex,getSymbolicName());
}
try
{
// prepare the SQL for the TestStatement
stmtProductSelectQuery = JDBCcon.prepareStatement(productSelectQuery,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
catch (SQLException ex)
{
message = "Error preparing the statement " + productSelectQuery;
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,ex,getSymbolicName());
}
try
{
// prepare the SQL for the TestStatement
stmtERASelectQuery = JDBCcon.prepareStatement(eraSelectQuery,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
catch (SQLException ex)
{
message = "Error preparing the statement " + eraSelectQuery;
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,ex,getSymbolicName());
}
}
}