/*
* Copyright (c) 2008-2013, 2016 Eike Stepper (Berlin, Germany) 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
*
* Contributors:
* Simon McDuff - initial API and implementation
* Eike Stepper - maintenance
*/
package org.eclipse.emf.cdo.internal.common.revision.delta;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDOFeatureDelta.WithIndex;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import java.io.IOException;
import java.text.MessageFormat;
/**
* @author Simon McDuff
*/
public abstract class CDOSingleValueFeatureDeltaImpl extends CDOFeatureDeltaImpl implements WithIndex
{
private int index;
private Object value;
public CDOSingleValueFeatureDeltaImpl(EStructuralFeature feature, int index, Object value)
{
super(feature);
this.index = index;
this.value = value;
}
public CDOSingleValueFeatureDeltaImpl(CDODataInput in, EClass eClass) throws IOException
{
super(in, eClass);
index = in.readInt();
value = readValue(in, eClass);
}
@Override
public void write(CDODataOutput out, EClass eClass) throws IOException
{
super.write(out, eClass);
out.writeInt(index);
writeValue(out, eClass);
}
protected void writeValue(CDODataOutput out, EClass eClass) throws IOException
{
writeValue(out, eClass, value);
}
protected void writeValue(CDODataOutput out, EClass eClass, Object value) throws IOException
{
Object valueToWrite = value;
if (valueToWrite == UNKNOWN_VALUE)
{
throw new IOException("Value is unknown");
}
EStructuralFeature feature = getFeature();
if (FeatureMapUtil.isFeatureMap(feature))
{
FeatureMap.Entry entry = (FeatureMap.Entry)valueToWrite;
feature = entry.getEStructuralFeature();
valueToWrite = entry.getValue();
int featureID = eClass.getFeatureID(feature);
out.writeInt(featureID);
}
if (valueToWrite != null && feature instanceof EReference)
{
valueToWrite = out.getIDProvider().provideCDOID(value);
}
out.writeCDOFeatureValue(feature, valueToWrite);
}
protected Object readValue(CDODataInput in, EClass eClass) throws IOException
{
EStructuralFeature feature = getFeature();
if (FeatureMapUtil.isFeatureMap(feature))
{
int featureID = in.readInt();
feature = eClass.getEStructuralFeature(featureID);
Object innerValue = in.readCDOFeatureValue(feature);
return CDORevisionUtil.createFeatureMapEntry(feature, innerValue);
}
return in.readCDOFeatureValue(feature);
}
public int getIndex()
{
return index;
}
public void setIndex(int index)
{
this.index = index;
}
public Object getValue()
{
return value;
}
public void setValue(Object value)
{
this.value = value;
}
public void clear()
{
setValue(CDOID.NULL);
}
public void adjustAfterAddition(int index)
{
if (index <= this.index)
{
++this.index;
}
}
public void adjustAfterRemoval(int index)
{
if (index < this.index && this.index > 0)
{
--this.index;
}
}
@Override
public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
{
if (value != UNKNOWN_VALUE)
{
Object adjustedValue = referenceAdjuster.adjustReference(value, getFeature(), NO_INDEX);
if (adjustedValue != value)
{
value = adjustedValue;
return true;
}
}
return false;
}
@Override
public boolean isStructurallyEqual(Object obj)
{
if (!super.isStructurallyEqual(obj))
{
return false;
}
CDOSingleValueFeatureDeltaImpl that = (CDOSingleValueFeatureDeltaImpl)obj;
return index == that.getIndex() && ObjectUtil.equals(value, that.getValue());
}
@Override
protected String toStringAdditional()
{
if (index == Notification.NO_INDEX)
{
return MessageFormat.format("value={0}", value); //$NON-NLS-1$
}
return MessageFormat.format("value={0}, index={1}", value, index); //$NON-NLS-1$
}
}