GetAllSelectedAttributesFromVertex(SecurityToken mySecurityToken, Int64 myTransactionToken, IVertex myDBObject, IVertexType myDBType, Int64 myDepth, EdgeList myLevelKey, String myReference, Boolean myUsingGraph) { IDictionary<String, Object> properties = new Dictionary<string, object>(); IDictionary<String, IEdgeView> edges = new Dictionary<string, IEdgeView>(); var Attributes = new Tuple<IDictionary<string, object>, IDictionary<string, IEdgeView>>(properties, edges); Int64 Depth; var minDepth = 0; //save the already created LevelKey of the refernce type EdgeList levelKey = myLevelKey; IEnumerable<SelectionElement> attributeSelections = null; attributeSelections = getAttributeSelections(myReference, myLevelKey); if (attributeSelections.IsNullOrEmpty()) { #region Get all attributes from the DBO if nothing special was selected if ((myDepth == -1) || (myDepth >= myLevelKey.Level)) { AddAttributesByDBO(mySecurityToken, myTransactionToken, ref Attributes, myDBType, myDBObject, myDepth, myLevelKey, myReference, myUsingGraph, TypesOfSelect.Asterisk); } #endregion } else { foreach (var attrSel in attributeSelections) { #region extract the selected infos //myDepth = attrSel.EdgeList.Level; #region Some kind of asterisk - return all attributes if (attrSel.Selection == TypesOfSelect.Asterisk) { #region Asterisk (*), Rhomb (#), Minus (-), Ad (@) selection Depth = GetDepth(myDepth, 0, myDBType); AddAttributesByDBO(mySecurityToken, myTransactionToken, ref Attributes, myDBType, myDBObject, Depth, myLevelKey, myReference, myUsingGraph, attrSel.Selection, attrSel.TypeID); #endregion continue; } #endregion #region Alias String alias = String.Empty; if (attrSel.Element == null) { alias = (attrSel.Alias == null) ? attrSel.RelatedIDChainDefinition.UndefinedAttribute : attrSel.Alias; } else { alias = (attrSel.Alias == null) ? attrSel.Element.Name : attrSel.Alias; } #endregion if (Attributes.Item1.ContainsKey(alias) || Attributes.Item2.ContainsKey(alias)) { // This is a bug in the attributeSelections add method. No attribute should be in the selected list twice. // If one attribute was selected more than one, these information will be stored in the next level. //System.Diagnostics.Debug.Assert(false, "The attribute '" + alias + "' is selected twice in that level - this shouldnt!"); continue; } if (attrSel is SelectionElementFunction) { #region Select a function var selectionElementFunction = (attrSel as SelectionElementFunction); if (selectionElementFunction.SelectValueAssignment != null && selectionElementFunction.SelectValueAssignment.ValueAssignmentType == SelectValueAssignment.ValueAssignmentTypes.Always) { Attributes.Item1.Add(alias, (selectionElementFunction.SelectValueAssignment.TermDefinition as ValueDefinition).Value); continue; } #region Get the CallingObject Object callingObject = null; if (myUsingGraph) { //a special attribute has no RelatedGraphDBTypeUUID. So use myDBType to create an EdgeKey //EdgeKey key = (selectionElementFunction.Element is ASpecialTypeAttribute) ? new EdgeKey(myDBType.UUID, selectionElementFunction.Element.UUID) : new EdgeKey(selectionElementFunction.Element); EdgeKey key = new EdgeKey(selectionElementFunction.Element.RelatedType.ID, selectionElementFunction.Element.ID); //the levelKey is created with the type inside the select -- f.e. FROM User SELECT Friends.TOP(2) -- it is 'User' //we have to check if the levelKey contains an edge of the VertexType which is equal to the related type of the selection element //this is neccessary -- f.e. FROM User SELECT Friends.TOP(2) -- if the edge 'FRIENDS' is not defined on type User //in this case we have to check if there is a parent type of the reference type which is equal to the related type of the selection element if (levelKey.Edges.All(x => x.VertexTypeID != selectionElementFunction.Element.RelatedType.ID)) { if (myDBType.GetAncestorVertexTypesAndSelf().Select(x => x.ID).Contains(selectionElementFunction.Element.RelatedType.ID)) { var typeID = myDBType.GetAncestorVertexTypesAndSelf().Select(x => x.ID).Where(x => x == selectionElementFunction.Element.RelatedType.ID).First(); levelKey = new EdgeList(typeID); } } myUsingGraph = _ExpressionGraph.IsGraphRelevant(new LevelKey((levelKey + key).Edges, _graphdb, mySecurityToken, myTransactionToken), myDBObject); } if (myUsingGraph && !(selectionElementFunction.Element.Kind != AttributeType.Property)) { switch (selectionElementFunction.Element.Kind) { case AttributeType.IncomingEdge: #region incoming edge var incomingEdgeDefinition = (IIncomingEdgeDefinition)selectionElementFunction.Element; if (myDBObject.HasIncomingVertices(incomingEdgeDefinition.RelatedEdgeDefinition.RelatedType.ID, incomingEdgeDefinition.RelatedEdgeDefinition.ID)) { callingObject = _ExpressionGraph.Select( new LevelKey( (myLevelKey + new EdgeKey(selectionElementFunction.Element.RelatedType.ID, selectionElementFunction.Element.ID)).Edges, _graphdb, mySecurityToken, myTransactionToken), myDBObject, true); } else { callingObject = null; } #endregion break; case AttributeType.OutgoingEdge: #region outgoing edge if (myDBObject.HasOutgoingEdge(selectionElementFunction.Element.ID)) { callingObject = _ExpressionGraph.Select( new LevelKey( (myLevelKey + new EdgeKey(selectionElementFunction.Element.RelatedType.ID, selectionElementFunction.Element.ID)).Edges, _graphdb, mySecurityToken, myTransactionToken), myDBObject, true); } else { callingObject = null; } #endregion break; case AttributeType.Property: callingObject = GetCallingObject(myDBObject, selectionElementFunction.Element); break; case AttributeType.BinaryProperty: default: continue; } } else { callingObject = GetCallingObject(myDBObject, selectionElementFunction.Element); } #endregion #region Execute the function var res = ExecuteFunction(selectionElementFunction, myDBObject, callingObject, myDepth, myReference, myDBType, myLevelKey, myUsingGraph, mySecurityToken, myTransactionToken); if (res == null) { continue; } #endregion #region Add function return value to attributes if (res.Value is IEnumerable<IVertex>) { #region Reference edge //minDepth = attrSel.EdgeList.Level + 1; // depth should be at least the depth of the selected element minDepth = (attrSel.RelatedIDChainDefinition != null) ? attrSel.RelatedIDChainDefinition.Edges.Count - 1 : 0; myUsingGraph = false; Depth = GetDepth(myDepth, minDepth, myDBType); var attr = (attrSel as SelectionElementFunction).Element; //if (Depth > myLevelKey.Level || getAttributeSelections(myReference, myLevelKey + new EdgeKey(attr.RelatedType.ID, attr.ID)).IsNotNullOrEmpty()) if (Depth > levelKey.Level || getAttributeSelections(myReference, levelKey + new EdgeKey(attr.RelatedType.ID, attr.ID)).IsNotNullOrEmpty()) { myUsingGraph = false; #region Resolve DBReferences Attributes.Item2.Add(alias, ResolveAttributeValue((IOutgoingEdgeDefinition)attr, (IEnumerable<IVertex>)res.Value, Depth, myLevelKey, myDBObject, myReference, myUsingGraph, mySecurityToken, myTransactionToken)); #endregion } else { Attributes.Item2.Add(alias, GetNotResolvedReferenceEdgeAttributeValue((IEnumerable<IVertex>)res.Value)); } #endregion } else if (res.Value is IVertexView) { //the result is one or multiple 'paths' if ((res.Value as IVertexView).HasEdge("path")) { var pathHyperEdge = (res.Value as IVertexView).GetAllHyperEdges().First(); if (!String.IsNullOrWhiteSpace(attrSel.Alias)) { Attributes.Item2.Add(attrSel.Alias, pathHyperEdge.Edge); } else Attributes.Item2.Add(pathHyperEdge.EdgeName, pathHyperEdge.Edge); } } else { Attributes.Item1.Add(alias, res.Value); } #endregion #endregion } else if (attrSel.Element is UnstructuredProperty) { #region undefined attribute selection var undef_alias = attrSel.Alias; if (!Attributes.Item1.ContainsKey(undef_alias)) { Object attrValue = null; if (myDBObject.HasUnstructuredProperty(undef_alias)) { Attributes.Item1.Add(undef_alias, attrValue); } } #endregion } else { #region Attribute selection minDepth = (attrSel.RelatedIDChainDefinition != null) ? attrSel.RelatedIDChainDefinition.Edges.Count - 1 : 0; //var alias = (attrSel.Alias == null) ? (attrSel.Element as TypeAttribute).Name : attrSel.Alias; Depth = GetDepth(myDepth, minDepth, myDBType, attrSel.Element); Object attrValue = null; if (GetAttributeValueAndResolve(mySecurityToken, myTransactionToken, myDBType, attrSel, myDBObject, Depth, myLevelKey, myReference, myUsingGraph, out attrValue)) { if (attrValue is IEdgeView) { Attributes.Item2.Add(alias, (IEdgeView)attrValue); } else { Attributes.Item1.Add(alias, attrValue); } } #endregion } #endregion } } return Attributes; }