private void UpdateLowerLevels(IExpressionNode myNode, LevelKey myCurrentLevelKey, IEnumerable<LevelKey> myLowerLevelKeys, IExpressionGraph myGraph) { if (myCurrentLevelKey.Level > 0) { lock (myGraph) { //iterate the next lower LevelKeys foreach (var aLowerLevelKey in myLowerLevelKeys) { #region data //get next lower attribute (might be more than one step away) int levelDistance = myCurrentLevelKey.Level - aLowerLevelKey.Level; //GraphDBType currentType = null; EdgeKey myCurrentBackwardEdgekey = null; TypeAttribute currentAttribute = null; SettingInvalidReferenceHandling invalidReferenceSetting = null; #endregion if (levelDistance >= 1) { if (myCurrentLevelKey.Level > 1) { myCurrentBackwardEdgekey = myCurrentLevelKey.Edges[myCurrentLevelKey.Level - 1]; } else { myCurrentBackwardEdgekey = myCurrentLevelKey.Edges[0]; } } else { throw new GraphDBException(new Error_ExpressionGraphInternal(new System.Diagnostics.StackTrace(true), "Distances below 1 are not valid.")); } IEnumerable<ObjectUUID> referencedUUIDs = null; GraphDBType referencedType = null; currentAttribute = _DBContext.DBTypeManager.GetTypeByUUID(myCurrentBackwardEdgekey.TypeUUID).GetTypeAttributeByUUID(myCurrentBackwardEdgekey.AttrUUID); if (currentAttribute.IsBackwardEdge) { var backwardEdgeTypeInfo = currentAttribute.BackwardEdgeDefinition.GetTypeAndAttributeInformation(_DBContext.DBTypeManager); var dbObjectStream = myNode.GetDBObjectStream(_DBObjectCache, backwardEdgeTypeInfo.Item1.UUID); referencedType = backwardEdgeTypeInfo.Item2.GetDBType(_DBContext.DBTypeManager); if (dbObjectStream.HasAttribute(backwardEdgeTypeInfo.Item2.UUID, backwardEdgeTypeInfo.Item1)) { referencedUUIDs = GetUUIDsForAttribute(dbObjectStream, backwardEdgeTypeInfo.Item2, backwardEdgeTypeInfo.Item1); } } else { referencedType = currentAttribute.GetRelatedType(_DBContext.DBTypeManager); if (myNode.BackwardEdges.ContainsKey(aLowerLevelKey.LastEdge)) { //take the edges that are already available referencedUUIDs = myNode.BackwardEdges[aLowerLevelKey.LastEdge].Select(item => item.Destination); } else { //load the backward edge stream var currentBackwardEdgeStream = _DBObjectCache.LoadDBBackwardEdgeStream(currentAttribute.GetDBType(_DBContext.DBTypeManager), myNode.GetObjectUUID()); if (currentBackwardEdgeStream.Failed()) { throw new GraphDBException(new Error_CouldNotLoadBackwardEdge(myNode.GetDBObjectStream(_DBObjectCache, currentAttribute.GetRelatedType(_DBContext.DBTypeManager).UUID), currentAttribute, currentBackwardEdgeStream.IErrors)); } if (currentBackwardEdgeStream.Value.ContainsBackwardEdge(myCurrentBackwardEdgekey)) { referencedUUIDs = currentBackwardEdgeStream.Value.GetBackwardEdgeUUIDs(myCurrentBackwardEdgekey); } } } if (referencedUUIDs != null) { var lowerLevelKeys = ExtractLowerLevelKeys(GetPreviousLevel(aLowerLevelKey.Level, myGraph.Levels), aLowerLevelKey, myGraph); EdgeKey edgeKeyForBackwardEdge = null; //get edgeKey for backwardEdge if (myCurrentLevelKey.Level == 1) { edgeKeyForBackwardEdge = aLowerLevelKey.LastEdge; } else { edgeKeyForBackwardEdge = aLowerLevelKey.Edges[aLowerLevelKey.Level - 1]; } Exceptional<DBObjectStream> referencedDBObject = null; foreach (var aReferenceObjectUUID in referencedUUIDs) { referencedDBObject = _DBObjectCache.LoadDBObjectStream(referencedType, aReferenceObjectUUID); if (!referencedDBObject.Success()) { #region error if (invalidReferenceSetting == null) { invalidReferenceSetting = (SettingInvalidReferenceHandling)_DBContext.DBSettingsManager.GetSetting(SettingInvalidReferenceHandling.UUID, _DBContext, Enums.TypesSettingScope.ATTRIBUTE, referencedType, currentAttribute).Value; } switch (invalidReferenceSetting.Behaviour) { case BehaviourOnInvalidReference.ignore: #region ignore //set lower levelKeys to null because it is not possible to go any lower AddNodeRecursiveBackward(aReferenceObjectUUID, myNode.GetObjectUUID(), myCurrentLevelKey, aLowerLevelKey, null, myGraph); myNode.AddBackwardEdge(edgeKeyForBackwardEdge, aReferenceObjectUUID, null); #endregion break; case BehaviourOnInvalidReference.log: AddWarning(new Warning_EdgeToNonExistingNode(myNode.GetDBObjectStream(_DBObjectCache, referencedType.UUID), currentAttribute.GetDBType(_DBContext.DBTypeManager), currentAttribute, referencedDBObject.IErrors)); break; default: throw new GraphDBException(new Error_NotImplemented(new System.Diagnostics.StackTrace())); } #endregion } else { AddNodeRecursiveBackward(aReferenceObjectUUID, myNode.GetObjectUUID(), myCurrentLevelKey, aLowerLevelKey, lowerLevelKeys, myGraph); myNode.AddBackwardEdge(edgeKeyForBackwardEdge, aReferenceObjectUUID, null); } } } } } } }