Package de.timefinder.core.io.xml

Source Code of de.timefinder.core.io.xml.XmlImport

/*
*  Copyright 2010 Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net.
*
*  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.
*  under the License.
*/
package de.timefinder.core.io.xml;

import de.timefinder.algo.constraint.DifferentDayConstraint;
import de.timefinder.algo.constraint.EventOrderConstraint;
import de.timefinder.algo.constraint.MinGapsConstraint;
import de.timefinder.algo.constraint.PersonITCRasterConstraint;
import de.timefinder.algo.constraint.RasterConstraint;
import de.timefinder.core.io.text.ObjectParsing;
import de.timefinder.core.io.text.Parsing;
import de.timefinder.core.util.ReaderInputStream;
import de.timefinder.data.DBInterface;
import de.timefinder.data.DataPool;
import de.timefinder.data.Event;
import de.timefinder.data.Feature;
import de.timefinder.data.Location;
import de.timefinder.data.Person;
import de.timefinder.data.Role;
import de.timefinder.data.access.Dao;
import de.timefinder.data.algo.Constraint;
import de.timefinder.data.algo.DataPoolSettings;
import de.timefinder.data.set.BitRasterImpl;
import de.timefinder.data.set.WeekRasterImpl;
import de.timefinder.data.util.Helper;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javolution.util.FastMap;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
*
* @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
*/
public class XmlImport extends AbstractXmlHelper {

    private InputStream reader;
    private ObjectParsing objectParsing = new ObjectParsing();
    private Map<Class, Map<Long, DBInterface>> simpleDaos = FastMap.newInstance();

    XmlImport(DataPool pool, DataPoolSettings settings, Reader reader) {
        this(pool, settings, new ReaderInputStream(reader));
    }

    public XmlImport(DataPool pool, DataPoolSettings settings, InputStream reader) {
        super(pool, settings);
        if (reader == null)
            throw new NullPointerException("InputStream cannot be null!");
        this.reader = reader;

        for (Dao<? extends DBInterface> dao : pool.getDaos()) {
            // should we use existing values?? (Map<Long, DBInterface>) dao.getMap()
            simpleDaos.put(dao.getType(), new FastMap());
        }
    }

    public void doWork() {
        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(reader);

            List list = document.getRootElement().elements();
            Iterator iter = list.iterator();
            while (iter.hasNext()) {
                Element element = (Element) iter.next();
                if ("settings".equals(element.getName())) {
                    readElements(element, settings);
                } else if ("objects".equals(element.getName())) {
                    Class clazz = Class.forName(element.attributeValue("class"));
                    readGeneric(clazz, element);
                }
            }
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        fillPoolFromSimpleDaos();
    }

    private void fillPoolFromSimpleDaos() {
        for (Entry<Class, Map<Long, DBInterface>> entry : simpleDaos.entrySet()) {
            Dao<DBInterface> dao = pool.getDao(entry.getKey());
            if (dao == null)
                throw new IllegalStateException("no dao in pool found for class:" + entry.getKey());

            dao.attachAll(entry.getValue().values());
        }
    }

    private void readGeneric(Class<DBInterface> clazz, Element rootElement) {
        for (Object objEl : rootElement.elements()) {
            Element objElement = (Element) objEl;
            if (!"object".equals(objElement.getName()))
                throw new UnsupportedOperationException("sub element should be object");

            long id = getId(objElement);
            Object obj = getObject(id, clazz);
            readElements(objElement, obj);
        }
    }

    private Element readElements(Element rootElement, Object object) {
        Map<String, Method> methods = Helper.findSetterMethods(object.getClass());
        for (Object objectEl : rootElement.elements()) {
            Element element = (Element) objectEl;
            Method m = methods.get(element.getName());
            if (m == null)
                throw new NullPointerException("Cannot find setter for element:" + element.getName());
            try {
                Class setterType = m.getParameterTypes()[0];
                Object result = getResult(object, setterType, element);
                m.invoke(object, result);
            } catch (Exception ex) {
                throw new RuntimeException("Exception while parsing ("
                        + element.getName() + ") to "
                        + object.getClass().getName() + " " + object, ex);
            }
        }

        return rootElement;
    }

    private Long getId(Element objElement) {
        try {
            return Long.parseLong(objElement.attributeValue("id"));
        } catch (Exception ex) {
            throw new UnsupportedOperationException("id of element mustn't be null!"
                    + objElement.getUniquePath(), ex);
        }
    }

    private Long getRef(Element objElement) {
        try {
            return Long.parseLong(objElement.attributeValue("ref"));
        } catch (Exception ex) {
            throw new UnsupportedOperationException("ref of element mustn't be null!"
                    + objElement.getUniquePath(), ex);
        }
    }

    private <T extends DBInterface> T getObject(Long id, Class<T> clazz) {
        Map<Long, DBInterface> simpleDao = simpleDaos.get(clazz);
        DBInterface obj = simpleDao.get(id);
        if (obj == null) {
            try {
                obj = clazz.newInstance();
                // obj.set(id) will be done in attach of the 'real dao'
                simpleDao.put(id, obj);
            } catch (Exception ex) {
                throw new IllegalStateException("Cannot create object of class:" + clazz, ex);
            }
        }
        return (T) obj;
    }

    public <T> T getResult(Object obj, Class<T> propertyClass, Element element) {
        Parsing parsing = objectParsing.getParsing(propertyClass);
        if (parsing == null) {
            if (Person.class.isAssignableFrom(obj.getClass())) {
                if ("constraints".equals(element.getName())) {
                    return (T) readConstraints(element);
                } else if ("eventsMap".equals(element.getName())) {
                    Map map = FastMap.newInstance();
                    for (Object evEl : element.elements()) {
                        Element evElement = (Element) evEl;
                        long ref = getRef(evElement);
                        Role role = Role.valueOf(evElement.attributeValue("role"));
                        map.put(getObject(ref, Event.class), role);
                    }
                    return (T) map;
                }
            } else if (Event.class.isAssignableFrom(obj.getClass())) {
                if ("constraints".equals(element.getName())) {
                    return (T) readConstraints(element);
                } else if ("features".equals(element.getName())) {
                    return (T) readCollection(element, Feature.class);
                }
                // location already parsed via location->events
                // persons  already parsed via persons->events
            } else if (Feature.class.isAssignableFrom(obj.getClass())) {
                if ("constraints".equals(element.getName())) {
                    return (T) readConstraints(element);
                }
            } else if (Location.class.isAssignableFrom(obj.getClass())) {
                if ("constraints".equals(element.getName())) {
                    return (T) readConstraints(element);
                } else if ("events".equals(element.getName())) {
                    return (T) readCollection(element, Event.class);
                } else if ("features".equals(element.getName())) {
                    return (T) readCollection(element, Feature.class);
                }
            }

            throw new UnsupportedOperationException("No parsing found for property class "
                    + propertyClass + " and object " + obj);
        } else
            return (T) parsing.parse(element.getText());
    }

    public Collection readCollection(Element eventsElement, Class clazz) {
        List res = new ArrayList();
        for (Object obj : eventsElement.elements()) {
            Element element = (Element) obj;
            long ref = getRef(element);
            res.add(getObject(ref, clazz));
        }
        return res;
    }

    public Collection readConstraints(Element constrElement) {
        List<Constraint> res = new ArrayList();
        for (Object obj : constrElement.elements()) {
            Element element = (Element) obj;
            Constraint constraint = null;

            if (RasterConstraint.class.getSimpleName().equals(element.getName())) {
                BitSet bs = getResult(obj, BitSet.class, element);
                int length = Integer.parseInt(element.attributeValue("length"));
                constraint = new RasterConstraint(new WeekRasterImpl(
                        new BitRasterImpl(bs, length)));

            } else if (EventOrderConstraint.class.getSimpleName().equals(element.getName())) {
                UnsupportedOperationException excFirstEl = new UnsupportedOperationException(
                        "First element in eventOrderConstraint must be the event!" + element.getPath());
                for (Object eocObj : element.elements()) {
                    Element eocEl = (Element) eocObj;
                    if ("event".equals(eocEl.getName())) {
                        Event ev = getObject(getRef(eocEl), Event.class);
                        constraint = new EventOrderConstraint(ev);
                    } else if ("beforeEvent".equals(eocEl.getName())) {
                        if (constraint == null)
                            throw excFirstEl;
                        Event ev = getObject(getRef(eocEl), Event.class);
                        ((EventOrderConstraint) constraint).addBefore(ev);
                    } else if ("followsEvent".equals(eocEl.getName())) {
                        if (constraint == null)
                            throw excFirstEl;
                        Event ev = getObject(getRef(eocEl), Event.class);
                        ((EventOrderConstraint) constraint).addFollow(ev);
                    } else
                        throw new UnsupportedOperationException("Element not supported in eventOrderConstraint:"
                                + eocEl.getPath());
                }
            } else if (PersonITCRasterConstraint.class.getSimpleName().equals(element.getName())) {
                Person p = getObject(getRef(element.element("person")), Person.class);
                constraint = new PersonITCRasterConstraint(p, settings);

            } else if (MinGapsConstraint.class.getSimpleName().equals(element.getName())) {
                constraint = new MinGapsConstraint(settings,
                        readCollection(element, Event.class));
                ((MinGapsConstraint) constraint).setCountEarly(
                        Boolean.parseBoolean(element.attributeValue("countEarly")));

            } else if (DifferentDayConstraint.class.getSimpleName().equals(element.getName())) {
                constraint = new DifferentDayConstraint(settings,
                        readCollection(element, Event.class));

            } else
                throw new UnsupportedOperationException("Constraint not supported:" + element.getName());

            if (constraint == null)
                throw new IllegalStateException("Couldn't find a constraint in path:" + element.getPath());
            float weight = Float.parseFloat(element.attributeValue("weight"));
            constraint.setWeight(weight);
            res.add(constraint);
        }
        return res;
    }
}
TOP

Related Classes of de.timefinder.core.io.xml.XmlImport

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.