com.dockingsoftware.dockingpreference.PreferenceProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.dockingsoftware.dockingpreference.PreferenceProcessor.java

Source

/*
 * Copyright 2016 Shunyi Chen
 *
 * 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.
 */

package com.dockingsoftware.dockingpreference;

import com.dockingsoftware.dockingpreference.persistent.DefaultPersistentAdapter;
import com.dockingsoftware.dockingpreference.persistent.PersistentAdapterIF;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class PreferenceProcessor {

    /**
     * Loads preference by filePath.
     * 
     * @param filePath
     * @return 
     */
    public Object load(String filePath) {
        Object obj = null;
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(file);
            Element parent = doc.getRootElement();
            NodeInfo rootInfo = new NodeInfo(parent);
            obj = Class.forName(rootInfo.getClazz()).newInstance();
            load(obj, parent);
        } catch (DocumentException ex) {
            String errMsg = "The system cannot find the file specified path " + filePath + ".";
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, errMsg, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            String errMsg = "No-args constructor is missing for " + ex.getMessage();
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, errMsg, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return obj;
    }

    /**
     * Loads user preference information.
     * 
     * @param obj the object whose field should be modified
     */
    public void load(Object obj) {
        String filePath = GlobalConstant.USER_HOME + "/" + obj.getClass().getName() + GlobalConstant.FILE_EXTENSION;
        File file = new File(filePath);
        if (!file.exists()) {
            return;
        }
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(file);
            Element parent = doc.getRootElement();
            load(obj, parent);
        } catch (DocumentException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            String errMsg = "No-args constructor is missing for " + ex.getMessage();
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, errMsg, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Loads user preference information.
     * 
     * @param obj
     * @param parent
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException 
     */
    private void load(Object obj, Element parent) throws ClassNotFoundException, InstantiationException,
            IllegalArgumentException, IllegalAccessException, Exception {

        Class cls = obj.getClass();

        if (cls.isArray()) {
            List<NodeInfo> infos = new ArrayList<NodeInfo>();
            List<Element> lstChildren = parent.elements();
            for (int i = 0; i < lstChildren.size(); i++) {
                Element child = lstChildren.get(i);
                NodeInfo nodeInfo = new NodeInfo(child);
                infos.add(nodeInfo);
            }

            Object array = obj;

            for (int i = 0; i < infos.size(); i++) {
                NodeInfo info = infos.get(i);
                Class fieldClass = Class.forName(info.getClazz());
                if (!StringUtils.isBlank(info.getValue())) {

                    PersistentAdapterIF adapter;
                    if (info.getAdapter() == null) {
                        adapter = new DefaultPersistentAdapter();
                    } else {
                        adapter = (PersistentAdapterIF) Class.forName(info.getAdapter()).newInstance();
                    }
                    //Gets the new value for the field of obj.
                    Object fieldValue = adapter.restore(info.getValue(), fieldClass);
                    Array.set(array, i, fieldValue);
                } else {

                    Object fieldValue = fieldClass.newInstance();
                    // Loading children
                    load(fieldValue, info.getElement());
                    Array.set(array, i, fieldValue);
                }
            }
        } else if (obj instanceof Collection) {

            List<NodeInfo> infos = new ArrayList<NodeInfo>();
            List<Element> lstChildren = parent.elements();
            for (int i = 0; i < lstChildren.size(); i++) {
                Element child = lstChildren.get(i);
                NodeInfo nodeInfo = new NodeInfo(child);
                infos.add(nodeInfo);
            }

            Collection coll = (Collection) obj;

            for (int i = 0; i < infos.size(); i++) {
                NodeInfo info = infos.get(i);
                Class fieldClass = Class.forName(info.getClazz());
                if (!StringUtils.isBlank(info.getValue())) {

                    PersistentAdapterIF adapter = null;
                    if (info.getAdapter() == null) {
                        adapter = new DefaultPersistentAdapter();
                    } else {
                        adapter = (PersistentAdapterIF) Class.forName(info.getAdapter()).newInstance();
                    }
                    //Gets the new value for the field of obj.
                    Object fieldValue = adapter.restore(info.getValue(), fieldClass);
                    coll.add(fieldValue);
                } else {

                    Object fieldValue = fieldClass.newInstance();
                    // Loading children
                    load(fieldValue, info.getElement());
                    coll.add(fieldValue);
                }
            }
        } else if (obj instanceof Map) {
            // Key is always String type. 
            Map<String, NodeInfo> infos = new HashMap<String, NodeInfo>();
            List<Element> lstKeys = parent.elements();
            for (int i = 0; i < lstKeys.size(); i++) {
                Element keyEle = lstKeys.get(i);
                Element valueEle = (Element) keyEle.elements().get(0);
                NodeInfo valueInfo = new NodeInfo(valueEle);
                infos.put(keyEle.getText().trim(), valueInfo);
            }

            Map map = (Map) obj;

            Iterator<String> iter = infos.keySet().iterator();
            while (iter.hasNext()) {
                String key = iter.next();
                NodeInfo valueInfo = infos.get(key);
                Class fieldClass = Class.forName(valueInfo.getClazz());
                if (!StringUtils.isBlank(valueInfo.getValue())) {

                    PersistentAdapterIF adapter = null;
                    if (valueInfo.getAdapter() == null) {
                        adapter = new DefaultPersistentAdapter();
                    } else {
                        adapter = (PersistentAdapterIF) Class.forName(valueInfo.getAdapter()).newInstance();
                    }
                    //Gets the new value for the field of obj.
                    Object fieldValue = adapter.restore(valueInfo.getValue(), fieldClass);
                    map.put(key, fieldValue);
                } else {

                    Object fieldValue = fieldClass.newInstance();
                    // Loading children
                    load(fieldValue, valueInfo.getElement());
                    map.put(key, fieldValue);
                }
            }
        } else {

            Map<String, NodeInfo> infos = new HashMap<String, NodeInfo>();
            List<Element> lstChildren = parent.elements();
            for (int i = 0; i < lstChildren.size(); i++) {
                Element child = lstChildren.get(i);
                NodeInfo nodeInfo = new NodeInfo(child);
                infos.put(nodeInfo.getName(), nodeInfo);
            }

            Field[] fields = cls.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                NodeInfo info = infos.get(fields[i].getName());
                if (info != null) {

                    Class fieldClass = Class.forName(info.getClazz());
                    if (!StringUtils.isBlank(info.getValue())) {

                        PersistentAdapterIF adapter = null;
                        if (info.getAdapter() == null) {
                            adapter = new DefaultPersistentAdapter();
                        } else {
                            adapter = (PersistentAdapterIF) Class.forName(info.getAdapter()).newInstance();
                        }
                        //Gets the new value for the field of obj.
                        Object fieldValue = adapter.restore(info.getValue(), fieldClass);
                        fields[i].set(obj, fieldValue);

                    } else {

                        if (fieldClass == java.lang.reflect.Array.class) {

                            Class arryCls = Class.forName(info.getArrayType());
                            Object fieldValue = Array.newInstance(arryCls, Integer.parseInt(info.getArrayLength()));
                            // Loading children
                            load(fieldValue, info.getElement());
                            fields[i].set(obj, fieldValue);
                        } else {

                            Object fieldValue = fieldClass.newInstance();
                            // Loading children
                            load(fieldValue, info.getElement());
                            fields[i].set(obj, fieldValue);
                        }
                    }
                }
            }

        }
    }

    /**
     * Store user preference information to default file.
     * 
     * @param obj 
     */
    public void store(Object obj) {
        store(obj, GlobalConstant.USER_HOME + "/" + obj.getClass().getName() + GlobalConstant.FILE_EXTENSION);
    }

    /**
     * Store user preference information to a specified file.
     * 
     * @param obj 
     * @param fullPath Specified the full path of the configuration file.
     */
    public void store(Object obj, String fullPath) {
        try {
            FileWriter out;
            Document document = DocumentHelper.createDocument();
            Element root = document.addElement(getName(obj.getClass()));
            root.addAttribute(GlobalConstant.CLASS, obj.getClass().getName());

            List<Field> pFields = getPreferenceFieldList(obj.getClass());
            for (int i = 0; i < pFields.size(); i++) {
                store(obj, pFields.get(i), root);
            }

            OutputFormat format = new OutputFormat("  ", true);
            out = new FileWriter(new File(fullPath));
            XMLWriter w = new XMLWriter(out, format);
            w.write(document);
            w.close();
            out.close();

        } catch (IOException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Store object tree into XML file.
     * 
     * @param obj
     * @param alias
     * @param parent
     * @throws IllegalArgumentException
     * @throws IllegalAccessException 
     */
    private void store(Object obj, Field field, Element parent)
            throws IllegalArgumentException, IllegalAccessException {
        Object fieldValue = field.get(obj);
        PreferenceField pf = field.getAnnotation(com.dockingsoftware.dockingpreference.PreferenceField.class);
        if (fieldValue != null) {
            store(field.getType(), field.getName(), fieldValue, parent, pf.adapter());
        }
    }

    /**
     * Store object tree into XML file.
     * 
     * @param fieldClass
     * @param fieldName
     * @param fieldValue
     * @param parent
     * @param adapterClass
     * @throws IllegalArgumentException
     * @throws IllegalAccessException 
     */
    private void store(Class fieldClass, String fieldName, Object fieldValue, Element parent,
            Class<? extends PersistentAdapterIF> adapterClass)
            throws IllegalArgumentException, IllegalAccessException {

        if (fieldClass.isArray()) {

            if (fieldName.endsWith("[]")) {
                fieldName = fieldName.substring(0, fieldName.length() - 2);
            }
            Object[] array = (Object[]) fieldValue;
            Element arrayEle = parent.addElement(fieldName);
            String arryType = fieldClass.getName();
            arryType = arryType.substring(arryType.lastIndexOf("[") + 2, arryType.length() - 1);
            arrayEle.addAttribute(GlobalConstant.CLASS, GlobalConstant.ARRAY);
            arrayEle.addAttribute(GlobalConstant.ARRAY_TYPE, arryType);
            arrayEle.addAttribute(GlobalConstant.ARRAY_LENGTH, array.length + "");

            for (int i = 0; i < array.length; i++) {

                List<Field> arrFields = getPreferenceFieldList(array[i].getClass());
                if (arrFields.size() > 0) {

                    Element child = arrayEle.addElement(getName(array[i].getClass()));
                    child.addAttribute(GlobalConstant.CLASS, array[i].getClass().getName());
                    for (int j = 0; j < arrFields.size(); j++) {
                        store(array[i], arrFields.get(j), child);
                    }
                } else {
                    store(array[i].getClass(), array[i].getClass().getSimpleName(), array[i], arrayEle,
                            adapterClass);
                }
            }

        } else if (fieldValue instanceof Collection) {
            Element lstEle = parent.addElement(fieldName);
            lstEle.addAttribute(GlobalConstant.CLASS, fieldValue.getClass().getName());

            Collection coll = (Collection) fieldValue;
            Iterator iter = coll.iterator();
            while (iter.hasNext()) {
                Object item = iter.next();
                List<Field> lstFields = getPreferenceFieldList(item.getClass());
                if (lstFields.size() > 0) {

                    Element child = lstEle.addElement(getName(item.getClass()));
                    child.addAttribute(GlobalConstant.CLASS, item.getClass().getName());
                    for (int j = 0; j < lstFields.size(); j++) {
                        store(item, lstFields.get(j), child);
                    }
                } else {
                    store(item.getClass(), item.getClass().getSimpleName(), item, lstEle, adapterClass);
                }
            }

        } else if (fieldValue instanceof Map) {

            Element mapEle = parent.addElement(fieldName);
            mapEle.addAttribute(GlobalConstant.CLASS, fieldValue.getClass().getName());

            Map map = (Map) fieldValue;
            Iterator iter = map.keySet().iterator();
            while (iter.hasNext()) {
                Object key = iter.next();
                Object value = map.get(key);
                Element keyEle = mapEle.addElement(GlobalConstant.KEY);
                keyEle.setText(key.toString());// Not suppert any adapter!
                keyEle.addAttribute(GlobalConstant.CLASS, key.getClass().getName());

                List<Field> vFields = getPreferenceFieldList(value.getClass());
                if (vFields.size() > 0) {

                    Element valueEle = keyEle.addElement(getName(value.getClass()));
                    valueEle.addAttribute(GlobalConstant.CLASS, value.getClass().getName());
                    for (int j = 0; j < vFields.size(); j++) {
                        store(value, vFields.get(j), valueEle);
                    }
                } else {
                    store(value.getClass(), value.getClass().getSimpleName(), value, keyEle, adapterClass);
                }
            }

        } else {

            List<Field> pFields = getPreferenceFieldList(fieldValue.getClass());
            if (pFields.size() > 0) {
                Element child = parent.addElement(fieldName);
                child.addAttribute(GlobalConstant.CLASS, fieldValue.getClass().getName());

                for (int i = 0; i < pFields.size(); i++) {
                    store(fieldValue, pFields.get(i), child);
                }
            } else {
                Element attrEle = parent.addElement(fieldName);
                attrEle.setText(getValue(fieldValue, adapterClass));
                attrEle.addAttribute(GlobalConstant.CLASS, fieldValue.getClass().getName());
                if (adapterClass != DefaultPersistentAdapter.class) {
                    attrEle.addAttribute(GlobalConstant.ADAPTER, adapterClass.getName());
                }
            }
        }
    }

    /**
     * Gets the listing of preference field.
     * 
     * @param c
     * @return 
     */
    private List<Field> getPreferenceFieldList(Class c) {
        List<Field> lstFields = new ArrayList<Field>();
        Field[] fields = c.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            PreferenceField pf = fields[i]
                    .getAnnotation(com.dockingsoftware.dockingpreference.PreferenceField.class);
            if (pf != null) {
                lstFields.add(fields[i]);
            }
        }
        return lstFields;
    }

    /**
     * Gets the simple name of the class.
     * 
     * @param c
     * @return 
     */
    private String getName(Class c) {
        return c.getSimpleName();
    }

    /**
     * Gets the value that's processed by adapter.
     * 
     * @param obj
     * @param adapterClass
     * @return 
     */
    private String getValue(Object obj, Class<? extends PersistentAdapterIF> adapterClass) {
        try {
            return ((PersistentAdapterIF) adapterClass.newInstance()).store(obj);
        } catch (InstantiationException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE,
                    "No-args constructor is missing.", ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(PreferenceProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

}