    001/*
    002 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
    003 *
    004 * Project and contact information: http://www.cascading.org/
    005 *
    006 * This file is part of the Cascading project.
    007 *
    008 * Licensed under the Apache License, Version 2.0 (the "License");
    009 * you may not use this file except in compliance with the License.
    010 * You may obtain a copy of the License at
    011 *
    012 *     http://www.apache.org/licenses/LICENSE-2.0
    013 *
    014 * Unless required by applicable law or agreed to in writing, software
    015 * distributed under the License is distributed on an "AS IS" BASIS,
    016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    017 * See the License for the specific language governing permissions and
    018 * limitations under the License.
    019 */
    020
    021package cascading.property;
    022
    023import java.io.Serializable;
    024import java.util.Collection;
    025import java.util.Collections;
    026import java.util.HashMap;
    027import java.util.HashSet;
    028import java.util.Map;
    029import java.util.Set;
    030
    031/**
    032 * The ConfigDef class allows for the creation of a configuration properties template to be applied to an existing
    033 * properties configuration set.
    034 * <p/>
    035 * There are three property modes, {@link Mode#DEFAULT}, {@link Mode#REPLACE}, and {@link Mode#UPDATE}.
    036 * <p/>
    037 * <ul>
    038 * <li>A DEFAULT property is only applied if there is no existing value in the property set.</li>
    039 * <li>A REPLACE property is always applied overriding any previous values.</li>
    040 * <li>An UPDATE property is always applied to an existing property. Usually when the property key represent a list of values.</li>
    041 * </ul>
    042 */
    043public class ConfigDef implements Serializable
    044  {
    045  public enum Mode
    046    {
    047      DEFAULT, REPLACE, UPDATE
    048    }
    049
    050  public interface Setter
    051    {
    052    String set( String key, String value );
    053
    054    String update( String key, String value );
    055
    056    String get( String key );
    057    }
    058
    059  public interface Getter
    060    {
    061    String update( String key, String value );
    062
    063    String get( String key );
    064    }
    065
    066  protected Map<Mode, Map<String, String>> config;
    067
    068  public ConfigDef()
    069    {
    070    }
    071
    072  /**
    073   * Method setProperty sets the value to the given key using the {@link Mode#REPLACE} mode.
    074   *
    075   * @param key   the key
    076   * @param value the value
    077   * @return the current ConfigDef instance
    078   */
    079  public ConfigDef setProperty( String key, String value )
    080    {
    081    return setProperty( Mode.REPLACE, key, value );
    082    }
    083
    084  /**
    085   * Method setProperty sets the value to the given key using the given {@link Mode} value.
    086   *
    087   * @param key   the key
    088   * @param value the value
    089   * @return the current ConfigDef instance
    090   */
    091  public ConfigDef setProperty( Mode mode, String key, String value )
    092    {
    093    getMode( mode ).put( key, value );
    094
    095    return this;
    096    }
    097
    098  protected Map<String, String> getMode( Mode mode )
    099    {
    100    if( config == null )
    101      config = new HashMap<Mode, Map<String, String>>();
    102
    103    if( !config.containsKey( mode ) )
    104      config.put( mode, new HashMap<String, String>() );
    105
    106    return config.get( mode );
    107    }
    108
    109  protected Map<String, String> getModeSafe( Mode mode )
    110    {
    111    if( config == null )
    112      return Collections.EMPTY_MAP;
    113
    114    if( !config.containsKey( mode ) )
    115      return Collections.EMPTY_MAP;
    116
    117    return config.get( mode );
    118    }
    119
    120  /**
    121   * Returns {@code true} if there are no properties.
    122   *
    123   * @return true if no properties.
    124   */
    125  public boolean isEmpty()
    126    {
    127    return config == null || config.isEmpty();
    128    }
    129
    130  public String apply( String key, Getter getter )
    131    {
    132    String defaultValue = getModeSafe( Mode.DEFAULT ).get( key );
    133    String replaceValue = getModeSafe( Mode.REPLACE ).get( key );
    134    String updateValue = getModeSafe( Mode.UPDATE ).get( key );
    135
    136    String currentValue = getter.get( key );
    137
    138    if( currentValue == null && replaceValue == null && updateValue == null )
    139      return defaultValue;
    140
    141    if( replaceValue != null )
    142      return replaceValue;
    143
    144    if( updateValue == null )
    145      return currentValue;
    146
    147    if( currentValue == null )
    148      return updateValue;
    149
    150    return getter.update( key, updateValue );
    151    }
    152
    153  public void apply( Mode mode, Setter setter )
    154    {
    155    if( !config.containsKey( mode ) )
    156      return;
    157
    158    for( String key : config.get( mode ).keySet() )
    159      {
    160      switch( mode )
    161        {
    162        case DEFAULT:
    163          if( setter.get( key ) == null )
    164            setter.set( key, config.get( mode ).get( key ) );
    165          break;
    166        case REPLACE:
    167          setter.set( key, config.get( mode ).get( key ) );
    168          break;
    169        case UPDATE:
    170          setter.update( key, config.get( mode ).get( key ) );
    171          break;
    172        }
    173      }
    174    }
    175
    176  public Collection<String> getAllKeys()
    177    {
    178    Set<String> keys = new HashSet<String>();
    179
    180    for( Map<String, String> map : config.values() )
    181      keys.addAll( map.keySet() );
    182
    183    return Collections.unmodifiableSet( keys );
    184    }
    185  }