/*
* (c) Rob Gordon 2005
*/
package org.oddjob.values.types;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.MutableDynaClass;
import org.oddjob.arooa.convert.Convertlet;
import org.oddjob.arooa.convert.ConvertletException;
import org.oddjob.arooa.convert.ConversionProvider;
import org.oddjob.arooa.convert.ConversionRegistry;
import org.oddjob.values.properties.PropertiesJob;
/**
* @oddjob.description This is an internal type used to allow nested properties
* in a {@link PropertiesJob}.
*/
public class PropertyType implements DynaBean, Serializable {
private static final long serialVersionUID = 2009042200L;
public static class Conversions implements ConversionProvider {
public void registerWith(ConversionRegistry registry) {
registry.register(PropertyType.class, String.class,
new Convertlet<PropertyType, String>() {
public String convert(PropertyType from) throws ConvertletException {
return from.value;
}
});
registry.register(PropertyType.class, Properties.class,
new Convertlet<PropertyType, Properties>() {
public Properties convert(PropertyType from) throws ConvertletException {
return from.toProperties();
}
});
}
}
/** Nested properties. */
private final Map<String, PropertyType> props =
new HashMap<String, PropertyType>();
/** The dynaClass. Should name be unique? - don't know. */
private final MutableDynaClass dynaClass = new PropertyTypeDynaClass(PropertyTypeDynaClass.class.getName());
/** The value of this property. */
private String value;
/** The name of this property. */
private final String name;
/**
* Only public constructor. Used to create the root of a property
* hierarchy.
*
*/
public PropertyType() {
this.name = null;
}
/**
* Private contructor used by add and set.
*
* @param name The name of the property being created.
*/
private PropertyType(String name) {
this.name = name;
}
/**
* Accumulate properties.
*
* @param props Properties accumulated so far.
*/
void properties(Properties result, String stem) {
String propertyName = "";
String nextStem = "";
if (name != null) {
propertyName = stem + name;
nextStem = propertyName + ".";
}
if (value != null) {
result.setProperty(propertyName, value);
}
for (String childName : props.keySet()) {
PropertyType child = props.get(childName);
child.properties(result, nextStem);
}
}
/**
* Converts this PropertyType into Properties.
*
* @return
*/
public Properties toProperties() {
Properties props = new Properties();
properties(props, "");
return props;
}
/**
* Get the size, which is the number of children,
* for this property.
*
* @return The number of children.
*/
public int size() {
return props.size();
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#contains(java.lang.String, java.lang.String)
*/
public boolean contains(String name, String key) {
throw new UnsupportedOperationException("Can't perform key operations on properties.");
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#get(java.lang.String)
*/
public Object get(String name) {
PropertyType prop = props.get(name);
if (prop == null) {
// no? - create a new PropertyType
prop = new PropertyType(name);
// and add it to the lazy bean.
props.put(prop.name, prop);
dynaClass.add(name);
}
return prop;
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#get(java.lang.String, int)
*/
public Object get(String name, int index) {
throw new UnsupportedOperationException("Can't get indexed values on properties.");
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#get(java.lang.String, java.lang.String)
*/
public Object get(String name, String key) {
throw new UnsupportedOperationException("Can't get mapped values on properties.");
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#getDynaClass()
*/
public DynaClass getDynaClass() {
return dynaClass;
}
/*
* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#remove(java.lang.String, java.lang.String)
*/
public void remove(String name, String key) {
throw new UnsupportedOperationException("Can't remove mapped values on properties.");
}
/*
* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#set(java.lang.String, int, java.lang.Object)
*/
public void set(String name, int index, Object value) {
throw new UnsupportedOperationException("Can't set mapped values on properties.");
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#set(java.lang.String, java.lang.Object)
*/
public void set(String name, Object value) {
// does our map already contain the value
PropertyType prop = (PropertyType) props.get(name);
if (prop == null) {
// no? - create a new PropertyType
prop = new PropertyType(name);
// and add it to the map.
props.put(prop.name, prop);
dynaClass.add(name);
}
prop.value = (String) value;
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.DynaBean#set(java.lang.String, java.lang.String, java.lang.Object)
*/
public void set(String name, String key, Object value) {
throw new UnsupportedOperationException("Can't set mapped values on properties.");
}
/**
* Override toString().
*
* @return a String or null if the resolved value is null.
*/
public String toString() {
if (value != null) {
return "Property: " + name + "=" + value;
}
else if (name != null){
return "Properties starting with " + name + ": " + size() + " sub types.";
}
else {
return "Properties root: " + size() + " sub types.";
}
}
}