package org.ff4j.commonsconf; /* * #%L * ff4j-archaius * %% * Copyright (C) 2013 - 2016 FF4J * %% * 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. * #L% */ import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.Configuration; import org.ff4j.exception.InvalidPropertyTypeException; import org.ff4j.property.Property; import org.ff4j.property.store.InMemoryPropertyStore; import org.ff4j.property.store.PropertyStore; import org.ff4j.property.util.PropertyFactory; import org.ff4j.utils.Util; /** * Bridge from {@link PropertyStore} to commons configuration {@link Configuration}. * * @author Cedrick Lunven (@clunven)</a> */ public class FF4jConfiguration extends AbstractConfiguration { /** Target delimiter for multivalued. */ private static final String DELIMITER = ","; /** * Source */ private PropertyStore ff4jStore; /** * Default constructor. */ public FF4jConfiguration() { } /** * Initialized with default value. * * @param ff4jPropertyStore * default store. */ public FF4jConfiguration(PropertyStore ff4jPropertyStore) { this.ff4jStore = ff4jPropertyStore; } /** {@inheritDoc} */ @Override public Configuration subset(String prefix) { Map < String, Property<?>> myProps = ff4jStore().readAllProperties(); PropertyStore ps = new InMemoryPropertyStore(); for (Map.Entry< String, Property<?>> prop : myProps.entrySet()) { if (prop.getKey().startsWith(prefix)) { ps.createProperty(prop.getValue()); } } return new FF4jConfiguration(ps); } /** {@inheritDoc} */ @Override public Properties getProperties(String key) { Properties props = new Properties(); if (key == null) return props; Map < String, Property<?>> myProps = ff4jStore().readAllProperties(); for (Map.Entry< String, Property<?>> prop : myProps.entrySet()) { if (prop.getKey().startsWith(key)) { props.put(prop.getKey(), prop.getValue().getValue()); } } return props; } /** {@inheritDoc} */ @Override public boolean isEmpty() { return ff4jStore().isEmpty(); } /** {@inheritDoc} */ @Override public boolean containsKey(String key) { if (key == null) return false; return ff4jStore().existProperty(key); } /** {@inheritDoc} */ @Override public void addProperty(String key, Object value) { ff4jStore().createProperty(PropertyFactory.createProperty(key, value)); } /** {@inheritDoc} */ @Override protected void addPropertyDirect(String key, Object value) { ff4jStore().createProperty(PropertyFactory.createProperty(key, value)); } /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public void setProperty(String key, Object value) { if (!ff4jStore.existProperty(key)) { addProperty(key, value); } Property<Object> ap = (Property<Object>) ff4jStore().readProperty(key); ap.setValue(String.valueOf(value)); ff4jStore().updateProperty(ap); } /** {@inheritDoc} */ @Override public void clearProperty(String key) { ff4jStore().deleteProperty(key); } /** {@inheritDoc} */ @Override public void clear() { ff4jStore().clear(); } /** {@inheritDoc} */ @Override public Object getProperty(String key) { return ff4jStore().readProperty(key).getValue(); } /** {@inheritDoc} */ @Override public Iterator<String> getKeys(String prefix) { Set< String > setOfNames = ff4jStore().listPropertyNames(); Set< String > results = new HashSet<String>(); if (setOfNames != null && setOfNames.size() > 0) { for (String name : setOfNames) { if (name.startsWith(prefix)) { results.add(name); } } } return results.iterator(); } /** * The read will raise PropertyNotFound if not exist, null could be cast in any type. * * @param key * current property name * @return * property value */ private Object getValue(String key) { Util.assertHasLength(key); return ff4jStore().readProperty(key).asString(); } /** {@inheritDoc} */ @Override public Iterator<String> getKeys() { Set< String > init = new HashSet<String>(); Set < String > result = ff4jStore().listPropertyNames(); return (result == null) ? init.iterator() : result.iterator(); } /** * {@inheritDoc} * * Use the object : * <li> To handle 'null' and avoid NPE on unboxing * <li> To raise classCast if invalid property type... */ @Override public boolean getBoolean(String key) { String value = (String) getValue(key); if (!Boolean.TRUE.toString().equals(value.toLowerCase()) && !Boolean.FALSE.toString().equals(value.toLowerCase()) ) { throw new InvalidPropertyTypeException("Cannot create Boolean from " + value); } return new Boolean(value).booleanValue(); } /** {@inheritDoc} */ @Override public Boolean getBoolean(String key, Boolean defaultValue) { return ff4jStore().existProperty(key) ? getBoolean(key) : defaultValue; } /** {@inheritDoc} */ @Override public boolean getBoolean(String key, boolean defaultValue) { return ff4jStore().existProperty(key) ? getBoolean(key) : defaultValue; } /** {@inheritDoc} */ @Override public byte getByte(String key) { String value = null; try { value = (String) getValue(key); return Byte.parseByte(value); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Byte from " + value, nbe); } } /** {@inheritDoc} */ @Override public byte getByte(String key, byte defaultValue) { return ff4jStore().existProperty(key) ? getByte(key) : defaultValue; } /** {@inheritDoc} */ @Override public Byte getByte(String key, Byte defaultValue) { return ff4jStore().existProperty(key) ? getByte(key) : defaultValue; } /** {@inheritDoc} */ @Override public double getDouble(String key) { try { return new Double((String) getValue(key)).doubleValue(); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Double from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public double getDouble(String key, double defaultValue) { return ff4jStore().existProperty(key) ? getDouble(key) : defaultValue; } /** {@inheritDoc} */ @Override public Double getDouble(String key, Double defaultValue) { return ff4jStore().existProperty(key) ? getDouble(key) : defaultValue; } /** {@inheritDoc} */ @Override public float getFloat(String key) { try { return new Float((String) getValue(key)).floatValue(); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Float from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public float getFloat(String key, float defaultValue) { return ff4jStore().existProperty(key) ? getFloat(key) : defaultValue; } /** {@inheritDoc} */ @Override public Float getFloat(String key, Float defaultValue) { return ff4jStore().existProperty(key) ? getFloat(key) : defaultValue; } /** {@inheritDoc} */ @Override public int getInt(String key) { try { return new Integer((String) getValue(key)).intValue(); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Integer from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public int getInt(String key, int defaultValue) { return ff4jStore().existProperty(key) ? getInt(key) : defaultValue; } /** {@inheritDoc} */ @Override public Integer getInteger(String key, Integer defaultValue) { return ff4jStore().existProperty(key) ? getInt(key) : defaultValue; } /** {@inheritDoc} */ @Override public long getLong(String key) { try { return new Long((String) getValue(key)).longValue(); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Long from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public Long getLong(String key, Long defaultValue) { return ff4jStore().existProperty(key) ? getLong(key) : defaultValue; } /** {@inheritDoc} */ @Override public long getLong(String key, long defaultValue) { return ff4jStore().existProperty(key) ? getLong(key) : defaultValue; } /** {@inheritDoc} */ @Override public short getShort(String key) { try { return new Short((String) getValue(key)).shortValue(); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create Short from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public short getShort(String key, short defaultValue) { return ff4jStore().existProperty(key) ? getShort(key) : defaultValue; } /** {@inheritDoc} */ @Override public Short getShort(String key, Short defaultValue) { return ff4jStore().existProperty(key) ? getShort(key) : defaultValue; } /** {@inheritDoc} */ @Override public BigDecimal getBigDecimal(String key) { try { return new BigDecimal((String) getValue(key)); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create BigDecimal from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { return ff4jStore().existProperty(key) ? getBigDecimal(key) : defaultValue; } /** {@inheritDoc} */ @Override public BigInteger getBigInteger(String key) { try { return new BigInteger((String) getValue(key)); } catch(NumberFormatException nbe) { throw new InvalidPropertyTypeException("Cannot create BigInteger from " + getValue(key), nbe); } } /** {@inheritDoc} */ @Override public BigInteger getBigInteger(String key, BigInteger defaultValue) { return ff4jStore().existProperty(key) ? getBigInteger(key) : defaultValue; } /** {@inheritDoc} */ @Override public String getString(String key) { return (String) getValue(key); } /** {@inheritDoc} */ @Override public String getString(String key, String defaultValue) { return ff4jStore().existProperty(key) ? getString(key) : defaultValue; } /** {@inheritDoc} */ @Override public List<Object> getList(String key) { return new ArrayList<Object>( Arrays.asList( ((String) getValue(key)).split(DELIMITER))); } /** {@inheritDoc} */ @Override public List<Object> getList(String key, List<?> defaultValue) { if (ff4jStore().existProperty(key)) return getList(key); return new ArrayList<Object>(defaultValue); } /** {@inheritDoc} */ @Override public String[] getStringArray(String key) { return getList(key).toArray(new String[0]); } /** * Read FF4J Store from its attribute. * * @return * current ff4j store. */ public PropertyStore ff4jStore() { if (ff4jStore == null) { throw new IllegalStateException("Cannot load property from store as not initialized please set 'ff4jStore' property"); } return getFf4jStore(); } /** * Getter accessor for attribute 'ff4jStore'. * * @return * current value of 'ff4jStore' */ public PropertyStore getFf4jStore() { return ff4jStore; } /** * Setter accessor for attribute 'ff4jStore'. * @param ff4jStore * new value for 'ff4jStore ' */ public void setFf4jStore(PropertyStore ff4jStore) { this.ff4jStore = ff4jStore; } }