/* * Copyright (c) 2010-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: * Eike Stepper - initial API and implementation * Simon McDuff - bug 201266 * Simon McDuff - bug 212958 * Simon McDuff - bug 213402 */ package org.eclipse.emf.cdo.spi.common.revision; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchManager; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDProvider; import org.eclipse.emf.cdo.common.id.CDOIDTemp; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; import org.eclipse.emf.cdo.common.model.CDOModelUtil; import org.eclipse.emf.cdo.common.model.CDOType; import org.eclipse.emf.cdo.common.protocol.CDODataInput; import org.eclipse.emf.cdo.common.protocol.CDODataOutput; import org.eclipse.emf.cdo.common.revision.CDOElementProxy; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDOListFactory; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionData; import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.common.security.CDOPermissionProvider; import org.eclipse.emf.cdo.common.security.NoPermissionException; import org.eclipse.emf.cdo.common.util.CDOCommonUtil; import org.eclipse.emf.cdo.internal.common.bundle.OM; import org.eclipse.emf.cdo.internal.common.messages.Messages; import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl; import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList.ConfigurableEquality; import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.net4j.util.om.trace.PerfTracer; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; 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.FeatureMap.Entry; import org.eclipse.emf.ecore.util.FeatureMapUtil; import java.io.IOException; import java.text.MessageFormat; import java.util.Map; /** * If the meaning of this type isn't clear, there really should be more of a description here... * * @author Eike Stepper * @since 3.0 * @noextend This class is not intended to be subclassed by clients. */ public abstract class BaseCDORevision extends AbstractCDORevision { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, BaseCDORevision.class); private static final PerfTracer READING = new PerfTracer(OM.PERF_REVISION_READING, BaseCDORevision.class); private static final PerfTracer WRITING = new PerfTracer(OM.PERF_REVISION_WRITING, BaseCDORevision.class); private static final int RESOURCE_NODE_NAME_INDEX = 1; private static final int RESOURCE_FOLDER_NODES_INDEX = 2; private static final byte UNSET_OPCODE = 0; private static final byte SET_NULL_OPCODE = 1; private static final byte SET_NOT_NULL_OPCODE = 2; private static final byte READ_PERMISSION_FLAG = 1 << 0; // 1 private static final byte WRITE_PERMISSION_FLAG = 1 << 1; // 2 private static final byte FROZEN_FLAG = 1 << 2; // 4 private static final byte UNCHUNKED_FLAG = 1 << 3; // 8 private static final byte BYPASS_PERMISSION_CHECKS_FLAG = 1 << 4; // 16 private static final byte LIST_PRESERVING_FLAG = 1 << 5; // 32; private static final byte PERMISSION_MASK = READ_PERMISSION_FLAG | WRITE_PERMISSION_FLAG; // 3 private CDOID id; private CDOBranchPoint branchPoint; private int version; private long revised; private CDOID resourceID; /** * On a client, between a local modification and the commit the value of this <i>ID</i> can be an EObject. */ private Object containerID; private int containingFeatureID; private transient byte flags; /** * @since 3.0 */ public BaseCDORevision(EClass eClass) { super(eClass); if (eClass != null) { version = UNSPECIFIED_VERSION; revised = UNSPECIFIED_DATE; resourceID = CDOID.NULL; containerID = CDOID.NULL; containingFeatureID = 0; initValues(getAllPersistentFeatures()); } flags = CDOPermission.WRITE.getBits(); } protected BaseCDORevision(BaseCDORevision source) { super(source.getEClass()); id = source.id; branchPoint = source.branchPoint; version = source.version; revised = source.revised; resourceID = source.resourceID; containerID = source.containerID; containingFeatureID = source.containingFeatureID; flags = (byte)(source.flags & ~FROZEN_FLAG); } /** * @since 3.0 */ public void read(CDODataInput in) throws IOException { if (READING.isEnabled()) { READING.start(this); } readSystemValues(in); flags = in.readByte(); // Don't set permissions into this.falgs before readValues() flags |= UNCHUNKED_FLAG; // First assume all lists are unchunked; may be revised below flags |= BYPASS_PERMISSION_CHECKS_FLAG; // Temporarily disable permission checking to be able to set the read values if ((flags & PERMISSION_MASK) == CDOPermission.NONE.ordinal()) { if (getClassInfo().isResourceNode()) { clearValues(); EClass eClass = getEClass(); EStructuralFeature[] features = getAllPersistentFeatures(); readValue(in, eClass, features, RESOURCE_NODE_NAME_INDEX, true); if (getClassInfo().isResourceFolder()) { if (!readValue(in, eClass, features, RESOURCE_FOLDER_NODES_INDEX, true)) { flags &= ~UNCHUNKED_FLAG; } } } } else { if (!readValues(in)) { flags &= ~UNCHUNKED_FLAG; } } // Enable permission checking flags &= ~BYPASS_PERMISSION_CHECKS_FLAG; if (READING.isEnabled()) { READING.stop(this); } } /** * @since 4.0 */ protected void readSystemValues(CDODataInput in) throws IOException { EClassifier classifier = in.readCDOClassifierRefAndResolve(); initClassInfo((EClass)classifier); id = in.readCDOID(); branchPoint = in.readCDOBranchPoint(); version = in.readInt(); if (!id.isTemporary()) { revised = in.readLong(); } resourceID = in.readCDOID(); containerID = in.readCDOID(); containingFeatureID = in.readInt(); if (TRACER.isEnabled()) { TRACER.format("Reading revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ id, getEClass().getName(), version, branchPoint, revised, resourceID, containerID, containingFeatureID); } } /** * @since 4.3 */ public boolean readValues(CDODataInput in) throws IOException { EClass owner = getEClass(); EStructuralFeature[] features = getAllPersistentFeatures(); initValues(features); boolean unchunked = true; for (int i = 0; i < features.length; i++) { unchunked = readValue(in, owner, features, i, unchunked); } return unchunked; } private boolean readValue(CDODataInput in, EClass owner, EStructuralFeature[] features, int i, boolean unchunked) throws IOException { Object value; byte unsetState = in.readByte(); switch (unsetState) { case UNSET_OPCODE: return unchunked; case SET_NULL_OPCODE: setValue(i, CDORevisionData.NIL); return unchunked; } EStructuralFeature feature = features[i]; if (feature.isMany()) { CDOList list = in.readCDOList(owner, feature); if (unchunked) { int size = list.size(); if (size != 0) { Object lastElement = list.get(size - 1); if (lastElement == InternalCDOList.UNINITIALIZED || lastElement instanceof CDOElementProxy) { unchunked = false; } } } value = list; } else { value = in.readCDOFeatureValue(feature); if (TRACER.isEnabled()) { TRACER.format("Read feature {0}: {1}", feature.getName(), value); } } setValue(i, value); return unchunked; } /** * @since 4.0 */ public void write(CDODataOutput out, int referenceChunk) throws IOException { write(out, referenceChunk, null); } /** * @since 4.1 */ public void write(CDODataOutput out, int referenceChunk, CDOBranchPoint securityContext) throws IOException { if (WRITING.isEnabled()) { WRITING.start(this); } writeSystemValues(out); CDOPermissionProvider permissionProvider = out.getPermissionProvider(); CDOPermission permission = permissionProvider.getPermission(this, securityContext); out.writeByte(permission.getBits()); if (permission == CDOPermission.NONE) { if (getClassInfo().isResourceNode()) { EClass eClass = getEClass(); EStructuralFeature[] features = getAllPersistentFeatures(); writeValue(out, eClass, features, RESOURCE_NODE_NAME_INDEX, referenceChunk); if (getClassInfo().isResourceFolder()) { writeValue(out, eClass, features, RESOURCE_FOLDER_NODES_INDEX, referenceChunk); } } } else { if (!isUnchunked() && referenceChunk != 0) { CDORevisionUnchunker unchunker = out.getRevisionUnchunker(); if (unchunker != null) { unchunker.ensureChunks(this, referenceChunk); } } writeValues(out, referenceChunk); } if (WRITING.isEnabled()) { WRITING.stop(this); } } /** * @since 4.0 */ protected void writeSystemValues(CDODataOutput out) throws IOException { EClass eClass = getEClass(); CDOClassifierRef classRef = new CDOClassifierRef(eClass); if (TRACER.isEnabled()) { TRACER.format("Writing revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ id, eClass.getName(), getVersion(), branchPoint, revised, resourceID, containerID, containingFeatureID); } out.writeCDOClassifierRef(classRef); out.writeCDOID(id); out.writeCDOBranchPoint(branchPoint); out.writeInt(getVersion()); if (!id.isTemporary()) { out.writeLong(revised); } out.writeCDOID(resourceID); out.writeCDOID(out.getIDProvider().provideCDOID(containerID)); out.writeInt(containingFeatureID); } /** * @since 4.3 */ public void writeValues(CDODataOutput out, int referenceChunk) throws IOException { EClass owner = getEClass(); EStructuralFeature[] features = getAllPersistentFeatures(); for (int i = 0; i < features.length; i++) { writeValue(out, owner, features, i, referenceChunk); } } private void writeValue(CDODataOutput out, EClass owner, EStructuralFeature[] features, int i, int referenceChunk) throws IOException { EStructuralFeature feature = features[i]; Object value = getValue(i); if (value == null) { // Feature is NOT set out.writeByte(UNSET_OPCODE); return; } // Feature IS set if (value == CDORevisionData.NIL) { // Feature IS null out.writeByte(SET_NULL_OPCODE); return; } // Feature is NOT null out.writeByte(SET_NOT_NULL_OPCODE); if (feature.isMany()) { CDOList list = (CDOList)value; out.writeCDOList(owner, feature, list, referenceChunk); } else { checkNoFeatureMap(feature); if (feature instanceof EReference) { value = out.getIDProvider().provideCDOID(value); } if (TRACER.isEnabled()) { TRACER.format("Writing feature {0}: {1}", feature.getName(), value); } out.writeCDOFeatureValue(feature, value); } } /** * @see #write(CDODataOutput, int) * @since 3.0 */ public void convertEObjects(CDOIDProvider idProvider) { if (!(containerID instanceof CDOID)) { containerID = idProvider.provideCDOID(containerID); } EStructuralFeature[] features = getAllPersistentFeatures(); for (int i = 0; i < features.length; i++) { EStructuralFeature feature = features[i]; if (feature.isMany()) { CDOList list = getValueAsList(i); if (list != null) { boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature); for (int j = 0; j < list.size(); j++) { Object value = list.get(j, false); EStructuralFeature innerFeature = feature; // Prepare for possible feature map if (isFeatureMap) { Entry entry = (FeatureMap.Entry)value; innerFeature = entry.getEStructuralFeature(); value = entry.getValue(); } if (value != null && innerFeature instanceof EReference) { CDOID newValue = idProvider.provideCDOID(value); if (newValue != value) { list.set(j, newValue); } } } } } else { checkNoFeatureMap(feature); Object value = getValue(i); if (value != null && feature instanceof EReference) { CDOID newValue = idProvider.provideCDOID(value); if (newValue != value) { setValue(i, newValue); } } } } } public CDOID getID() { return id; } public void setID(CDOID id) { if (CDOIDUtil.isNull(id)) { throw new IllegalArgumentException(Messages.getString("AbstractCDORevision.1")); //$NON-NLS-1$ } if (TRACER.isEnabled()) { TRACER.format("Setting ID: {0}", id); } this.id = id; } /** * @since 4.2 */ public InternalCDOBranch getBranch() { if (branchPoint == null) { return null; } return (InternalCDOBranch)branchPoint.getBranch(); } /** * @since 3.0 */ public long getTimeStamp() { if (branchPoint == null) { return UNSPECIFIED_DATE; } return branchPoint.getTimeStamp(); } /** * @since 3.0 */ public void setBranchPoint(CDOBranchPoint branchPoint) { branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint); if (TRACER.isEnabled()) { TRACER.format("Setting branchPoint {0}: {1}", this, branchPoint); } this.branchPoint = branchPoint; } public int getVersion() { return version; } public void setVersion(int version) { if (TRACER.isEnabled()) { TRACER.format("Setting version for {0}: v{1}", this, version); } this.version = version; } public long getRevised() { return revised; } public void setRevised(long revised) { long created = branchPoint.getTimeStamp(); if (revised != UNSPECIFIED_DATE && revised < Math.max(0, created)) { throw new IllegalArgumentException( "revision=" + this + ", created=" + CDOCommonUtil.formatTimeStamp(created) + ", revised=" + CDOCommonUtil.formatTimeStamp(revised)); } if (TRACER.isEnabled()) { TRACER.format("Setting revised {0}: {1}", this, CDOCommonUtil.formatTimeStamp(revised)); } this.revised = revised; } public InternalCDORevisionDelta compare(CDORevision origin) { return new CDORevisionDeltaImpl(origin, this); } public void merge(CDORevisionDelta delta) { CDORevisionMerger applier = new CDORevisionMerger(); applier.merge(this, delta); } public CDOID getResourceID() { return resourceID; } public void setResourceID(CDOID resourceID) { if (TRACER.isEnabled()) { TRACER.format("Setting resourceID {0}: {1}", this, resourceID); } this.resourceID = resourceID; } public Object getContainerID() { return containerID; } public void setContainerID(Object containerID) { if (TRACER.isEnabled()) { TRACER.format("Setting containerID {0}: {1}", this, containerID); } this.containerID = containerID; } public int getContainingFeatureID() { return containingFeatureID; } public void setContainingFeatureID(int containingFeatureID) { if (TRACER.isEnabled()) { TRACER.format("Setting containingFeatureID {0}: {1}", this, containingFeatureID); } this.containingFeatureID = containingFeatureID; } public int hashCode(EStructuralFeature feature) { Object value = getValue(feature); if (value == null) { // See how AbstractEList.hashCode() returns 1 for an empty list. return 1; } return value.hashCode(); } public Object get(EStructuralFeature feature, int index) { if (feature.isMany()) { CDOList list = getList(feature); return list.get(index); } return getValue(feature); } public boolean contains(EStructuralFeature feature, Object value) { CDOList list = getList(feature); return list.contains(value); } public int indexOf(EStructuralFeature feature, Object value) { CDOList list = getList(feature); return list.indexOf(value); } public int lastIndexOf(EStructuralFeature feature, Object value) { CDOList list = getList(feature); return list.lastIndexOf(value); } public boolean isEmpty(EStructuralFeature feature) { CDOList list = getList(feature); return list.isEmpty(); } public int size(EStructuralFeature feature) { CDOList list = getList(feature); return list.size(); } public Object[] toArray(EStructuralFeature feature) { if (!feature.isMany()) { throw new IllegalStateException("!feature.isMany()"); } CDOList list = getList(feature); return list.toArray(); } public <T> T[] toArray(EStructuralFeature feature, T[] array) { if (!feature.isMany()) { throw new IllegalStateException("!feature.isMany()"); } CDOList list = getList(feature); return list.toArray(array); } public void add(EStructuralFeature feature, int index, Object value) { CDOList list = getList(feature); list.add(index, value); } public void clear(EStructuralFeature feature) { if (feature.isMany() && isListPreserving()) { getList(feature).clear(); } else { setValue(feature, null); } } public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex) { CDOList list = getList(feature); return list.move(targetIndex, sourceIndex); } public Object remove(EStructuralFeature feature, int index) { CDOList list = getList(feature); return list.remove(index); } public Object set(EStructuralFeature feature, int index, Object value) { if (feature.isMany()) { CDOList list = getList(feature); return list.set(index, value); } return setValue(feature, value); } public void unset(EStructuralFeature feature) { if (feature.isMany() && isListPreserving()) { getList(feature).clear(); } else { setValue(feature, null); } } /** * @since 4.0 */ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster) { if (TRACER.isEnabled()) { TRACER.format("Adjusting references for revision {0}", this); } boolean changed = false; CDOID id1 = (CDOID)referenceAdjuster.adjustReference(resourceID, CDOContainerFeatureDelta.CONTAINER_FEATURE, CDOFeatureDelta.NO_INDEX); if (id1 != resourceID) { resourceID = id1; changed = true; } Object id2 = referenceAdjuster.adjustReference(containerID, CDOContainerFeatureDelta.CONTAINER_FEATURE, CDOFeatureDelta.NO_INDEX); if (id2 != containerID) { containerID = id2; changed = true; } EStructuralFeature[] features = getAllPersistentFeatures(); for (int i = 0; i < features.length; i++) { EStructuralFeature feature = features[i]; if (feature instanceof EReference || FeatureMapUtil.isFeatureMap(feature)) { if (feature.isMany()) { InternalCDOList list = (InternalCDOList)getValueAsList(i); if (list != null) { changed |= list.adjustReferences(referenceAdjuster, feature); } } else { CDOType type = CDOModelUtil.getType(feature); Object oldValue = getValue(i); Object newValue = type.adjustReferences(referenceAdjuster, oldValue, feature, CDOFeatureDelta.NO_INDEX); if (oldValue != newValue) // Just an optimization for NOOP adjusters { setValue(i, newValue); changed = true; } } } } return changed; } /** * @since 4.3 */ public void adjustBranches(CDOBranchManager newBranchManager) { if (branchPoint != null) { CDOBranch branch = branchPoint.getBranch(); if (branch != null) { branch = newBranchManager.getBranch(branch.getID()); branchPoint = branch.getPoint(branchPoint.getTimeStamp()); } } } public Object getValue(EStructuralFeature feature) { checkReadable(feature); int featureIndex = getFeatureIndex(feature); return getValue(featureIndex); } public Object setValue(EStructuralFeature feature, Object value) { int featureIndex = getFeatureIndex(feature); try { Object old = getValue(featureIndex); setValue(featureIndex, value); return old; } catch (ArrayIndexOutOfBoundsException ex) { throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.20"), feature, getClassInfo()), ex); } } public CDOList getList(EStructuralFeature feature) { return getList(feature, 0); } public CDOList getList(EStructuralFeature feature, int size) { checkReadable(feature); int featureIndex = getFeatureIndex(feature); InternalCDOList list = (InternalCDOList)getValue(featureIndex); if (list == null && size != -1) { list = (InternalCDOList)CDOListFactory.DEFAULT.createList(size, 0, 0); if (feature instanceof EReference && list instanceof ConfigurableEquality) { ((ConfigurableEquality)list).setUseEquals(false); } synchronized (this) { boolean bypassPermissionChecks = bypassPermissionChecks(true); try { setValue(featureIndex, list); } finally { bypassPermissionChecks(bypassPermissionChecks); } } } return list; } public void setList(EStructuralFeature feature, InternalCDOList list) { int featureIndex = getFeatureIndex(feature); setValue(featureIndex, list); } /** * @since 4.2 */ public EStructuralFeature[] clearValues() { EStructuralFeature[] features = getClassInfo().getAllPersistentFeatures(); initValues(features); return features; } /** * @since 4.3 */ public String getResourceNodeName() { return (String)doGetValue(RESOURCE_NODE_NAME_INDEX); } /** * @since 4.1 */ public CDOPermission getPermission() { return CDOPermission.get(flags & PERMISSION_MASK); } /** * @since 4.1 */ public void setPermission(CDOPermission permission) { flags = (byte)(flags & ~PERMISSION_MASK | permission.getBits() & PERMISSION_MASK); } /** * @since 4.3 */ public boolean bypassPermissionChecks(boolean on) { boolean old = (flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0; if (on) { flags |= BYPASS_PERMISSION_CHECKS_FLAG; } else { flags &= ~BYPASS_PERMISSION_CHECKS_FLAG; } return old; } /** * @since 4.3 */ public boolean isListPreserving() { return (flags & LIST_PRESERVING_FLAG) != 0; } /** * @since 4.3 */ public void setListPreserving() { flags |= LIST_PRESERVING_FLAG; } /** * @since 4.1 */ public void freeze() { flags |= FROZEN_FLAG; if (isReadable()) { EStructuralFeature[] features = getAllPersistentFeatures(); for (int i = 0; i < features.length; i++) { EStructuralFeature feature = features[i]; if (feature.isMany()) { InternalCDOList list = (InternalCDOList)doGetValue(i); if (list != null) { list.freeze(); } } } } } /** * @since 4.2 */ public boolean isFrozen() { return (flags & FROZEN_FLAG) != 0; } /** * @since 4.1 */ public boolean isUnchunked() { return (flags & UNCHUNKED_FLAG) != 0; } /** * @since 4.1 */ public void setUnchunked() { flags |= UNCHUNKED_FLAG; } protected Object getValue(int featureIndex) { return doGetValue(featureIndex); } protected void setValue(int featureIndex, Object value) { checkUnfrozen(featureIndex, value); checkWritable(); doSetValue(featureIndex, value); } protected abstract void initValues(EStructuralFeature[] allPersistentFeatures); /** * @since 4.1 */ protected abstract Object doGetValue(int featureIndex); /** * @since 4.1 */ protected abstract void doSetValue(int featureIndex, Object value); private CDOList getValueAsList(int i) { return (CDOList)getValue(i); } private void checkUnfrozen(int featureIndex, Object value) { if ((flags & FROZEN_FLAG) != 0) { // Exception 1: LoadPermissionsRequest needs to "reload" revision values in case the original permission was NONE. // In this case BYPASS_PERMISSION_CHECKS_FLAG is set. if ((flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0) { return; } Object oldValue = getValue(featureIndex); // Exception 2: Setting an empty list as the value for an isMany feature, is allowed if the old value is null. // This is a case of lazy initialization. boolean newIsEmptyList = value instanceof EList<?> && ((EList<?>)value).size() == 0; if (newIsEmptyList && oldValue == null) { return; } // Exception 3a: Replacing a temp ID with a regular ID is allowed (happens during postCommit of new objects) // Exception 3b: Replacing a temp ID with another temp ID is also allowed (happens when changes are imported in a // PushTx). if (oldValue instanceof CDOIDTemp && value instanceof CDOID) { return; } throw new IllegalStateException("Cannot modify a frozen revision"); } } private void checkReadable(EStructuralFeature feature) { if ((flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0) { return; } if (CDOModelUtil.isResourcePathFeature(feature)) { return; } if ((flags & READ_PERMISSION_FLAG) == 0) { throw new NoPermissionException(this); } } private void checkWritable() { if ((flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0) { return; } if ((flags & WRITE_PERMISSION_FLAG) == 0) { throw new NoPermissionException(this); } } public static void checkNoFeatureMap(EStructuralFeature feature) { if (FeatureMapUtil.isFeatureMap(feature)) { throw new UnsupportedOperationException("Single-valued feature maps not yet handled"); } } public static Object remapID(Object value, Map<CDOID, CDOID> idMappings, boolean allowUnmappedTempIDs) { if (value instanceof CDOID) { CDOID oldID = (CDOID)value; if (!oldID.isNull()) { CDOID newID = idMappings.get(oldID); if (newID != null) { if (TRACER.isEnabled()) { TRACER.format("Adjusting ID: {0} --> {1}", oldID, newID); } return newID; } if (oldID instanceof CDOIDTemp) { throw new IllegalStateException(MessageFormat.format(Messages.getString("AbstractCDORevision.2"), oldID)); } } } return value; } /** * @since 4.3 */ public static String formatFlags(BaseCDORevision revision) { int flags = revision.flags; StringBuilder builder = new StringBuilder(); if ((flags & UNCHUNKED_FLAG) != 0) { builder.append("UNCHUNKED"); } if ((flags & FROZEN_FLAG) != 0) { if (builder.length() != 0) { builder.append("|"); } builder.append("FROZEN"); } if ((flags & READ_PERMISSION_FLAG) != 0) { if (builder.length() != 0) { builder.append("|"); } builder.append("READ"); } if ((flags & WRITE_PERMISSION_FLAG) != 0) { if (builder.length() != 0) { builder.append("|"); } builder.append("WRITE"); } if ((flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0) { if (builder.length() != 0) { builder.append("|"); } builder.append("BYPASS_PERMISSION_CHECKS"); } return builder.toString(); } }