org.jdice.calc.Properties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcalc Show documentation
Show all versions of jcalc Show documentation
Fluent Java API for easier work with numbers, writing formula and calculations in Java.
The newest version!
/*
* Copyright 2014 Davor Sauer
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jdice.calc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;
import org.jdice.calc.internal.CacheExtension;
import org.jdice.calc.internal.Objects;
/**
* Properties for {@link AbstractCalculator}, {@link Num}
*
* With ability to declare global properties on scope of running application by providing properties file in class path.
* Or by saving properties file with {@link #saveGlobalProperties()}
*
*
* It's possible to define default configuration with jcalc.properties file in root of classpath.
*
* Example of jcalc.properties file where all properties are optional:
*
*
* roundingMode=HALF_UP
* scale=2
* stripTrailingZeros=true
* decimalSeparator.out='.'
* decimalSeparator.in='.'
* numconverter[0]=org.jdice.calc.test.NumTest$CustomObject > org.jdice.calc.test.NumTest$CustomObjectNumConverter
* operator[0]=org.jdice.calc.test.CustomOperatorFunctionTest$QuestionOperator
* function[0]=org.jdice.calc.test.CustomOperatorFunctionTest$SumFunction
*
* @author Davor Sauer
*/
public class Properties implements Serializable {
private static final long serialVersionUID = 1L;
//
// Defaults
//
public static final boolean DEFAULT_STRIP_TRAILING_ZEROS = true;
public static final String DEFAULT_OUTPUT_FORMAT = "#,###,###,##0.00";
public static final int DEFAULT_SCALE = 64;
public static final char DEFAULT_DECIMAL_SEPARATOR = '.';
public static final Rounding DEFAULT_ROUNDING_MODE = Rounding.HALF_UP;
//
// set defaults / load global scope defaults
//
private static Rounding defRoundingMode = Properties.DEFAULT_ROUNDING_MODE;
private static Integer defScale;
private static boolean defStripTrailingZeros = Properties.DEFAULT_STRIP_TRAILING_ZEROS;
private static char defDecimalSeparatorIN = Properties.DEFAULT_DECIMAL_SEPARATOR;
private static char defDecimalSeparatorOUT = Properties.DEFAULT_DECIMAL_SEPARATOR;
private static Character defGroupingSeparator;
private static String defOutputFormat;
static {
String propPath = getGlobalPropertiesFile();
if (propPath != null) {
File propFile = new File(propPath);
if (propFile != null && propFile.exists() && propFile.isFile() && propFile.canRead()) {
java.util.Properties prop = new java.util.Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(propFile);
prop.load(fis);
// calc.roundingMode
String propRM = prop.getProperty("roundingMode");
if (propRM != null && propRM.trim().length() != 0) {
Rounding rm = Rounding.getRoundingMode(propRM.trim());
if (rm != null)
defRoundingMode = rm;
}
// calc.scale
String propS = prop.getProperty("scale");
if (propS != null && propS.trim().length() != 0) {
try {
Integer sc = Integer.parseInt(propS);
if (sc != null)
defScale = sc;
}
catch (Exception e) {
}
}
// calc.stripTrailingZeros
String propSTZ = prop.getProperty("stripTrailingZeros");
if (propSTZ != null && propSTZ.trim().length() != 0) {
Boolean stz = Boolean.parseBoolean(propSTZ.trim());
if (stz != null)
defStripTrailingZeros = stz;
}
// calc.decimalSeparator = '.' or calc.decimalSeparator = "."
String propDS = prop.getProperty("decimalSeparator");
if (propDS != null && propDS.trim().matches("['\"](.){1}['\"]")) {
defDecimalSeparatorIN = propDS.trim().charAt(1);
}
// calc.decimalSeparator.IN = '.' or calc.decimalSeparator.IN = "."
String propDSin = prop.getProperty("decimalSeparator.in");
if (propDSin != null && propDSin.trim().matches("['\"](.){1}['\"]")) {
defDecimalSeparatorIN = propDSin.trim().charAt(1);
}
// calc.decimalSeparator.OUT = '.' or calc.decimalSeparator.OUT = "."
String propDSout = prop.getProperty("decimalSeparator.out");
if (propDSout != null && propDSout.trim().matches("['\"](.){1}['\"]")) {
defDecimalSeparatorOUT = propDSout.trim().charAt(1);
}
// calc.groupingSeparator = ' ' or calc.groupingSeparator = " "
String propGS = prop.getProperty("groupingSeparator");
if (propGS != null && propGS.trim().matches("['\"](.){1}['\"]")) {
defGroupingSeparator = propGS.trim().charAt(1);
}
// calc.outputFormat
String propOF = prop.getProperty("outputFormat");
if (propOF != null && propOF.trim().length() != 0) {
defOutputFormat = propOF.trim();
}
//
// Load custom NumConverters, Operators, Functions
//
CacheExtension.loadProperties(prop);
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (fis != null)
try {
fis.close();
}
catch (IOException e) {
}
}
}
}
}
//
// Set instance defaults
//
private Rounding roundingMode = defRoundingMode;
private Integer scale = defScale;
private boolean stripTrailingZeros = defStripTrailingZeros;
private char decimalSeparatorIN = defDecimalSeparatorIN;
private char decimalSeparatorOUT = defDecimalSeparatorOUT;
private Character groupingSeparator = defGroupingSeparator;
private String outputFormat = defOutputFormat;
public Properties() {
}
public Rounding getRoundingMode() {
return roundingMode;
}
public Properties setRoundingMode(Rounding roundingMode) {
this.roundingMode = roundingMode;
return this;
}
public Integer getScale() {
return scale;
}
public Properties setScale(Integer scale) {
if (scale != null && scale >= 0)
this.scale = scale;
else
this.scale = null;
return this;
}
public boolean hasStripTrailingZeros() {
return stripTrailingZeros;
}
public Properties setStripTrailingZeros(boolean stripTrailingZeros) {
this.stripTrailingZeros = stripTrailingZeros;
return this;
}
public String getOutputFormat() {
return outputFormat;
}
public Properties setOutputFormat(String outputFormat) {
this.outputFormat = outputFormat;
return this;
}
public char getInputDecimalSeparator() {
return decimalSeparatorIN;
}
public char getOutputDecimalSeparator() {
return decimalSeparatorOUT;
}
public Properties setDecimalSeparator(char inputDecimalSeparator, char outputDecimalSeparator) {
this.decimalSeparatorIN = inputDecimalSeparator;
this.decimalSeparatorOUT = outputDecimalSeparator;
return this;
}
public Properties setInputDecimalSeparator(char inputDecimalSeparator) {
this.decimalSeparatorIN = inputDecimalSeparator;
return this;
}
public Properties setOutputDecimalSeparator(char outputDecimalSeparator) {
this.decimalSeparatorOUT = outputDecimalSeparator;
return this;
}
public Character getGroupingSeparator() {
return groupingSeparator;
}
public void setGroupingSeparator(Character groupingSeparator) {
this.groupingSeparator = groupingSeparator;
}
public void load(Properties properties) {
setScale(properties.getScale());
setRoundingMode(properties.getRoundingMode());
setStripTrailingZeros(properties.hasStripTrailingZeros());
setOutputFormat(properties.getOutputFormat());
setInputDecimalSeparator(properties.getInputDecimalSeparator());
setOutputDecimalSeparator(properties.getOutputDecimalSeparator());
setGroupingSeparator(properties.getGroupingSeparator());
}
@Override
public String toString() {
return "scale: " + (scale != null ? scale : "none")
+ ", rounding mode: " + roundingMode
+ ", strip trailing zeros: " + stripTrailingZeros
+ ", decimal separator: " + decimalSeparatorIN
+ (groupingSeparator != null ? ", grouping separator: '" + groupingSeparator + "'" : "")
+ ", outputFormat: "
+ (outputFormat != null ? outputFormat : "none");
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
else if (obj == this)
return true;
else if (obj instanceof Properties) {
Properties second = (Properties) obj;
if(!Objects.equals(this.getGroupingSeparator(), second.getGroupingSeparator()))
return false;
if(!Objects.equals(this.getInputDecimalSeparator(), second.getInputDecimalSeparator()))
return false;
if(!Objects.equals(this.getOutputDecimalSeparator(), second.getOutputDecimalSeparator()))
return false;
if(!Objects.equals(this.getOutputFormat(), second.getOutputFormat()))
return false;
if(!Objects.equals(this.getRoundingMode(), second.getRoundingMode()))
return false;
if(!Objects.equals(this.getScale(), second.getScale()))
return false;
if(!Objects.equals(this.hasStripTrailingZeros(), second.hasStripTrailingZeros()))
return false;
return true;
}
return false;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[] {groupingSeparator, decimalSeparatorIN, decimalSeparatorOUT, outputFormat, roundingMode, scale, stripTrailingZeros});
}
/**
* File location ..\bin\org.jdice.calc.properties
*
* File content:
* roundingMode=HALF_UP
* stripTrailingZeros=true
* decimalSeparator.out='.'
* decimalSeparator.in='.'
* numconverter[0]=org.jdice.calc.test.NumTest$CustomObject > org.jdice.calc.test.NumTest$CustomObjectNumConverter
* operator[0]=org.jdice.calc.test.CustomOperatorFunctionTest$QuestionOperator
* function[0]=org.jdice.calc.test.CustomOperatorFunctionTest$SumFunction
*
* @throws IOException
*/
public void saveGlobalProperties() throws IOException {
File propFile = new File(getGlobalPropertiesFile());
if (propFile.createNewFile() || propFile.isFile()) {
java.util.Properties prop = new java.util.Properties();
if (getRoundingMode() != null)
prop.put("roundingMode", getRoundingMode().name());
if (getScale() != null)
prop.put("scale", getScale());
prop.put("stripTrailingZeros", Boolean.toString(hasStripTrailingZeros()));
prop.put("decimalSeparator.in", "'" + getInputDecimalSeparator() + "'");
prop.put("decimalSeparator.out", "'" + getOutputDecimalSeparator() + "'");
if (getGroupingSeparator() != null)
prop.put("groupingSeparator", getGroupingSeparator());
if (getOutputFormat() != null)
prop.put("outputFormat", getOutputFormat());
//
// Global NumConverter
//
HashMap cncs = CacheExtension.getAllNumConverter();
int count = 0;
for (Entry cnc : cncs.entrySet()) {
prop.put("numconverter[" + count++ + "]", cnc.getKey().getName() + " > " + cnc.getValue().getClass().getName());
}
//
// Global Operator
//
HashMap, Operator> cops = CacheExtension.getOperators();
count = 0;
for (Entry, Operator> cop : cops.entrySet()) {
prop.put("operator[" + count++ + "]", cop.getKey().getName());
}
//
// Global Function
//
HashMap, Function> cfns = CacheExtension.getFunctions();
count = 0;
for (Entry, Function> cfn : cfns.entrySet()) {
prop.put("function[" + count++ + "]", cfn.getKey().getName());
}
FileOutputStream fos = new FileOutputStream(propFile);
prop.store(fos, "Global properties for jCalc");
fos.close();
fos.flush();
}
}
/**
* If {@link Num} don't define scale then use scale from {@link AbstractCalculator} instance.
* Othervise use default scale {@link Properties#DEFAULT_SCALE}
*
* @param calc
* @param value
*/
public static Rounding getInheritedRoundingMode(AbstractCalculator calc, Num value) {
if (value.getRoundingMode() == null) {
if (calc != null && calc.getRoundingMode() != null)
return calc.getRoundingMode();
else
return Properties.defRoundingMode;
}
else
return value.getRoundingMode();
}
public static Properties getInheritedProperties(AbstractCalculator calc, Num value) {
Properties prop = new Properties(); // load global and default properties
return prop;
}
/**
* If {@link Num} don't define scale then use scale from {@link AbstractCalculator} instance.
* Othervise use default scale {@link Properties#DEFAULT_SCALE}
*
* @param calc
* @param value
*/
public static int getInheritedScale(AbstractCalculator calc, Num value) {
if (value.getScale() == null) {
if (calc != null && calc.getScale() != null)
return calc.getScale();
else
return Properties.DEFAULT_SCALE;
}
else
return value.getScale();
}
public static String getGlobalPropertiesFile() {
final String CONF_PROPERTIES = "jcalc.properties";
String path = null;
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL res = classLoader.getResource(".");
String abspath = res.getFile();
if (abspath.endsWith(File.separator))
path = abspath + CONF_PROPERTIES;
else
path = abspath + File.separatorChar + CONF_PROPERTIES;
}
catch (Exception e) {
}
return path;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy