/******************************************************************************* * Copyright (c) 2008-2011 Chair for Applied Software Engineering, * Technische Universitaet Muenchen. * 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 * * Contributors: ******************************************************************************/ package org.eclipse.emf.emfstore.client.model.changeTracking.notification; import java.lang.reflect.Field; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.NotificationImpl; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.emfstore.client.model.util.WorkspaceUtil; import org.eclipse.emf.emfstore.common.model.Project; /** * NotificationInfo is a type safe wrapper for EMF Notifications. It wraps a org.eclipse.emf.common.notify.Notification * and implements a few additional getter methods * * @author chodnick */ public class NotificationInfo implements Notification { private Notification notification; private boolean valid; private String validationMessage; /** * The constructor needs the notification to wrap. * * @param n the notification to wrap */ public NotificationInfo(Notification n) { this.notification = n; NotificationValidator.getInstance().validate(this); } /** * @return the structural feature affected */ public EStructuralFeature getStructuralFeature() { if (getFeature() instanceof EStructuralFeature) { return (EStructuralFeature) getFeature(); } return null; } /** * @return the valid */ public boolean isValid() { return valid; } /** * @param valid the valid to set */ protected void setValid(boolean valid) { this.valid = valid; } /** * @return the validationMessage */ public String getValidationMessage() { return validationMessage; } /** * @param validationMessage the validationMessage to set */ protected void setValidationMessage(String validationMessage) { this.validationMessage = validationMessage; } /** * @return whether this notification signals a change of an attribute value */ public boolean isAttributeNotification() { return notification.getFeature() instanceof EAttribute; } /** * @return whether this notification signals a change of a reference value */ public boolean isReferenceNotification() { return notification.getFeature() instanceof EReference; } /** * @return the EAttribute if the notification relates to an attribute, null otherwise */ public EAttribute getAttribute() { if (isAttributeNotification()) { return (EAttribute) notification.getFeature(); } return null; } /** * @return the EReference if the notification relates to a reference feature, null otherwise */ public EReference getReference() { if (isReferenceNotification()) { return (EReference) notification.getFeature(); } return null; } /** * @return true if the changed feature is marked transient, false otherwise */ public boolean isTransient() { return (isReferenceNotification() && getReference().isTransient()) || (isAttributeNotification() && getAttribute().isTransient()); } /** * @return true if the event is of type Notification.ADD, false otherwise */ public boolean isAddEvent() { return this.getEventType() == Notification.ADD; } /** * @return true if the event is of type Notification.REMOVE, false otherwise */ public boolean isRemoveEvent() { return this.getEventType() == Notification.REMOVE; } /** * @return true if the event is of type Notification.SET, false otherwise */ public boolean isSetEvent() { return this.getEventType() == Notification.SET; } /** * @return true if the event is of type Notification.ADD_MANY, false otherwise */ public boolean isAddManyEvent() { return this.getEventType() == Notification.ADD_MANY; } /** * @return true if the event is of type Notification.REMOVE_MANY, false otherwise */ public boolean isRemoveManyEvent() { return this.getEventType() == Notification.REMOVE_MANY; } /** * @return true if the event is of type Notification.MOVE, false otherwise */ public boolean isMoveEvent() { return this.getEventType() == Notification.MOVE; } /** * @return true if this notification is followed by more notifications in a chain, false if this is the last * notification of a chain */ public boolean hasNext() { if (!(notification instanceof NotificationImpl)) { return false; } try { Field declaredField = NotificationImpl.class.getDeclaredField("next"); declaredField.setAccessible(true); Object object = declaredField.get(notification); Notification nextNotification = (Notification) object; if (nextNotification == null) { return false; } // notifications from project are never propagated, thus considered nonexistent // however, they themselves might have followups if (nextNotification.getNotifier() instanceof Project) { NotificationInfo nextNextInfo = new NotificationInfo(nextNotification); return nextNextInfo.hasNext(); } else { return true; } // BEGIN SUPRESS CATCH EXCEPTION } catch (RuntimeException e) { WorkspaceUtil.logException("Access to next field of notification failed.", e); // END SUPRESS CATCH EXCEPTION } catch (IllegalAccessException e) { WorkspaceUtil.logException("Access to next field of notification failed.", e); } catch (NoSuchFieldException e) { WorkspaceUtil.logException("Access to next field of notification failed.", e); } return false; } /** * @return @see org.eclipse.emf.common.notify.Notification#getEventType() */ public int getEventType() { return notification.getEventType(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getFeature() */ public Object getFeature() { return notification.getFeature(); } /** * @param expectedClass @see org.eclipse.emf.common.notify.Notification#getFeatureID(java.lang.Class) * @return @see org.eclipse.emf.common.notify.Notification#getFeatureID(java.lang.Class) */ public int getFeatureID(Class<?> expectedClass) { return notification.getFeatureID(expectedClass); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewBooleanValue() */ public boolean getNewBooleanValue() { return notification.getNewBooleanValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewByteValue() */ public byte getNewByteValue() { return notification.getNewByteValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewCharValue() */ public char getNewCharValue() { return notification.getNewCharValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewDoubleValue() */ public double getNewDoubleValue() { return notification.getNewDoubleValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewFloatValue() */ public float getNewFloatValue() { return notification.getNewFloatValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewIntValue() */ public int getNewIntValue() { return notification.getNewIntValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewLongValue() */ public long getNewLongValue() { return notification.getNewLongValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewShortValue() */ public short getNewShortValue() { return notification.getNewShortValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewStringValue() */ public String getNewStringValue() { return notification.getNewStringValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewValue() */ public Object getNewValue() { return notification.getNewValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNewValue() */ public EObject getNewModelElementValue() { return (EObject) notification.getNewValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNotifier() */ public Object getNotifier() { return notification.getNotifier(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldBooleanValue() */ public boolean getOldBooleanValue() { return notification.getOldBooleanValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldByteValue() */ public byte getOldByteValue() { return notification.getOldByteValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldCharValue() */ public char getOldCharValue() { return notification.getOldCharValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldDoubleValue() */ public double getOldDoubleValue() { return notification.getOldDoubleValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldFloatValue() */ public float getOldFloatValue() { return notification.getOldFloatValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldIntValue() */ public int getOldIntValue() { return notification.getOldIntValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldLongValue() */ public long getOldLongValue() { return notification.getOldLongValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldShortValue() */ public short getOldShortValue() { return notification.getOldShortValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldStringValue() */ public String getOldStringValue() { return notification.getOldStringValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldValue() */ public Object getOldValue() { return notification.getOldValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getOldValue() */ public EObject getOldModelElementValue() { return (EObject) notification.getOldValue(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getPosition() */ public int getPosition() { return notification.getPosition(); } /** * @return @see org.eclipse.emf.common.notify.Notification#isReset() */ public boolean isReset() { return notification.isReset(); } /** * @return @see org.eclipse.emf.common.notify.Notification#isTouch() */ public boolean isTouch() { return notification.isTouch(); } /** * @param notification @see * org.eclipse.emf.common.notify.Notification#merge(org.eclipse.emf.common.notify.Notification) * @return @see org.eclipse.emf.common.notify.Notification#merge(org.eclipse.emf.common.notify.Notification) */ public boolean merge(Notification notification) { return notification.merge(notification); } /** * @return @see org.eclipse.emf.common.notify.Notification#wasSet() */ public boolean wasSet() { return notification.wasSet(); } /** * @return @see java.lang.Object#toString() */ @Override public String toString() { return notification.toString(); } /** * @return @see org.eclipse.emf.common.notify.Notification#getNotifier() */ public EObject getNotifierModelElement() { return (EObject) notification.getNotifier(); } /** * @return a string useful for debugging only */ public String getDebugString() { StringBuilder sb = new StringBuilder(); // handle type if (isAddEvent()) { sb.append("ADD"); } else if (isSetEvent()) { sb.append("SET"); } else if (isAddManyEvent()) { sb.append("ADD_MANY"); } else if (isRemoveEvent()) { sb.append("REMOVE"); } else if (isRemoveManyEvent()) { sb.append("REMOVE_MANY"); } else if (isMoveEvent()) { sb.append("MOVE"); } else { sb.append(getEventType()); } sb.append(" val: " + getValidationMessage()); EObject n = (EObject) notification.getNotifier(); sb.append(" / on: " + extractName(n)); sb.append("."); if (isAttributeNotification()) { sb.append(getAttribute().getName()); } else if (isReferenceNotification()) { sb.append(getReference().getName()); } sb.append(" / old: "); if (getOldValue() instanceof EObject) { sb.append(extractName((EObject) getOldValue())); } else { sb.append(getOldValue()); } sb.append(" / new: "); if (getNewValue() instanceof EObject) { sb.append(extractName((EObject) getNewValue())); } else { sb.append(getNewValue()); } return sb.toString(); } private String extractName(EObject o) { if (o == null) { return null; } EStructuralFeature f = o.eClass().getEStructuralFeature("name"); if (f != null && o.eGet(f) != null) { return "'" + (String) o.eGet(f) + "'"; } else { return o.eClass().getName(); } } /** * Returns the type of the {@link Notification}. * * @return a {@link Notification} type */ public Class<? extends Notification> getNotificationType() { return notification.getClass(); } }