de.uniks.networkparser.json.UpdateJson Maven / Gradle / Ivy
package de.uniks.networkparser.json;
/*
NetworkParser
The MIT License
Copyright (c) 2010-2016 Stefan Lindel https://github.com/fujaba/NetworkParser/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import de.uniks.networkparser.Filter;
import de.uniks.networkparser.IdMap;
import de.uniks.networkparser.SimpleEvent;
import de.uniks.networkparser.UpdateCondition;
import de.uniks.networkparser.interfaces.Entity;
import de.uniks.networkparser.interfaces.Grammar;
import de.uniks.networkparser.interfaces.MapListener;
import de.uniks.networkparser.interfaces.SendableEntityCreator;
import de.uniks.networkparser.list.SimpleIteratorSet;
/**
* The listener interface for receiving update events. The class that is
* interested in processing a update event implements this interface, and the
* object created with that class is registered with a component using the
* component's addUpdateListener
method. When the update event
* occurs, that object's appropriate method is invoked.
*
*/
public class UpdateJson implements MapListener {
/** The map. */
private IdMap map;
/** The suspend id list. */
private ArrayList suspendIdList;
private Filter updateFilter = new Filter().withStrategy(SendableEntityCreator.UPDATE).withConvertable(new UpdateCondition());
/**
* Instantiates a new update listener.
*
* @param map
* the map
*/
public UpdateJson(IdMap map) {
this.map = map;
}
/**
* Suspend notification.
*
* @return success for suspend Notification
*/
public boolean suspendNotification() {
this.suspendIdList = new ArrayList();
return true;
}
/**
* Reset notification.
*
* @return success for reset Notification
*/
public boolean resumeNotification() {
JsonArray array = this.map.getJsonByIds(this.suspendIdList);
if(array.size() > 0) {
JsonObject message = new JsonObject();
message.put(SendableEntityCreator.UPDATE, array);
this.map.notify(new SimpleEvent(SendableEntityCreator.NEW, message, map, null, null, null));
}
this.suspendIdList = null;
return true;
}
public boolean resetNotification() {
this.suspendIdList = null;
return true;
}
/*
* (non-Javadoc)
*
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.
* PropertyChangeEvent)
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if ((oldValue == null && newValue == null)
|| (oldValue != null && oldValue.equals(newValue))) {
// Nothing to do
return;
}
// put changes into msg and send to receiver
Object source = evt.getSource();
String propertyName = evt.getPropertyName();
SendableEntityCreator creatorClass = this.map.getCreatorClass(source);
if (creatorClass == null) {
// this class is not supported, do nor replicate
return;
}
boolean done = false;
for (String attrName : creatorClass.getProperties()) {
if (attrName.equals(propertyName)) {
done = true;
break;
}
}
if (!done) {
// this property is not part of the replicated model, do not
// replicate
// if propertyname is not found and the name is REMOVE_YOU it remove it from the IdMap
if(SendableEntityCreator.REMOVE_YOU.equals(propertyName)) {
this.removeObj(evt.getOldValue(), true);
}
return;
}
JsonObject jsonObject = new JsonObject();
String id = this.map.getId(source, true);
Grammar grammar = this.map.getGrammar();
grammar.writeBasicValue(jsonObject, source.getClass().getName(), id, map);
if (oldValue != null) {
creatorClass = this.map.getCreatorClass(oldValue);
JsonObject child = new JsonObject();
if (creatorClass != null) {
String oldId = this.map.getId(oldValue, true);
if (oldId != null) {
child.put(propertyName,
new JsonObject().withValue(IdMap.ID, oldId));
}
} else {
child.put(propertyName, oldValue);
}
jsonObject.put(SendableEntityCreator.REMOVE, child);
}
if (newValue != null) {
creatorClass = this.map.getCreatorClass(newValue);
JsonObject child = new JsonObject();
if (creatorClass != null) {
String key = this.map.getKey(newValue);
if (key != null) {
JsonObject item = new JsonObject()
.withValue(IdMap.CLASS, newValue.getClass().getName())
.withValue(IdMap.ID, key);
child.put(propertyName, item);
} else {
JsonObject item = this.map.toJsonObject(newValue,
this.updateFilter);
child.put(propertyName, item);
if (this.suspendIdList != null) {
this.suspendIdList.add(this.map.getId(newValue, true));
}
}
} else {
// plain attribute
child.put(propertyName, newValue);
}
jsonObject.put(SendableEntityCreator.UPDATE, child);
}
if (this.suspendIdList == null) {
// Add Message Value
this.map.notify(new SimpleEvent(SendableEntityCreator.NEW, jsonObject, evt, map));
}
}
/**
* Execute.
*
* @param updateMessage the update message
* @param filter Filter for exclude UpdateMessages
* @return the MasterObject, if successful
*/
public Object execute(Entity updateMessage, Filter filter) {
if(!updateMessage.has(SendableEntityCreator.UPDATE) && !updateMessage.has(SendableEntityCreator.REMOVE)) {
return null;
}
if(this.map == null) {
return null;
}
String id = updateMessage.getString(IdMap.ID);
JsonObject remove = (JsonObject) updateMessage.getValue(SendableEntityCreator.REMOVE);
JsonObject update = (JsonObject) updateMessage.getValue(SendableEntityCreator.UPDATE);
// Object prio = updateMessage.getValue(Filter.PRIO);
Object masterObj = this.map.getObject(id);
if (masterObj == null)
{
String masterObjClassName = (String) updateMessage.getValue(IdMap.CLASS);
if (masterObjClassName != null)
{
// cool, lets make it
SendableEntityCreator creator = this.map.getCreator(masterObjClassName, true, null);
masterObj = creator.getSendableInstance(false);
if (masterObj != null)
{
this.map.put(id, masterObj, false);
}
}
}
if (masterObj == null) {
return null;
}
SendableEntityCreator creator = this.map.getCreatorClass(masterObj);
if (remove == null && update != null) {
// create Message
Object refObject = creator.getSendableInstance(true);
for(SimpleIteratorSet i = new SimpleIteratorSet(update);i.hasNext();) {
Entry item = i.next();
String key = item.getKey();
Object value = creator.getValue(masterObj, key);
if (value == null) {
// Old Value is Standard
return setValue(creator, masterObj, key, item.getValue(), SendableEntityCreator.NEW);
} else if (value.equals(creator.getValue(refObject, key))) {
// Old Value is Standard
return setValue(creator, masterObj, key,
update.get(key), SendableEntityCreator.NEW);
}
}
return true;
} else if (update == null && remove != null) {
// delete Message
Object refObject = creator.getSendableInstance(true);
Iterator keys = remove.keyIterator();
while (keys.hasNext()) {
String key = keys.next();
Object value = creator.getValue(masterObj, key);
if (value instanceof Collection>) {
JsonObject removeJsonObject = remove.getJsonObject(key);
setValue(creator, masterObj, key, removeJsonObject,
SendableEntityCreator.REMOVE);
} else {
if (checkValue(value, key, remove)) {
setValue(creator, masterObj, key,
creator.getValue(refObject, key),
SendableEntityCreator.REMOVE);
}
}
Object removeJsonObject = remove.get(key);
if (removeJsonObject != null
&& removeJsonObject instanceof JsonObject) {
JsonObject json = (JsonObject) removeJsonObject;
this.map.notify(new SimpleEvent(SendableEntityCreator.REMOVE, json, map, key, this.map.decode(json), null).withModelValue(masterObj));
}
}
return masterObj;
} else if (update != null) {
// update Message
Iterator keys = update.keyIterator();
while (keys.hasNext()) {
String key = keys.next();
// CHECK WITH REMOVE key
Object oldValue = creator.getValue(masterObj, key);
if (checkValue(oldValue, key, remove)) {
Object newValue = update.get(key);
setValue(creator, masterObj, key, newValue, SendableEntityCreator.UPDATE);
this.map.notify(new SimpleEvent(SendableEntityCreator.UPDATE, update, map, key, oldValue, newValue).withModelValue(masterObj));
}
}
return masterObj;
}
return null;
}
/**
* Check value.
*
* @param value the value
* @param key the key
* @param oldJsonObject the json obj
* @return true, if successful
*/
private boolean checkValue(Object value, String key,
JsonObject oldJsonObject) {
Object oldValue = oldJsonObject.get(key);
if (value != null) {
if (oldValue instanceof JsonObject) {
// GLAUB ICH MAL
String oldId = (String) ((JsonObject) oldValue)
.get(IdMap.ID);
return oldId.equals(this.map.getId(value, true));
}
return value.equals(oldValue);
}
return oldValue == null;
}
/**
* Sets the value.
*
* @param creator the creator
* @param element the element
* @param key the key
* @param newValue the new value
* @param typ type of set NEW, UPDATE, REMOVE
* @return true, if successful
*/
private Object setValue(SendableEntityCreator creator, Object element,
String key, Object newValue, String typ) {
if (newValue instanceof JsonObject) {
JsonObject json = (JsonObject) newValue;
Object value = this.map.decode(json);
if (value != null) {
creator.setValue(element, key, value, typ);
if(this.map.notify(new SimpleEvent(typ, json, map, key, null, value).withModelValue(element))){
return element;
}
}
} else {
creator.setValue(element, key, newValue, typ);
if(this.map.notify(new SimpleEvent(typ, null, map, key, null, newValue).withModelValue(element))){
return element;
}
}
return null;
}
public UpdateJson withFilter(Filter filter) {
this.updateFilter = filter;
return this;
}
@Override
public Filter getFilter() {
return this.updateFilter;
}
/**
* Remove the given object from the IdMap
* @param oldValue Object to remove
* @param destroy switch for remove link from object
* @return success
*/
public boolean removeObj(Object oldValue, boolean destroy) {
if(this.map != null) {
return this.map.removeObj(oldValue, destroy);
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy