fujaba/NetworkParser

View on GitHub
src/main/java/de/uniks/networkparser/UpdateCondition.java

Summary

Maintainability
F
1 wk
Test Coverage
package de.uniks.networkparser;

import java.beans.PropertyChangeEvent;

import de.uniks.networkparser.interfaces.Entity;
import de.uniks.networkparser.interfaces.ObjectCondition;
import de.uniks.networkparser.interfaces.SendableEntityCreator;
import de.uniks.networkparser.list.SimpleSet;

/**
 * Condition for Listener for changes in Element (Datamodel) in IdMap Or
 * AtomarCondition with PropertyChange
 * 
 * @author Stefan Lindel
 */
public class UpdateCondition implements ObjectCondition {
    private Object owner;
    private ObjectCondition condition; /* FOR ATOM OR TRANSACTION */

    /** FOR ACCUMULATE */
    private Tokener tokener;
    private Entity change;
    private IdMap map;
    /** Target */
    private Object defaultItem;

    /** Target or StartClass */
    private SendableEntityCreator creator;
    /** May be class<?> or Object */
    private String property;
    private ObjectCondition startCondition;

    private ObjectCondition endCondition;
    /** May be class<?> or Object */
    private String endProperty;
    private Object endClass;
    private SimpleSet<SimpleEvent> changes;
    private SendableEntityCreator endCreator;

    UpdateCondition() {

    }

    public UpdateCondition withContidion(ObjectCondition condition) {
        this.condition = condition;
        return this;
    }

    public static UpdateCondition createAtomarCondition(ObjectCondition listener) {
        UpdateCondition condition = new UpdateCondition();
        condition.condition = listener;
        return condition;
    }

    public static UpdateCondition createUpdateCondition() {
        return new UpdateCondition();
    }

    public static UpdateCondition createAcumulateCondition(Tokener tokener) {
        UpdateCondition condition = new UpdateCondition();
        condition.tokener = tokener;
        return condition;
    }

    public static UpdateCondition createAcumulateCondition(IdMap map) {
        UpdateCondition condition = new UpdateCondition();
        if (map != null) {
            condition.tokener = map.getMapListener().getTokener();
        }
        condition.map = map;
        return condition;
    }

    public static UpdateCondition createAcumulateCondition(Tokener tokener, Object target,
            SendableEntityCreator creator, String property) {
        UpdateCondition condition = new UpdateCondition();
        condition.tokener = tokener;
        condition.owner = target;
        condition.creator = creator;
        condition.property = property;
        return condition;
    }

    public static UpdateCondition createTransaction(IdMap map) {
        UpdateCondition condition = new UpdateCondition();
        condition.map = map;
        return condition;
    }

    public boolean isAtomar() {
        return isTransaction() == false && condition != null;
    }

    public boolean isTransaction() {
        return (endProperty != null || endClass != null);
    }

    public boolean isAccumulate() {
        return tokener != null;
    }

    public boolean isChangeListener() {
        return condition == null;
    }

    public UpdateCondition withStart(String property, Object startClass) {
        this.owner = startClass;
        this.property = property;
        if (startClass instanceof Class<?> == false && map != null) {
            this.creator = map.getCreatorClass(startClass);
        }
        return this;
    }

    public UpdateCondition withStart(Object startClass) {
        this.owner = startClass;
        if (map != null) {
            if (startClass instanceof Class<?>) {
                Class<?> subClass = (Class<?>) startClass;
                this.creator = map.getCreator(subClass.getName(), true);
            } else {
                this.creator = map.getCreatorClass(startClass);
            }
        }
        return this;
    }

    public UpdateCondition withEnd(String property) {
        this.endProperty = property;
        return this;
    }

    public UpdateCondition withStartConition(ObjectCondition condition) {
        this.startCondition = condition;
        return this;
    }

    public UpdateCondition withEnd(String property, Object endClass) {
        this.endClass = endClass;
        this.endProperty = property;
        if (map != null) {
            if (endClass instanceof Class<?>) {
                Class<?> subClass = (Class<?>) endClass;
                this.creator = map.getCreator(subClass.getName(), true);
            } else {
                this.creator = map.getCreatorClass(endClass);
            }
        }
        return this;
    }

    public UpdateCondition withEndConition(ObjectCondition condition) {
        this.endCondition = condition;
        return this;
    }

    @Override
    public boolean update(Object evt) {
        if (isAtomar()) {
            if (evt instanceof PropertyChangeEvent) {
                return condition.update(evt);
            }
            return false;
        }
        /* MUST BE A SIMPLEEVENT */
        if (evt == null || evt instanceof SimpleEvent == false) {
            return false;
        }

        SimpleEvent event = (SimpleEvent) evt;
        if (isChangeListener()) {
            if (creator != null && property != null) {
                if (event.getNewValue() != null) {
                    /* CREATE ONE */
                    creator.setValue(event.getNewValue(), property, owner, SendableEntityCreator.NEW);
                } else {
                    creator.setValue(event.getOldValue(), property, owner, SendableEntityCreator.REMOVE);
                }
                return false;
            }
            Object source = event.getSource();
            if (source instanceof IdMap) {
                IdMap map = (IdMap) source;
                return map.getKey(event.getModelValue()) == null && map.getKey(event.getNewValue()) == null;
            }
            return false;
        }
        if (isTransaction()) {
            if (startCondition != null && startCondition.update(evt) == false) {
                return false;
            }
            Object source = event.getSource();
            if (source == null) {
                return false;
            }
            if (changes == null && property != null && property.equalsIgnoreCase(event.getPropertyName())) {
                /* Search for Start Transaction */
                if (owner instanceof Class<?>) {
                    if (source.getClass() == owner) {
                        this.changes = new SimpleSet<SimpleEvent>();
                        return true;
                    }
                }
            } else if (owner != null && creator != null) {
                SendableEntityCreator creator = map.getCreatorClass(source);
                if (creator != null && creator == this.creator) {
                    this.changes = new SimpleSet<SimpleEvent>();
                    return true;
                }
                creator = map.getCreatorClass(event.getNewValue());
                if (creator != null && creator == this.creator) {
                    this.changes = new SimpleSet<SimpleEvent>();
                    return true;
                }
            }

            if (this.changes != null) {
                this.changes.add(event);
                /* Check for End */
                if (endCondition != null && endCondition.update(evt) == false) {
                    return true;
                }
                if (endProperty != null && endProperty.equalsIgnoreCase(event.getPropertyName())) {
                    /* Search for Start Transaction */
                    if (endClass instanceof Class<?>) {
                        if (source.getClass() == endClass) {
                            if (this.condition != null) {
                                return this.condition.update(this.changes);
                            }
                            this.changes = null;
                            return true;
                        }
                    } else if (endClass != null && endCreator != null) {
                        SendableEntityCreator creator = map.getCreatorClass(source);
                        if (creator != null && creator == endCreator) {
                            if (this.condition != null) {
                                return this.condition.update(this.changes);
                            }
                            this.changes = null;
                            return true;
                        }
                    } else if (creator != null && owner != null) {
                        SendableEntityCreator creator = map.getCreatorClass(event.getModelValue());
                        if (creator != null && this.creator == creator) {
                            if (this.condition != null) {

                                SimpleEvent eventTransaction = new SimpleEvent(this, "transaction", null,
                                        mergeChanges());
                                return this.condition.update(eventTransaction);
                            }
                            this.changes = null;
                            return true;
                        }

                    }
                }
            }
            return true;
        }
        return false;
    }

    public Object mergeChanges() {
        if (this.changes == null) {
            return null;
        }
        Entity mergeChange = null;
        Entity mergeUpdate = null;

        for (Object change : this.changes) {
            if (change instanceof SimpleEvent == false) {
                continue;
            }
            SimpleEvent evt = (SimpleEvent) change;
            Entity entity = evt.getEntity();
            if (mergeChange == null) {
                mergeChange = (Entity) entity.getNewList(true);
                /* Copy first One */
                for (int i = 0; i < entity.size(); i++) {
                    String key = entity.getKeyByIndex(i);
                    Object value = entity.getValueByIndex(i);
                    mergeChange.put(key, value);
                    if (SendableEntityCreator.UPDATE.equals(key)) {
                        mergeUpdate = (Entity) value;
                    }
                }
            } else {
                for (int i = 0; i < entity.size(); i++) {
                    String key = entity.getKeyByIndex(i);
                    if (SendableEntityCreator.UPDATE.equals(key)) {
                        Object value = entity.getValueByIndex(i);
                        if (value instanceof Entity) {
                            Entity valueEntity = (Entity) value;
                            for (int c = 0; c < valueEntity.size(); c++) {
                                String valueKey = valueEntity.getKeyByIndex(c);
                                Object valueValue = valueEntity.getValueByIndex(c);
                                if (mergeUpdate != null) {
                                    mergeUpdate.put(valueKey, valueValue);
                                }
                            }
                        }
                    }
                }
            }
        }
        return mergeChange;
    }

    public boolean changeItem(Object source, Object target, String property) {
        if (map == null) {
            return false;
        }
        SendableEntityCreator creator = map.getCreatorClass(source);
        Object defaultItem = creator.getSendableInstance(true);
        Object oldValue = creator.getValue(source, property);
        Object newValue = creator.getValue(source, property);

        if ((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue))) {
            return false;
        }

        if (oldValue != creator.getValue(defaultItem, property)) {
            if (change == null) {
                change = tokener.newInstance();
                change.put(IdMap.ID, map.getId(source, true));
            }
            Entity child;

            /* OldValue */
            if (change.has(SendableEntityCreator.REMOVE)) {
                child = tokener.newInstance();
            } else {
                child = (Entity) change.getValue(SendableEntityCreator.REMOVE);
                change.put(SendableEntityCreator.REMOVE, child);
            }
            SendableEntityCreator creatorClass = map.getCreatorClass(oldValue);
            if (creatorClass != null) {
                String oldId = map.getId(oldValue, true);
                if (oldId != null) {
                    Entity item = tokener.newInstance();
                    item.put(IdMap.ID, oldId);
                    child.put(property, item);
                }
            } else {
                child.put(property, oldValue);
            }

            /* NewValue */
            if (change.has(SendableEntityCreator.UPDATE)) {
                child = tokener.newInstance();
            } else {
                child = (Entity) change.getValue(SendableEntityCreator.UPDATE);
                change.put(SendableEntityCreator.UPDATE, child);
            }

            creatorClass = map.getCreatorClass(newValue);
            if (creatorClass != null) {
                String newId = map.getId(newValue, true);
                if (newId != null) {
                    Entity item = tokener.newInstance();
                    item.put(IdMap.ID, newId);
                    child.put(property, item);
                }
            } else {
                child.put(property, newValue);
            }
        }
        return true;
    }

    public UpdateCondition withAttribute(Object newValue, String property) {
        changeAttribute(newValue, property);
        return this;
    }

    public UpdateCondition withTarget(Object value) {
        this.owner = value;
        if (value != null && map != null) {
            this.creator = map.getCreatorClass(owner);
            if (this.creator != null) {
                this.defaultItem = creator.getSendableInstance(true);
            }
        }
        return this;
    }

    public UpdateCondition withAcumulateTarget(Object value, SendableEntityCreator creator, String property) {
        this.owner = value;
        this.creator = creator;
        this.property = property;
        return this;
    }

    private void addChange(UpdateListener listener, Object source, SendableEntityCreator creator, String property,
            Object oldValue, Object newValue) {
        if (listener == null) {
            return;
        }
        if (this.change == null) {
            this.change = listener.change(property, source, creator, oldValue, newValue);
        } else {
            listener.change(property, creator, change, oldValue, newValue);
        }
    }

    public boolean changeAttribute(UpdateListener listener, Object source, SendableEntityCreator creator,
            String property, Object oldValue, Object newValue) {
        if (this.owner == null) {
            addChange(listener, source, creator, property, oldValue, newValue);
            return true;
        } else if (this.property == null) {
            addChange(listener, source, creator, property, oldValue, newValue);
            return true;
        } else if (this.property.equals(property)) {
            addChange(listener, source, creator, property, oldValue, newValue);
            return true;
        }
        return false;
    }

    public boolean changeAttribute(Object newValue, String property) {
        return changeAttribute(owner, newValue, property, creator, defaultItem);
    }

    private boolean changeAttribute(Object target, Object newValue, String property, SendableEntityCreator creator,
            Object defaultItem) {
        if (creator == null) {
            return false;
        }
        Object oldValue = creator.getValue(target, property);

        if ((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue))) {
            return false;
        }

        if (oldValue != creator.getValue(defaultItem, property)) {
            if (change == null) {
                change = tokener.newInstance();
                change.put(IdMap.ID, map.getId(target, true));
            }
            Entity child;

            /* OldValue */
            if (change.has(SendableEntityCreator.REMOVE)) {
                child = (Entity) change.getValue(SendableEntityCreator.REMOVE);
                change.put(SendableEntityCreator.REMOVE, child);
            } else {
                child = tokener.newInstance();
                change.put(SendableEntityCreator.REMOVE, child);
            }
            SendableEntityCreator creatorClass = map.getCreatorClass(oldValue);
            if (creatorClass != null) {
                String oldId = map.getId(oldValue, true);
                if (oldId != null) {
                    Entity childItem = tokener.newInstance();
                    childItem.put(IdMap.ID, oldId);
                    child.put(property, childItem);
                }
            } else {
                child.put(property, oldValue);
            }

            /* NewValue */
            if (change.has(SendableEntityCreator.UPDATE)) {
                child = (Entity) change.getValue(SendableEntityCreator.UPDATE);
                change.put(SendableEntityCreator.UPDATE, child);
            } else {
                child = tokener.newInstance();
                change.put(SendableEntityCreator.UPDATE, child);
            }

            creatorClass = map.getCreatorClass(newValue);
            if (creatorClass != null) {
                String newId = map.getId(newValue, true);
                if (newId != null) {
                    Entity childItem = tokener.newInstance();
                    childItem.put(IdMap.ID, newId);
                    child.put(property, childItem);
                }
            } else {
                child.put(property, newValue);
            }
        }
        return true;
    }

    public Entity getChange() {
        return change;
    }

    public UpdateCondition withChange(Entity change) {
        this.change = change;
        return this;
    }
}