Beginner Tutorial - Configuration

Introduction

Having a place to store custom configuration is a better choice than creating a table every time, especially when the custom data is limited. In this tutorial, we will learn how to store configuration into FineDB.

Store into FineDB

All the configuration data are stored in the FINE_CONF_ENTITY table of FineDB, such as the data connection config.

In order to store custom data, we need to wrap our object by com.fr.config.holder.Conf, and pass actual data type by generics. FineReport has provided a factory class com.fr.config.holder.factory.Holders to construct the instance.

package com.fr.config.holder.factory;

import com.fr.config.holder.Conf;
import com.fr.config.holder.impl.ColConf;
import com.fr.config.holder.impl.MapConf;
import com.fr.config.holder.impl.ObjConf;
import com.fr.config.holder.impl.ObjectColConf;
import com.fr.config.holder.impl.ObjectMapConf;
import com.fr.config.holder.impl.SimConf;

import java.util.Collection;
import java.util.Map;

/**
 * Factory class of the wrapper
 */
public class Holders {
    /**
     * Create a Holder for basic types. It should be used as long as T does not contain a ConfigHolder field
     *
     * @param property
     * @param t
     * @param nameSpace
     * @param <T>      
     * @return
     * @see Holders#simple(Object)
     */
    @Deprecated
    public static <T> Conf<T> simple(String property, T t, String nameSpace) {
        return new SimConf<T>(property, t).setNameSpace(nameSpace);
    }

    public static <T> Conf<T> simple(T t) {
        return new SimConf<T>(t);
    }

    /**
     * Create a Holder for T class. T contains a ConfigHolder field.
     *
     * @param property
     * @param t
     * @param type
     * @param nameSpace
     * @param <T>
     * @return
     * @see Holders#obj(Object, Class)
     */
    @Deprecated
    public static <T> Conf<T> obj(String property, T t, Class<T> type, String nameSpace) {
        return new ObjConf<T>(property, t, type).setNameSpace(nameSpace);
    }

    public static <T> Conf<T> obj(T t, Class<T> type) {
        return new ObjConf<T>(t, type);
    }


    /**
     * Create a Holder for the collection of basic data types.
     *
     * @param property
     * @param collection
     * @param valueType
     * @param nameSpace
     * @param <K>
     * @return
     * @see Holders#objCollection(Collection, Class)
     */
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <K> Conf<Collection<K>> collection(String property, Collection<K> collection, Class<K> valueType, String nameSpace) {
        return new ColConf(property, collection, valueType).setNameSpace(nameSpace);
    }

    @SuppressWarnings("unchecked")
    public static <K> ColConf<Collection<K>> collection(Collection<K> collection, Class<K> valueType) {
        return new ColConf(collection, valueType);
    }

    /**
     * Create a Holder for the collection of T class.
     *
     * @param property   属性标签
     * @param collection
     * @param type
     * @param nameSpace  名字空间
     * @param <T>
     * @return 属性节点的包装
     * @see Holders#collection(Collection, Class)
     */
    @Deprecated
    public static <T> ObjectColConf<Collection<T>> objCollection(String property, Collection<T> collection, Class<T> type, String nameSpace) {
        return new ObjectColConf<Collection<T>>(property, collection, type).setNameSpace(nameSpace);
    }

    public static <T> ObjectColConf<Collection<T>> objCollection(Collection<T> collection, Class<T> type) {
        return new ObjectColConf<Collection<T>>(collection, type);
    }

    public static <T> ObjectColConf<Collection<T>> objCollection(Collection<T> collection, Class<T> type, boolean order) {
        return new ObjectColConf<Collection<T>>(collection, type, order);
    }

    /**
     * Create a Holder for the Map which key and value are of basic type.
     *
     * @param property
     * @param map
     * @param keyType   not null
     * @param valueType not null
     * @param nameSpace
     * @param <K>
     * @param <V>
     * @return
     * @see Holders#map(Map, Class, Class)
     */
    @Deprecated
    @SuppressWarnings("unchecked")
    public static <K, V> MapConf<Map<K, V>> map(String property, Map<K, V> map, Class<K> keyType, Class<V> valueType, String nameSpace) {
        return new MapConf(property, map, keyType, valueType).setNameSpace(nameSpace);
    }

    @SuppressWarnings("unchecked")
    public static <K, V> MapConf<Map<K, V>> map(Map<K, V> map, Class<K> keyType, Class<V> valueType) {
        return new MapConf(map, keyType, valueType);
    }

    /**
     * Value is a Holder for the Map of V class. V contains a ConfigHolder field.
     * KeyType can be empty, but the key in the map has to be basic type or String. ValueType can be empty, but it has to be complex type.
     *
     * @param property
     * @param map
     * @param keyType
     * @param valueType
     * @param nameSpace
     * @param <K>
     * @param <V>
     * @return
     * @see Holders#objMap(Map, Class, Class)
     */
    @Deprecated
    public static <K, V> ObjectMapConf<Map<K, V>> objMap(String property, Map<K, V> map, Class<K> keyType, Class<V> valueType, String nameSpace) {
        return new ObjectMapConf<Map<K, V>>(property, map, keyType, valueType).setNameSpace(nameSpace);
    }

    public static <K, V> ObjectMapConf<Map<K, V>> objMap(Map<K, V> map, Class<K> keyType, Class<V> valueType) {
        return new ObjectMapConf<Map<K, V>>(map, keyType, valueType);
    }

    public static <K, V> ObjectMapConf<Map<K, V>> objMap(Map<K, V> map, Class<K> keyType, Class<V> valueType, boolean ordered) {
        return new ObjectMapConf<Map<K, V>>(map, keyType, valueType, ordered);
    }
}

Basic Type

Use Holders.simple() to create such configuration, Including basic types and String.

private Conf<String> demoString = Holders.simple(StringUtils.EMPTY);

public String getDemoString(){
    return demoString.get();
}

public void setDemoString(String s){
    demoString.set(s);
}

Data Model with Conf Member

If we define a data model, which member value also needs to be stored, we should wrap the member with Conf. In addition, the data model has to be created by Holders.obj().

package com.fr.plugin.configfile;

import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
import com.fr.config.utils.UniqueKey;
import com.fr.stable.StringUtils;

public class CustomConfig extends UniqueKey {
    private Conf<String> simpledata = Holders.simple(StringUtils.EMPTY);
    public String getSimpledata(){
        return simpledata.get();
    }
    public void setSimpledata(String simple){
        simpledata.set(simple);
    }
}
private Conf<CustomConfig> democusConfig = Holders.obj(new CustomConfig(),CustomConfig.class);

public CustomConfig getDemocusConfig() {
    return democusConfig.get();
}
public void setDemocusConfig(CustomConfig democusConfig) {
    this.democusConfig.set(democusConfig);
}

Collection of Basic Type

Use Holders.collection() as the constructor.

private ColConf<Collection<String>> stringList = Holders.collection(new ArrayList<String>(),String.class);

public List<String> getStringList(){
    return (List<String>) this.stringList.get();
}
public void setStringList(List<String> list){
    this.stringList.set(list);
}
public void addStringListValue(String s){
    this.stringList.add(s);
}

Notice: use the add/remove method of ColConf in order to store the modification into the FineDB.

Collection of Data Model

If elements are of the type such as CustomConfig defined above, we should use Holders.objCollection().

private ObjectColConf<Collection<CustomConfig>> customConfigList = Holders.objCollection(new ArrayList<CustomConfig>(), CustomConfig.class);

public List<CustomConfig> getCustomConfigList(){
    return (List<CustomConfig>) this.customConfigList.get();
}
public void setCustomConfigList(List<CustomConfig> list){
    this.customConfigList.set(list);
}
public void addCustomConfigListValue(CustomConfig config){
    this.customConfigList.add(config);
}

Map of Basic Type

If the data is a map with key and value of basic type, we should use Holders.map().

private MapConf<Map<String,Integer>> mapString = Holders.map(new HashMap<String,Integer>(),String.class,Integer.class);

public Map<String,Integer> getStringMap(){
    return  this.mapString.get();
}
public void setStringMap(Map<String,Integer> mapString){
    this.mapString.set(mapString);
}
public void putStringMap(String key,Integer value){
    this.mapString.put(key,value);
}

Notice: use the method of MapConf to modify the map.

Map of Data Model

If the key of a map is a basic type and the value is a data model like CustomConfig, we should use Holders.objMap().

private ObjectMapConf<Map<String,CustomConfig>> mapCustomConfig = Holders.objMap(new HashMap<String,CustomConfig>(),String.class,CustomConfig.class);

public Map<String,CustomConfig> getCustomconfigMap(){
    return this.mapCustomConfig.get();
}
public void setCustomconfigMap(Map<String,CustomConfig> map){
    this.mapCustomConfig.set(map);
}
public void putCustomConfigMap(String key,CustomConfig value){
    this.mapCustomConfig.put(key,value);
}

Example

Configuration Class

After defining these configs, we need a class to encapsulate them. The configuration class has to inherit com.fr.config.DefaultConfiguration.

package com.fr.plugin.configfile;

import com.fr.config.ConfigContext;

import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
import com.fr.config.holder.impl.ColConf;
import com.fr.config.holder.impl.MapConf;
import com.fr.config.holder.impl.ObjectColConf;
import com.fr.config.holder.impl.ObjectMapConf;
import com.fr.stable.StringUtils;

import java.util.*;

public class Config extends com.fr.config.DefaultConfiguration {
    private static Config config = null;
    private Conf<String> demoString = Holders.simple(StringUtils.EMPTY);
    private Conf<CustomConfig> democusConfig = Holders.obj(new CustomConfig(), CustomConfig.class);
    private ColConf<Collection<String>> stringList = Holders.collection(new ArrayList<String>(), String.class);
    private ObjectColConf<Collection<CustomConfig>> customConfigList = Holders.objCollection(new ArrayList<CustomConfig>(), CustomConfig.class);
    private MapConf<Map<String, Integer>> mapString = Holders.map(new HashMap<String, Integer>(), String.class, Integer.class);
    private ObjectMapConf<Map<String, CustomConfig>> mapCustomConfig = Holders.objMap(new HashMap<String, CustomConfig>(), String.class, CustomConfig.class);

    // Use singleton to create the instance.
    public static Config getInstance() {
        if (config == null) {
            config = ConfigContext.getConfigInstance(Config.class);
        }
        return config;
    }

    // The namespace is the prefix of the config in FINE_CONF_ENTITY
    public String getNameSpace() {
        return "configFR";
    }

    public String getDemoString() {
        return this.demoString.get();
    }

    public void setDemoString(String s) {
        this.demoString.set(s);
    }

    public CustomConfig getDemocusConfig() {
        return democusConfig.get();
    }

    public void setDemocusConfig(CustomConfig democusConfig) {
        this.democusConfig.set(democusConfig);
    }

    public List<String> getStringList() {
        return (List<String>) this.stringList.get();
    }

    public void setStringList(List<String> list) {
        this.stringList.set(list);
    }

    public void addStringListValue(String s) {

        this.stringList.add(s);
    }

    public List<CustomConfig> getCustomConfigList() {
        return (List<CustomConfig>) this.customConfigList.get();
    }

    public void setCustomConfigList(List<CustomConfig> list) {
        this.customConfigList.set(list);
    }

    public void addCustomConfigListValue(CustomConfig config) {
        this.customConfigList.add(config);
    }

    public Map<String, Integer> getStringMap() {
        return this.mapString.get();
    }

    public void setStringMap(Map<String, Integer> mapString) {

        this.mapString.set(mapString);
    }

    public void putStringMap(String key, Integer value) {
        this.mapString.put(key, value);
    }

    public Map<String, CustomConfig> getCustomconfigMap() {
        return this.mapCustomConfig.get();
    }

    public void setCustomconfigMap(Map<String, CustomConfig> map) {
        this.mapCustomConfig.set(map);
    }

    public void putCustomConfigMap(String key, CustomConfig value) {
        this.mapCustomConfig.put(key, value);
    }

}

Save the configuration

public class DemoHandler extends BaseHttpHandler {
    @Override
    public RequestMethod getMethod() {
        return null;
    }

    @Override
    public String getPath() {
        return "/demo/test";
    }

    @Override
    public boolean isPublic() {
        return true;
    }

    @Override
    public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception {

        // Basic data type
        Config config = Config.getInstance();
        config.setDemoString("Demo String");

        // Custom data model
        CustomConfig demoConfig = new CustomConfig("Data Model");
        config.setDemocusConfig(demoConfig);

        // Collection of basic type
        List<String> stringValues = new ArrayList<String>();
        stringValues.add("Data 1");
        stringValues.add("Data 2");
        config.setStringList(stringValues);

        // Collection of data model
        List<CustomConfig> customList=new ArrayList<CustomConfig>();
        customList.add(new CustomConfig("Data Model 1"));
        customList.add(new CustomConfig("Data Model 2"));
        config.setCustomConfigList(customList);

        // Map of basic type
        Map<String,Integer> stringMap=new HashMap<String,Integer>();
        stringMap.put("Basic test 1",1);
        stringMap.put("Basic test 2",2);
        config.setStringMap(stringMap);

        // Map of data model
        Map<String,CustomConfig> customConfigMap=new HashMap<String,CustomConfig>();
        customConfigMap.put("Custom test 1",new CustomConfig("Custom test 1"));
        customConfigMap.put("Custom test 2",new CustomConfig("Custom test 2"));
        config.setCustomconfigMap(customConfigMap);

    }
}

result

results matching ""

    No results matching ""