/**
* (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jabylon.resources.diff;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.jabylon.properties.PropertiesPackage;
import org.jabylon.properties.Property;
import org.jabylon.properties.PropertyFile;
public class PropertyDifferentiator {
private PropertyFile original;
public PropertyDifferentiator(PropertyFile original) {
super();
this.original = original;
}
public List<Notification> diff(PropertyFile modified) {
Map<String, Property> orignalProperties = buildMap(original);
List<Notification> noticiations = new ArrayList<Notification>();
computeStructuralDiff(orignalProperties, modified, noticiations);
return noticiations;
}
private void computeStructuralDiff(Map<String, Property> orignalProperties, PropertyFile modified, List<Notification> noticiations) {
List<Property> additions = new ArrayList<Property>();
List<Property> removals = new ArrayList<Property>();
for (Property prop : modified.getProperties()) {
Property originalProperty = orignalProperties.get(prop.getKey());
if (originalProperty == null)
additions.add(prop);
else {
orignalProperties.remove(prop.getKey());
Notification change = computeDiff(originalProperty, prop);
if(change!=null)
noticiations.add(change);
}
}
removals.addAll(orignalProperties.values());
if(!additions.isEmpty())
{
Notification notification = new ENotificationImpl((InternalEObject) modified,Notification.ADD_MANY, PropertiesPackage.Literals.PROPERTY_FILE__PROPERTIES,null, additions);
noticiations.add(notification);
}
if(!removals.isEmpty())
{
Notification notification = new ENotificationImpl((InternalEObject) modified,Notification.ADD_MANY, PropertiesPackage.Literals.PROPERTY_FILE__PROPERTIES,removals, null);
noticiations.add(notification);
}
}
private Notification computeDiff(Property orignalPropertery, Property modifiedProperty) {
if (orignalPropertery.getValue() == null && modifiedProperty.getValue() == null)
return null; // if both are null, it's all good
if (orignalPropertery.getValue() == null && modifiedProperty.getValue() != null) {
return new CustomNotification(Notification.SET, null, modifiedProperty.getValue(), modifiedProperty);
}
if (modifiedProperty.getValue() == null && orignalPropertery.getValue() != null) {
return new CustomNotification(Notification.UNSET, orignalPropertery.getValue(), null, modifiedProperty);
}
if(modifiedProperty.getValue().equals(orignalPropertery.getValue()))
return null;
return new CustomNotification(Notification.SET, orignalPropertery.getValue(), modifiedProperty.getValue(), modifiedProperty);
}
private Map<String, Property> buildMap(PropertyFile file) {
Map<String, Property> properties = new HashMap<String, Property>(file.getProperties().size());
for (Property property : file.getProperties()) {
properties.put(property.getKey(), property);
}
return properties;
}
}
class CustomNotification extends NotificationImpl {
private Property notifier;
public CustomNotification(int eventType, String oldValue, String newValue, Property notifier) {
super(eventType, oldValue, newValue);
this.notifier = notifier;
}
@Override
public Object getFeature() {
return PropertiesPackage.Literals.PROPERTY__VALUE;
}
@Override
public Property getNotifier() {
return notifier;
}
}