/* ==================================================================== * 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.process; import OpenRate.configurationmanager.ClientManager; import OpenRate.exception.InitializationException; import OpenRate.logging.LogUtil; import OpenRate.record.*; /** * This class provides the abstract base for a more complex rating plug in. A * raw rate object is retrieved from the RateCache object, and this class * provides the primitives required for performing rating, including selecting * the correct RUM (Rateable Usage Metric) to use and creating balance impacts * on the record. * * This is a high-level module that requires records based on the RatingRecord * class. */ public class GatherRUMImpacts extends AbstractStubPlugIn { // List of Services that this Client supports private static final String SERVICE_0_BAL_IMP = "CreateZeroBalImpacts"; // Whether we create bal impact packets for 0 balance items private boolean Create0BalImpacts = false; private class SummarizationArray { String ResourceName = null; double ResourceValue = 0; int CounterPeriod = 0; int ResourceID = 0; SummarizationArray child = null; } // ----------------------------------------------------------------------------- // ------------------ Start of inherited Plug In functions --------------------- // ----------------------------------------------------------------------------- /** * This is called when a good record is encountered. We perform the charge * packet summarization in this case. * * @param r The record to work on * @return Modified record */ @Override public IRecord procValidRecord(IRecord r) { SummarizeChargePackets((RatingRecord)r); return r; } /** * This is called when an error record is encountered. We do no processing in * this case. * * @param r The record to work on * @return Modified record */ @Override public IRecord procErrorRecord(IRecord r) { return r; } // ----------------------------------------------------------------------------- // ----------------------- Start of utility functions -------------------------- // ----------------------------------------------------------------------------- /** * Calculate the summary of the charge packets in the record * * @param CurrentRecord The record to summarise */ public void SummarizeChargePackets(RatingRecord CurrentRecord) { int Index; ChargePacket tmpCP; String tmpResource; int tmpResID; boolean found; boolean createImpact; SummarizationArray tmpImpacts = new SummarizationArray(); tmpImpacts.ResourceName = "root"; SummarizationArray tmpImpactsRider; BalanceImpact tmpBalImpact; // Cycle over the charge packets gathering the impacts as we go for (Index = 0 ; Index < CurrentRecord.getChargePacketCount() ; Index++) { tmpCP = CurrentRecord.getChargePacket(Index); tmpResource = tmpCP.resource; tmpResID = tmpCP.resCounter; // if the resource is not set, we cannot do anything with the record if (tmpResource == null) { CurrentRecord.addError(new RecordError("ERR_RESOURCE_NOT_SET",ErrorType.DATA_NOT_FOUND, getSymbolicName())); return; } // initialise found = false; // reset the rider object tmpImpactsRider = tmpImpacts; do { if ((tmpImpactsRider.ResourceName.equals(tmpResource)) & (tmpImpactsRider.CounterPeriod == CurrentRecord.getCounterCycle()) & (tmpImpactsRider.ResourceID == tmpResID)) { tmpImpactsRider.ResourceValue += tmpCP.chargedValue; break; } if (tmpImpactsRider.child == null) { // we are at the end of the list if (!found) { // we did not find an impact to aggregate into, so make one tmpImpactsRider.child = new SummarizationArray(); tmpImpactsRider.child.ResourceName = tmpResource; tmpImpactsRider.child.ResourceValue = tmpCP.chargedValue; tmpImpactsRider.child.ResourceID = tmpCP.resCounter; tmpImpactsRider.child.CounterPeriod = CurrentRecord.getCounterCycle(); break; } } else { // move down the list tmpImpactsRider = tmpImpactsRider.child; } } while (tmpImpactsRider != null); } // We have finished gathering, now create the balance impacts tmpImpactsRider = tmpImpacts; while (tmpImpactsRider.child != null) { // find out whether we are to create the impact or not createImpact = (tmpImpactsRider.child.ResourceValue != 0) | Create0BalImpacts; if (createImpact) { tmpBalImpact = new BalanceImpact(); tmpBalImpact.type = "R"; tmpBalImpact.balanceDelta = tmpImpactsRider.child.ResourceValue; tmpBalImpact.Resource = tmpImpactsRider.child.ResourceName; tmpBalImpact.counterID = tmpImpactsRider.child.ResourceID; tmpBalImpact.recID = tmpImpactsRider.child.CounterPeriod; CurrentRecord.addBalanceImpact(tmpBalImpact); } // move down the list tmpImpactsRider = tmpImpactsRider.child; } } // ----------------------------------------------------------------------------- // ------------- Start of inherited IEventInterface functions ------------------ // ----------------------------------------------------------------------------- /** * processControlEvent is the event processing hook for the External Control * Interface (ECI). This allows interaction with the external world. * * @param Command The Command that should be processed * @param Init True if we are during pipeline starup * @param Parameter The parameter value that should be operated on * @return The message as a result of the operation */ @Override public String processControlEvent(String Command, boolean Init, String Parameter) { int ResultCode = -1; // The input file name can be changed if (Command.equalsIgnoreCase(SERVICE_0_BAL_IMP)) { if (Parameter.equalsIgnoreCase("true")) { Create0BalImpacts = true; ResultCode = 0; } else if (Parameter.equalsIgnoreCase("false")) { Create0BalImpacts = false; ResultCode = 0; } else if (Parameter.equals("")) { // Get the current state if (Create0BalImpacts) { return "true"; } else { return "false"; } } else { // we don't recognise this, give an error return "Unknown parameter value."; } } if (ResultCode == 0) { getPipeLog().debug(LogUtil.LogECIPipeCommand(getSymbolicName(), getPipeName(), Command, Parameter)); return "OK"; } else { // This is not our event, pass it up the stack return super.processControlEvent(Command, Init, Parameter); } } /** * registerClientManager registers this class as a client of the ECI listener * and publishes the commands that the plug in understands. The listener is * responsible for delivering only these commands to the plug in. * */ @Override public void registerClientManager() throws InitializationException { // Set the client reference and the base services first super.registerClientManager(); //Register services for this Client ClientManager.getClientManager().registerClientService(getSymbolicName(), SERVICE_0_BAL_IMP, ClientManager.PARAM_NONE); } }