public void cdoInternalPostDetach(boolean remote) { if (remote) { setInstanceContainer(null, eContainerFeatureID()); setInstanceResource(null); return; } // This loop adjusts the opposite wrapper objects to support dangling references. See // Bugzilla_251263_Test InternalCDORevision revision = cdoRevision(); for (EReference reference : classInfo.getAllPersistentReferences()) { if (!reference.isContainer() && classInfo.hasPersistentOpposite(reference)) { if (reference.isMany()) { EReference oppositeReference = reference.getEOpposite(); int size = revision.size(reference); for (int i = 0; i < size; i++) { EObject object = (EObject) getValueFromRevision(reference, i); adjustPersistentOppositeReference(this, object, oppositeReference); } } else { EObject oppositeObject = (EObject) instance.eGet(reference); if (oppositeObject != null) { EReference oppositeReference = reference.getEOpposite(); adjustPersistentOppositeReference(this, oppositeObject, oppositeReference); } } } } }
private void addLink( EObject sourceEObject, EObject targetEObject, EReference eReference, int targetPosition) { Object_ sourceObject = map.getObject(sourceEObject); Object_ targetObject = map.getObject(targetEObject); Association association = getFUMLAssociation(eReference); if (hasOppositeReference(eReference) && haveProcessedAsOpposite(eReference, sourceObject, targetObject, association)) { return; } // Setup target property end LinkCreationData linkData = new LinkCreationData(sourceObject, targetObject, association); LinkEndCreationData targetEndData = linkData.createLinkEndCreationData(); targetEndData.setEnd(getTargetPropertyEnd(eReference, association)); linkData.setTargetEndData(targetEndData); linkData.setTargetPosition(targetPosition); // Setup source property end LinkEndCreationData sourceEndData = linkData.createLinkEndCreationData(); if (hasOppositeReference(eReference)) { EReference oppositeReference = eReference.getEOpposite(); sourceEndData.setEnd(getTargetPropertyEnd(oppositeReference, association)); int sourcePosition = getPosition(targetEObject, oppositeReference, sourceEObject); linkData.setSourcePosition(sourcePosition); addProcessedOpposite(sourceEndData); } else { sourceEndData.setEnd(getSourcePropertyEnd(eReference, association)); } linkData.setSourceEndData(sourceEndData); Link link = linkData.createNewLink(); map.addExtensionalValue(link); // link.addTo(locus); locus.add(link); }
public static int kind(EStructuralFeature eStructuralFeature) { int result = 0; EClassifier eClassifier = eStructuralFeature.getEType(); if (eClassifier.getInstanceClass() != null) { result |= HAS_INSTANCE_CLASS; } if (eStructuralFeature.isUnsettable()) { result |= IS_UNSETTABLE; } if (eStructuralFeature instanceof EReference) { EReference eReference = (EReference) eStructuralFeature; EReference inverseEReference = eReference.getEOpposite(); if (eReference.isContainment()) { result |= IS_CONTAINMENT; } if (inverseEReference != null) { // This forces the feature ids to be assigned. // inverseEReference.getEContainingClass().getFeatureCount(); result |= HAS_NAVIGABLE_INVERSE; if (inverseEReference.isMany()) { result |= HAS_MANY_INVERSE; } if (inverseEReference.isContainment()) { result |= IS_CONTAINER; } } if (eReference.isResolveProxies()) { result |= HAS_PROXIES; } result |= IS_EOBJECT; } else // if (eStructuralFeature instanceof EAttribute { if (eClassifier instanceof EEnum) { result |= IS_ENUM; } else { Class<?> instanceClass = eClassifier.getInstanceClass(); if (instanceClass != null && instanceClass.isPrimitive()) { result |= IS_PRIMITIVE; } } } if (eStructuralFeature.isUnique()) { result |= IS_UNIQUE; } return result; }
void resolve(EObject object, EReference reference, EObject proxy) { EReference opposite = reference.getEOpposite(); if (opposite != null) { if (opposite.isMany()) { InternalEList<?> list = (InternalEList<?>) object.eGet(opposite, false); int index = list.basicIndexOf(proxy); if (index >= 0) { list.get(index); // resolve just this index } } else { object.eGet(opposite, true); // resolve the scalar reference } } }
/** * Converts the value of an EReference with isMany==false, the value is converted to a Object and * set in the correct feature in the model managed object. * * @param eObject the eObject from which the value is read * @param modelObject the Object in which the value is to be set * @param eReference the eReference which is converted */ protected void convertSingleEReference( final EObject eObject, final ModelObject<?> modelObject, final EReference eReference) { // bidirectional one-to-many are always set from the many side to preserve the order final EObject value = (EObject) eObject.eGet(eReference); if (!eReference.isMany() && value != null && eReference.getEOpposite() != null && eReference.getEOpposite().isMany()) { return; } if (value == null) { modelObject.eSet(eReference, null); } else { modelObject.eSet(eReference, createTarget(value)); } }
/** * Converts the value of an EReference with isMany==true, the values of the collection are * converted to Objects and added to the list in the correct feature in the {@link ModelObject}. * * @param eObject the eObject from which the value is read * @param modelObject the Object in which the value is set * @param eReference the eReference which is converted */ protected void convertManyEReference( final EObject eObject, final ModelObject<?> modelObject, final EReference eReference) { @SuppressWarnings("unchecked") final Collection<EObject> eValues = (Collection<EObject>) eObject.eGet(eReference); if (ModelUtils.isEMap(eReference)) { @SuppressWarnings("unchecked") final Map<Object, Object> mValues = (Map<Object, Object>) modelObject.eGet(eReference); // clear as there can be current values if the target is read from the db mValues.clear(); for (final Object eValue : eValues) { @SuppressWarnings("unchecked") final Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) eValue; // key and value can also be an EObject final Object key; if (entry.getKey() instanceof EObject) { key = createTarget((EObject) entry.getKey()); } else { key = entry.getKey(); } final Object value; if (entry.getValue() instanceof EObject) { value = createTarget((EObject) entry.getValue()); } else { value = entry.getValue(); } mValues.put(key, value); } } else { // a many to many if (eReference.getEOpposite() != null && eReference.getEOpposite().isMany()) { final ManyToMany mtm = new ManyToMany(); mtm.setOwner(eObject); mtm.setEReference(eReference); toRepairManyToMany.add(mtm); } final Collection<?> mValues = (Collection<?>) modelObject.eGet(eReference); // make a copy final List<Object> copiedMValues = new ArrayList<Object>(mValues); // clear as there can be current values if the target is read from the db // use forloop as the collection can be unmodifiable for (Object o : new ArrayList<Object>(mValues)) { modelObject.eRemoveFrom(eReference, o); } // check that the eopposite is indeed cleared, this is not the case if // there is no bi-directional code generated final EReference eOpposite = eReference.getEOpposite(); if (eOpposite != null && !eOpposite.isMany()) { for (Object mValue : copiedMValues) { final ModelObject<?> modelMValue = ModelResolver.getInstance().getModelObject(mValue); modelMValue.eSet(eOpposite, null); } } for (final EObject eValue : eValues) { final Object target = createTarget(eValue); // first add to the many reference modelObject.eAddTo(eReference, target); // add to the other side, this is needed because the bi-directional // api is not always generated if (eOpposite != null && !eOpposite.isMany()) { final ModelObject<?> modelObjectTarget = ModelResolver.getInstance().getModelObject(target); modelObjectTarget.eSet(eReference.getEOpposite(), modelObject.getTarget()); } } } }
private boolean hasOppositeReference(EReference eReference) { return eReference.getEOpposite() != null; }
/** * Converts the value of an EReference with isMany==true, the values of the collection are * converted to EObjects and added to the list in the correct feature in the eObject. * * @param modelObject the modelObject from which the value is retrieved. * @param eObject the eObject in which the value is set (after it has been converted) * @param eReference the eReference which is converted */ protected void convertManyEReference( final ModelObject<?> modelObject, final EObject eObject, final EReference eReference) { // container feature is always set from the other side, the containment // side if (eReference.isContainer()) { return; } final Object manyValue = modelObject.eGet(eReference); final Collection<EObject> newValues = new ArrayList<EObject>(); boolean isMap = Map.class.isAssignableFrom(manyValue.getClass()); EStructuralFeature valueFeature = null; EStructuralFeature keyFeature = null; if (isMap) { final EClass mapEClass = eReference.getEReferenceType(); valueFeature = mapEClass.getEStructuralFeature("value"); // $NON-NLS-1$ keyFeature = mapEClass.getEStructuralFeature("key"); // $NON-NLS-1$ Check.isTrue( ModelUtils.isEMap(eReference), "Expected emap EReference, but th// case for EReference " //$NON-NLS-1$ + eReference); final Map<?, ?> map = (Map<?, ?>) manyValue; for (final Object key : map.keySet()) { final Object value = map.get(key); final EObject mapEntryEObject = EcoreUtil.create(mapEClass); // key and value maybe primitive types but can also be // references to model objects. if (valueFeature instanceof EReference) { mapEntryEObject.eSet(valueFeature, createTarget(value)); } else { mapEntryEObject.eSet(valueFeature, value); } if (keyFeature instanceof EReference) { mapEntryEObject.eSet(keyFeature, createTarget(key)); } else { mapEntryEObject.eSet(keyFeature, key); } newValues.add(mapEntryEObject); } } else { // a many to many if (eReference.getEOpposite() != null && eReference.getEOpposite().isMany()) { final ManyToMany mtm = new ManyToMany(); mtm.setOwner(modelObject); mtm.setEReference(eReference); toRepairManyToMany.add(mtm); } @SuppressWarnings("unchecked") final Collection<Object> values = (Collection<Object>) manyValue; for (final Object value : values) { if (value == null) { newValues.add(null); } else { final InternalEObject eValue = (InternalEObject) createTarget(value); if (!newValues.contains(eValue)) { newValues.add(eValue); } } } } @SuppressWarnings("unchecked") final Collection<EObject> eValues = (Collection<EObject>) eObject.eGet(eReference); boolean updateList = false; if (newValues.size() == eValues.size()) { final Iterator<?> it = eValues.iterator(); for (Object newValue : newValues) { final Object oldValue = it.next(); if (isMap) { final EObject oldMapEntry = (EObject) oldValue; final EObject newMapEntry = (EObject) newValue; final Object oldMapValue = oldMapEntry.eGet(valueFeature); final Object oldMapKey = oldMapEntry.eGet(keyFeature); final Object newMapValue = newMapEntry.eGet(valueFeature); final Object newMapKey = newMapEntry.eGet(keyFeature); if (valueFeature instanceof EReference) { updateList = oldMapValue == newMapValue; } else { updateList = oldMapValue != null ? !oldMapValue.equals(newMapValue) : newMapValue != null ? !newMapValue.equals(oldMapValue) : false; } if (keyFeature instanceof EReference) { updateList = updateList || oldMapKey == newMapKey; } else { updateList = updateList || (oldMapKey != null ? !oldMapKey.equals(newMapKey) : newMapKey != null ? !newMapKey.equals(oldMapKey) : false); } } else { updateList = oldValue != newValue; } if (updateList) { break; } } } else { updateList = true; } if (updateList) { // clear the evalues so that an empty tag is created in the xml eValues.clear(); eValues.addAll(newValues); } }