/* ==================================================================== * 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.record; import java.util.ArrayList; import java.util.List; /** * IRecord implementation fleshing out the most basic elements of the IRecord * interface. The basic functions handled by this record implementation are: * - Standard record error handling * - Standard record output handling * - record validity * - record dump flagging * - record type * - record id */ public abstract class AbstractRecord implements IRecord { /** * Default UID for Serializable class */ private static final long serialVersionUID = -1971022798790808812L; // Errors that this record has private List<IError> errors = new ArrayList<>(); /** * The record number is the sequential number of the record in the stream. */ public int recordNumber; /** * the record type - integer for speed * The record type is what allows us to determine what the records to handle * are, and what to ignore. This is the internal version of the information * which basically tells us if this record is a detail CDR or a header or * trailer */ public int RECORD_TYPE = 0; /** * This tells us whether to bother processing the record or not * Usually this will only be true for records that really need processing * (headers and trailers can be ignored, for example) */ public boolean validRecord = true; /** *This tells us if the record is a real time record or not */ public boolean RTRecord = false; /** * Outputs that this record should go to */ public ArrayList<String> outputs = new ArrayList<>(); // These are for the tracking of the outputting via the output adapter chain // Each time we add an output, we increment the OutputsAssigned, each time // an output adapter writes, OutputsWritten is incremented, when we have // written all of the outputs, the record can be destroyed. If OutputsAssigned // is 0, all outputs are written private int outputsWritten = 0; /** * Used for the dump flagging. If this is set to true and the dump is set to * dump flagged records, then the record will be dumped. */ public boolean dumpRecord = false; /** * */ public Object currentStateObject = null; /** * default constructor */ public AbstractRecord() { // Nop } /** * Is the Record valid. This is a flag that, when true, means that processing * modules should do their thing with the record. The reasons for this being * false are that it is not a real record (e.g. it is a control record) or * that it is a record that has an error attached to it that means it is * not worth the effort of processing. * * @return True if the record is marked as valid, otherwise false */ @Override public boolean isValid() { return validRecord; } /** * Set the state of the valid flag to the new defined value * * @param NewValue The new state of the valid flag */ @Override public void setValid(boolean NewValue) { validRecord = NewValue; } /** * Is the Record going to be dumped - this flag allows you to decide if a * record is to be dumped. * * @return True if the record is marked as a record to dump, otherwise false */ @Override public boolean isDump() { return dumpRecord; } /** * Set the state of the dump flag to the new defined value * * @param NewValue The new state of the dump flag */ @Override public void setDump(boolean NewValue) { dumpRecord = NewValue; } /** * Is the Record a real time record. This is a flag that, when true, means that * the record has arrived via a real time (i.e. priority) feed * * @return True if the record is real time, otherwise false */ @Override public boolean isRealtime() { return RTRecord; } /** * Set the state of the real time flag to the new defined value * * @param NewValue The new state of the real time flag */ @Override public void setRealtime(boolean NewValue) { RTRecord = NewValue; } /** * Get if the record has an error attached to it. * * If isErrored() returns true, the getErrors() method should * return a List with size() > 1. If the error list is empty, * isErrored should be false. * * @return True if the record is marked as errored, otherwise false */ @Override public boolean isErrored() { return errors.size() > 0; } /** * Return the list of errors attached to this record. * Allows a cumulative process for attaching errors * to the record where the first error in the list is * the first error found during processing. * * @return List of the errors associated with the record */ @Override public List<IError> getErrors() { return this.errors; } /** * Return the number of errors attached to this record. * * @return List of the errors associated with the record */ @Override public int getErrorCount() { return this.errors.size(); } /** * Add a single error to the error list for this record * * @param error The new error to add */ @Override public void addError(IError error) { if (error.getModuleName().isEmpty()) { // get the name of the calling class error.setModuleName(new Throwable().fillInStackTrace().getStackTrace()[1].getClassName()); } // Add the error to the list errors.add(error); // Mark by default that the errored record is not valid this.setValid(false); } /** * Clear the errors for this record */ @Override public void clearErrors() { errors.clear(); // Reset the record valid this.setValid(true); } /** * Set a single error to the error list for this record * * @param Index The index of the error to set * @param error The new error to add */ public void setError(int Index, IError error) { errors.set(Index, error); } /** * Set a list of errors on the record. This overwrites any existing errors. * * @param errors New error list to substitute the old list */ public void setErrors(List<IError> errors) { this.errors = errors; // Mark by default that the errored record is not valid this.setValid(false); } /** * Add an output to be written in the output adapter chain * * @param OutputToAdd The name of the output to add */ public void addOutput(String OutputToAdd) { outputs.add(OutputToAdd); } /** * Check if we should write to the given output. True if we should write, * otherwise false. In the default case of not having defined outputs, all * outputs are written to. * * @param OutputToCheck The name of the output to check * @return True if the output was in the output list, otherwise false */ @Override public boolean getOutput(String OutputToCheck) { int i; if (outputs.isEmpty()) { // we do not have outputs defined, so by default we write to all outputs return true; } else { if (outputs.size() == outputsWritten) { // we have written all the outputs we need to return false; } for ( i = 0 ; i < outputs.size() ; i++) { if (outputs.get(i).equalsIgnoreCase(OutputToCheck)) { outputsWritten++; return true; } } } return false; } /** * Return a list of all the outputs that we are to write to. * * @return Array list of the outputs */ public ArrayList<String> getOutputs() { return outputs; } /** * Clear the list of outputs that we are to write to. */ public void clearOutputs() { outputs.clear(); } /** * Consume the given output. Return whether the record is completely * consumed or not * * @param OutputToDelete The name of the output to remove * @param TerminatingAdapter True if this is the terminating adapter * @return True if all outputs were consumed */ @Override public boolean deleteOutput(String OutputToDelete, boolean TerminatingAdapter) { if (outputs.size() > 0) { if (outputsWritten >= outputs.size()) { // Consumed all outputs return true; } else { // Not all outputs consumed return false; } } else { // return true for the case that we are not managing outputs and this // is the terminating adapter return TerminatingAdapter; } } /** * This method allows the internal record ID to be set */ @Override public void setRecordID(int newRecordID) { this.recordNumber = newRecordID; } /** * This method allows the internal record ID to be retrieved */ @Override public int getRecordID() { return this.recordNumber; } /** * Used to provide diagnostic information for the dumpRecord module * * @return The dump strings */ @Override public abstract ArrayList<String> getDumpInfo(); /** * Return the current state for the ProcessStateLogger * * @return The current state object */ @Override public Object getCurrentStateObject() { return currentStateObject; } /** * Set the current state for the ProcessStateLogger * * @param currentStateObject */ @Override public void setCurrentStateObject(Object currentStateObject) { this.currentStateObject = currentStateObject; } /** * Get the Error dump information for the errors associated with this record * using default padding * * @return Error dumpRecord Information */ public ArrayList<String> getErrorDump() { return getErrorDump(24, false); } /** * Get the Error dump information for the errors associated with this record * with a specified padding * * @param padding The number of characters to pad to * @return Error dumpRecord Information */ public ArrayList<String> getErrorDump(int padding) { return getErrorDump(padding, false); } /** * Get the Error dump information for the errors associated with this record * with a specified padding and control of whether module name is shown * * @param padding The number of characters to pad to * @param showFullInfo if true show the module name that raised the error * @return Error dumpRecord Information */ public ArrayList<String> getErrorDump(int padding, boolean showFullInfo) { int i; RecordError tmpError; ArrayList<String> tmpDumpList = new ArrayList<>(); // set up the padding int tmpPadding; if (padding < 19) { tmpPadding = 19; } else { tmpPadding = padding; } String pad = " ".substring(1, tmpPadding - 18); int tmpErrorCount = this.getErrors().size(); tmpDumpList.add(" Errors " + pad + "= <" + tmpErrorCount + ">"); if (tmpErrorCount>0) { tmpDumpList.add("-------------- ERRORS ----------------"); for (i = 0 ; i < tmpErrorCount ; i++) { tmpError = (RecordError) this.getErrors().get(i); tmpDumpList.add(" Error " + pad + "= <" + tmpError.getMessage() + ">"); if (showFullInfo && (tmpError.getModuleName().isEmpty() == false)) { tmpDumpList.add(" Module " + pad + "= <" + tmpError.getModuleName() + ">"); tmpDumpList.add(" Desc " + pad + "= <" + tmpError.getErrorDescription() + ">"); tmpDumpList.add(" Number " + pad + "= <" + tmpError.getErrorNumber() + ">"); } } } return tmpDumpList; } }