/* jBilling - The Enterprise Open Source Billing System Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde This file is part of jbilling. jbilling is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. jbilling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with jbilling. If not, see <http://www.gnu.org/licenses/>. */ package com.sapienter.jbilling.server.item; import javax.xml.bind.annotation.XmlTransient; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * @author Emil */ public class PricingField { private String name; private Type type; private Integer position = 1; private String value = null; private long resultId; // at the time, only used for mediation of batch public enum Type { STRING, INTEGER, DECIMAL, DATE, BOOLEAN } public PricingField() { } /** * Constructs a new PricingField from a given encoded String. * * This constructor is designed for internal use only. * * @see #encode(PricingField) * @param encoded encoded string to parse */ public PricingField(String encoded) { String[] fields = encoded.split(":"); if (fields == null || fields.length != 4) { this.name = ""; this.type = Type.INTEGER; this.value = "0"; return; } this.name = fields[0]; this.position = Integer.parseInt(fields[1]); this.type = mapType(fields[2]); this.value = fields[3]; } /** * Copy constructor, creates a new instance of the given PricingField with * the same member values. * * @param field pricing field to copy */ public PricingField(PricingField field) { this.name = field.getName(); this.type = field.getType(); this.position = field.getPosition(); this.value = field.getStrValue(); } /** * Constructs a new PricingField of type {@code STRING} * * @param name field name * @param value field value */ public PricingField(String name, String value) { this.name = name; this.type = Type.STRING; setStrValue(value); } /** * Constructs a new PricingField of type {@code DATE} * * @param name field name * @param value field value */ public PricingField(String name, Date value) { this.name = name; this.type = Type.DATE; setDateValue(value); } /** * Constructs a new PricingField of type {@code INTEGER} * * @param name field name * @param value field value */ public PricingField(String name, Integer value) { this.name = name; this.type = Type.INTEGER; setIntValue(value); } /** * Constructs a new PricingField of type {@code DECIMAL} * * @param name field name * @param value field value */ public PricingField(String name, BigDecimal value) { this.name = name; this.type = Type.DECIMAL; setDecimalValue(value); } /** * Constructs a new PricingField of type {@code BOOLEAN} * * @param name field name * @param value field value */ public PricingField(String name, Boolean value) { this.name = name; this.type = Type.BOOLEAN; setBooleanValue(value); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } public void setPosition(Integer position) { this.position = position; } public Integer getPosition() { return position; } public long getResultId() { return resultId; } public void setResultId(long resultId) { this.resultId = resultId; } /** * Returns this pricing fields value as a raw type. * * @return pricing field value */ public Object getValue() { switch (type) { case STRING : return value; case DATE : return getDateValue(); case INTEGER : return getIntValue(); case DECIMAL : return getDecimalValue(); case BOOLEAN : return getBooleanValue(); default: return null; } } @XmlTransient public String getStrValue() { return value; } public void setStrValue(String value) { this.value = value; } @XmlTransient public Date getDateValue() { if (value == null) return null; return new Date(Long.parseLong(value)); } public void setDateValue(Date value) { if (value != null) { this.value = String.valueOf(value.getTime()); } else { this.value = null; } } @XmlTransient public Calendar getCalendarValue() { if (value == null) return null; Calendar cal = Calendar.getInstance(); cal.setTime(getDateValue()); return cal; } @XmlTransient public Integer getIntValue() { if (value == null) return null; return Integer.valueOf(value); } public void setIntValue(Integer value) { if (value != null) { this.value = value.toString(); } else { this.value = null; } } @XmlTransient public BigDecimal getDecimalValue() { if (value == null) return null; return new BigDecimal(value); } public void setDecimalValue(BigDecimal value) { if (value != null) { this.value = value.toString(); } else { this.value = null; } } /** * Returns the decimal value as a double. This method is provided for backwards * compatibility, use {@link PricingField#getDecimalValue()} instead. * * @return decimal value as a double */ @XmlTransient public Double getDoubleValue() { BigDecimal value = getDecimalValue(); return (value != null ? value.doubleValue() : null); } /** * @see #getDoubleValue() * @return decimal value as a float */ @XmlTransient public Double getFloatValue() { return getDoubleValue(); } public void setBooleanValue(Boolean value) { if (value != null) { this.value = value.toString(); } else { this.value = null; } } @XmlTransient public Boolean getBooleanValue() { if (value == null) return null; return Boolean.valueOf(this.value); } /** * Returns an appropriate {@link Type} for the given string, or null if no matching type found. * * Type strings: * string * integer * float * double * decimal * date * boolean * * @param myType type string * @return matching type */ public static Type mapType(String myType) { // todo: should be a member of the Type enum eg, Type$fromString(...); if (myType.equalsIgnoreCase("string")) { return Type.STRING; } else if (myType.equalsIgnoreCase("integer")) { return Type.INTEGER; } else if (myType.equalsIgnoreCase("float") || myType.equalsIgnoreCase("double") || myType.equalsIgnoreCase("decimal")) { return Type.DECIMAL; } else if (myType.equalsIgnoreCase("date")) { return Type.DATE; } else if (myType.equalsIgnoreCase("boolean")) { return Type.BOOLEAN; } else { return null; } } /** * Encodes a pricing field as a string. The encoded string is a semi-colon * delimited string in the format {@code :name:position:type:value}, where name and position are * optional. * * Example: * :src::string:310-1010 * :dst::string:1-800-123-4567 * :userid:integer:1234 * * @param field field to encode * @return encoded string */ public static String encode(PricingField field) { StringBuffer sb = new StringBuffer() .append(field.getName()) .append(":") .append(field.getPosition()); switch(field.getType()) { case STRING: sb.append(":string:"); break; case INTEGER: sb.append(":integer:"); break; case DECIMAL: sb.append(":float:"); break; case DATE: sb.append(":date:"); break; case BOOLEAN: sb.append(":boolean:"); break; } sb.append(field.getStrValue()); return sb.toString(); } /** * Parses a comma separated list of encoded PricingField strings and returns * an array of fields. * * @param pricingFields comma separated list of encoded pricing field strings * @return array of fields */ public static PricingField[] getPricingFieldsValue(String pricingFields) { if (pricingFields == null) return null; String[] fields = pricingFields.split(","); if (fields == null || fields.length == 0) { return null; } List<PricingField> result = new ArrayList<PricingField>(); for (int i = 0; i < fields.length; i++) { if (fields[i] != null && !fields[i].equals("") && fields[i].split(":").length == 4) { result.add(new PricingField(fields[i])); } } return result.toArray(new PricingField[0]); } /** * Returns a comma separated list of encoded PricingField strings from the given * array of fields. * * @param pricingFields array of fields to convert * @return comma separated list of encoded pricing field strings */ public static String setPricingFieldsValue(PricingField[] pricingFields) { PricingField[] fields = pricingFields; // defensive copy StringBuffer result = new StringBuffer(); if (fields != null && fields.length > 0) { for (int i = 0; i < fields.length; i++) { result.append(PricingField.encode(fields[i])); if (i < (fields.length - 1)) { result.append(","); } } } return result.toString(); } @Override public String toString() { return "name: " + name + " type: " + type + " value: " + getValue() + " position: " + position + " resultId: " + resultId; } }