Package au.net.causal.projo.prefs.properties

Source Code of au.net.causal.projo.prefs.properties.PropertiesPreferenceNode

package au.net.causal.projo.prefs.properties;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import au.net.causal.projo.prefs.AbstractPreferenceNode;
import au.net.causal.projo.prefs.PreferenceKeyMetadata;
import au.net.causal.projo.prefs.PreferenceNode;
import au.net.causal.projo.prefs.PreferencesException;
import au.net.causal.projo.prefs.UnsupportedDataTypeException;

import com.google.common.reflect.TypeToken;

/**
* A preference node implementation that uses a {@link Properties} object to store values.
* <p>
*
* Child nodes are supported by generating property key names with '.' delimited node names and the key name.  So you will get a property name of
* 'com.example.myKey' for a key of 'myKey', a parent node of 'com' and a child node of 'example'.
*
* @author prunge
*/
public class PropertiesPreferenceNode extends AbstractPreferenceNode
{
  private static final String NODE_SEPARATOR = ".";
 
  private final Properties properties;
  private final String keyPrefix;
 
  //TODO what happens if a key name or node name contains the node separator character?
 
  /**
   * Creates a <code>PropertiesPreferenceNode</code> that wraps a {@link Properties} object.
   *
   * @param properties the properties to wrap.
   *
   * @throws NullPointerException if <code>properties</code> is null.
   */
  public PropertiesPreferenceNode(Properties properties)
  {
    this(properties, "");
  }
 
  /**
   * Creates a <code>PropertiesPreferenceNode</code> that wraps a {@link Properties} and all keys will have the specified prefix.
   * <p>
   *
   * This is not typically used by end-users, as it mostly provides a way of creating child nodes.
   *
   * @param properties the properties to wrap.
   * @param keyPrefix the key prefix.
   *
   * @throws NullPointerException if <code>properties</code> or <code>keyPrefix</code> is null.
   */
  public PropertiesPreferenceNode(Properties properties, String keyPrefix)
  {
    super(Collections.<Class<? extends Annotation>>emptySet());
   
    if (properties == null)
      throw new NullPointerException("properties == null");
    if (keyPrefix == null)
      throw new NullPointerException("keyPrefix == null");
   
    this.properties = properties;
    this.keyPrefix = keyPrefix;
  }

  @Override
  protected boolean isDataTypeSupportedImpl(PreferenceKeyMetadata<?> keyType) throws PreferencesException
  {
    return(isDataTypeSupported(keyType.getDataType()));
  }
 
  private boolean isDataTypeSupported(TypeToken<?> type) throws PreferencesException
  {
    //Only supports string values
    return(TypeToken.of(String.class).equals(type));
  }

  @Override
  protected <T> T getValueImpl(String key, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
  {
    if (key == null)
      throw new NullPointerException("key == null");
    if (metadata == null)
      throw new NullPointerException("metadata == null");
    if (!isDataTypeSupported(metadata.getDataType()))
      throw new UnsupportedDataTypeException(metadata.getDataType());
   
    String fullKey = keyPrefix + key;
    String value = properties.getProperty(fullKey);
   
    //We know T is for String since that is the only supported data type
    @SuppressWarnings("unchecked")
    T safeValue = (T)value;
   
    return(safeValue);
  }

  @Override
  protected <T> void putValueImpl(String key, T value, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
  {
    if (key == null)
      throw new NullPointerException("key == null");
    if (metadata == null)
      throw new NullPointerException("metadata == null");
    if (!isDataTypeSupported(metadata.getDataType()))
      throw new UnsupportedDataTypeException(metadata.getDataType());
   
    String fullKey = keyPrefix + key;

    properties.setProperty(fullKey, (String)value);
  }

  @Override
  protected <T> void removeValueImpl(String key, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
  {
    if (key == null)
      throw new NullPointerException("key == null");
    if (metadata == null)
      throw new NullPointerException("metadata == null");
    if (!isDataTypeSupported(metadata.getDataType()))
      throw new UnsupportedDataTypeException(metadata.getDataType());
   
    String fullKey = keyPrefix + key;

    properties.remove(fullKey);
  }
 
  @Override
  public void removeAllValues() throws PreferencesException
  {
    //Look for all nodes with our prefix and no other separator characters
    for (String propertyName : properties.stringPropertyNames())
    {
      if (propertyName.startsWith(keyPrefix))
      {
        String unprefixedPropertyName = propertyName.substring(keyPrefix.length());
        if (!unprefixedPropertyName.contains(NODE_SEPARATOR))
          properties.remove(propertyName);
      }
    }
  }

  @Override
  public PreferenceNode getChildNode(String name) throws PreferencesException
  {
    String fullPrefix = keyPrefix + name + NODE_SEPARATOR;
    return(new PropertiesPreferenceNode(properties, fullPrefix));
  }

  @Override
  public void removeChildNode(String name) throws PreferencesException
  {
    getChildNode(name).removeAllValues();
  }

  @Override
  public Set<String> getKeyNames() throws PreferencesException
  {
    Set<String> keyNames = new LinkedHashSet<>();
   
    //Look for all nodes with our prefix and no other separator characters
    for (String propertyName : properties.stringPropertyNames())
    {
      if (propertyName.startsWith(keyPrefix))
      {
        String unprefixedPropertyName = propertyName.substring(keyPrefix.length());
        if (!unprefixedPropertyName.contains(NODE_SEPARATOR))
          keyNames.add(unprefixedPropertyName);
      }
    }
   
    return(keyNames);
  }

  @Override
  public Set<String> getNodeNames() throws PreferencesException
  {
    Set<String> nodeNames = new LinkedHashSet<>();
   
    //Look for all nodes with our prefix and no other separator characters
    for (String propertyName : properties.stringPropertyNames())
    {
      if (propertyName.startsWith(keyPrefix))
      {
        String unprefixedPropertyName = propertyName.substring(keyPrefix.length());
        String[] splitPropertyName = unprefixedPropertyName.split(Pattern.quote(NODE_SEPARATOR), 2);
        if (splitPropertyName.length > 1) //Don't include keys, just child nodes
          nodeNames.add(splitPropertyName[0]);
      }
    }
   
    return(nodeNames);
  }
 
  @Override
  public void flush() throws PreferencesException
  {
    //Nothing to do
  }
 
  @Override
  public void close() throws PreferencesException
  {
    flush();
  }
}
TOP

Related Classes of au.net.causal.projo.prefs.properties.PropertiesPreferenceNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.