/// <summary> /// Executes the function and return the result - for concatenated functions this will be done recursively /// </summary> /// <param name="mySelectionElementFunction"></param> /// <param name="myDBObject"></param> /// <param name="myCallingObject"></param> /// <param name="myDepth"></param> /// <param name="myReference"></param> /// <param name="myReferencedDBType"></param> /// <param name="myLevelKey"></param> /// <param name="myUsingGraph"></param> /// <returns></returns> private Exceptional<FuncParameter> ExecuteFunction(SelectionElementFunction mySelectionElementFunction, DBObjectStream myDBObject, IObject myCallingObject, Int64 myDepth, String myReference, GraphDBType myReferencedDBType, EdgeList myLevelKey, Boolean myUsingGraph) { #region Function if (myCallingObject == null) // DBObject does not have the attribute { if (mySelectionElementFunction.SelectValueAssignment != null) { return new Exceptional<FuncParameter>(new FuncParameter((mySelectionElementFunction.SelectValueAssignment.TermDefinition as ValueDefinition).Value)); } return null; } #region Get the FunctionNode and validate the Element var func = mySelectionElementFunction.Function; func.Function.CallingAttribute = mySelectionElementFunction.Element; if (mySelectionElementFunction.Element == null) { return null; } #endregion func.Function.CallingObject = myCallingObject; #region CallingDBObjectStream func.Function.CallingDBObjectStream = myDBObject; #endregion #region Execute the function var res = func.Execute(myReferencedDBType, myDBObject, myReference, _DBContext); if (res.Failed()) { return new Exceptional<FuncParameter>(res); } else { if (res.Value.Value == null) { return null; // no result for this object because of not set attribute value } if (mySelectionElementFunction.FollowingFunction != null) { return ExecuteFunction(mySelectionElementFunction.FollowingFunction, myDBObject, res.Value.Value, myDepth, myReference, myReferencedDBType, myLevelKey, myUsingGraph); } else { return res; } } #endregion #endregion }
/// <summary> /// Single IDNode selection attribute /// </summary> /// <param name="myReference"></param> /// <param name="myAlias"></param> /// <param name="myAStructureNode"></param> /// <param name="myGraphType"></param> public Exceptional AddElementToSelection(string myAlias, String myReference, IDChainDefinition myIDChainDefinition, Boolean myIsGroupedOrAggregated, SelectValueAssignment mySelectValueAssignment = null) { SelectionElement lastElem = null; var curLevel = new EdgeList(); EdgeList preLevel = null; if (myReference != null && _Selections.ContainsKey(myReference) && _Selections[myReference].Any(kv => kv.Value.Any(se => se.RelatedIDChainDefinition == myIDChainDefinition && se.Alias == myAlias))) { return new Exceptional(new Error_DuplicateAttributeSelection(myAlias)); } foreach (var nodeEdgeKey in myIDChainDefinition) { if (nodeEdgeKey is ChainPartTypeOrAttributeDefinition) { #region Usual attribute preLevel = null; var selElem = new SelectionElement(myAlias, curLevel, myIsGroupedOrAggregated, myIDChainDefinition); var typeOrAttr = (nodeEdgeKey as ChainPartTypeOrAttributeDefinition); if (true || typeOrAttr.DBType != null && typeOrAttr.TypeAttribute != null) { #region defined var edgeKey = typeOrAttr.EdgeKey; selElem.Element = typeOrAttr.TypeAttribute; //_DBContext.DBTypeManager.GetTypeAttributeByEdge(edgeKey); if (String.IsNullOrEmpty(selElem.Alias) || (nodeEdgeKey.Next != null && !(nodeEdgeKey.Next is ChainPartFuncDefinition))) { selElem.Alias = typeOrAttr.TypeAttribute.Name;//_DBContext.DBTypeManager.GetTypeAttributeByEdge(edgeKey).Name; } curLevel += edgeKey; preLevel = curLevel.GetPredecessorLevel(); #endregion } else { #region undefined attribute if (myIDChainDefinition.Level == 0) { preLevel = new EdgeList(myIDChainDefinition.LastType.UUID); } else { var element = _Selections[myReference].Last(); preLevel = curLevel.GetPredecessorLevel(); //preLevel = curLevel; } selElem.Alias = typeOrAttr.TypeOrAttributeName; selElem.Element = new UndefinedTypeAttribute(typeOrAttr.TypeOrAttributeName); #endregion } #region Add to _Selections if valid if (!_Selections.ContainsKey(myReference)) { _Selections.Add(myReference, new Dictionary<EdgeList, List<SelectionElement>>()); } if (!_Selections[myReference].ContainsKey(preLevel)) { _Selections[myReference].Add(preLevel, new List<SelectionElement>()); } /// /// Duplicate AttributeSelection is: "U.Name, U.Name" or "U.Name.TOUPPER(), U.Name" but not "U.Friends.TOP(1).Name, U.Friends.TOP(1).Age" if ((nodeEdgeKey.Next == null || (nodeEdgeKey.Next is ChainPartFuncDefinition && nodeEdgeKey.Next.Next == null)) // U.Name, U.Name U.Name.TOUPPER, U.Name && _Selections[myReference][preLevel].Exists(item => item.Alias == selElem.Alias && selElem.EdgeList.Level == item.EdgeList.Level && item.RelatedIDChainDefinition.Depth == selElem.RelatedIDChainDefinition.Depth && item.Element != null) && !myIsGroupedOrAggregated) { return new Exceptional(new Error_DuplicateAttributeSelection(selElem.Alias)); } // Do not add again if: // - it is a defined attribute and there is an asterisk selection at this level // - it is not the last part AND // - there is already an item of this part with the same alias and the same Depth if (nodeEdgeKey.Next == null || _Selections[myReference][preLevel].Count == 0 || _Selections[myReference][preLevel].Any(item => IsNewSelectionElement(item, selElem))) { _Selections[myReference][preLevel].Add(selElem); } #endregion lastElem = selElem; #endregion } else if (nodeEdgeKey is ChainPartFuncDefinition) { var chainPartFuncDefinition = (nodeEdgeKey as ChainPartFuncDefinition); #region Function if (myReference == null) { #region Type independent functions var selElem = new SelectionElement(myAlias, myIDChainDefinition); if (String.IsNullOrEmpty(selElem.Alias)) { selElem.Alias = chainPartFuncDefinition.SourceParsedString; } var funcElem = new SelectionElementFunction(selElem, chainPartFuncDefinition, chainPartFuncDefinition.Parameters); if (lastElem is SelectionElementFunction) { (lastElem as SelectionElementFunction).AddFollowingFunction(funcElem); lastElem = funcElem; } else { if (_SelectionElementsTypeIndependend.Any(se => se.Alias == funcElem.Alias)) { return new Exceptional(new Error_DuplicateAttributeSelection(funcElem.Alias)); } _SelectionElementsTypeIndependend.Add(funcElem); lastElem = funcElem; } #endregion } else { #region Type dependent function var funcElem = new SelectionElementFunction(lastElem, (nodeEdgeKey as ChainPartFuncDefinition), (nodeEdgeKey as ChainPartFuncDefinition).Parameters); funcElem.RelatedIDChainDefinition = myIDChainDefinition; if (!String.IsNullOrEmpty(myAlias) && nodeEdgeKey.Next == null) { funcElem.Alias = myAlias; } if (lastElem is SelectionElementFunction) { (lastElem as SelectionElementFunction).AddFollowingFunction(funcElem); lastElem = funcElem; } else if (_Selections[myReference][preLevel].Contains(lastElem)) { #region Add function to the last selection element (replace it) _Selections[myReference][preLevel].Remove(lastElem); //lastElem = new SelectionElementFunction(lastElem, (nodeEdgeKey as ChainPartFuncDefinition), (nodeEdgeKey as ChainPartFuncDefinition).Parameters); //lastElem.RelatedIDChainDefinition = myIDChainDefinition; //if (!String.IsNullOrEmpty(alias) && nodeEdgeKey.Next == null) //{ // lastElem.Alias = alias; //} lastElem = funcElem; if (!_Selections[myReference][preLevel].Contains(lastElem)) // In case this Element with func is already in the selection list do nothing. { _Selections[myReference][preLevel].Add(lastElem); } #endregion } else if (!_Selections[myReference][preLevel].Contains(funcElem)) { #region In this case we have a similar function but NOT THE SAME. Since we don't know what to do, return error. return new Exceptional(new Error_InvalidAttributeSelection(myIDChainDefinition.ContentString)); #endregion } #endregion } #endregion } } #region Set the SelectValueAssignment for the last element if (lastElem != null && mySelectValueAssignment != null) { #region Error handling System.Diagnostics.Debug.Assert(lastElem.Element != null); if (lastElem.Element.IsUserDefinedType(_DBContext.DBTypeManager)) { return new Exceptional(new Error_InvalidSelectValueAssignment(lastElem.Element.Name)); } if (!(mySelectValueAssignment.TermDefinition is ValueDefinition)) { return new Exceptional(new Error_NotImplemented(new System.Diagnostics.StackTrace(true))); } #endregion #region Validate datatype if the attribute is a defined attribute if (!(lastElem.Element is UndefinedTypeAttribute)) { if (!lastElem.Element.GetADBBaseObjectType(_DBContext.DBTypeManager).IsValidValue((mySelectValueAssignment.TermDefinition as ValueDefinition).Value.Value)) { return new Exceptional(new Error_SelectValueAssignmentDataTypeDoesNotMatch(lastElem.Element.GetADBBaseObjectType(_DBContext.DBTypeManager).ObjectName, (mySelectValueAssignment.TermDefinition as ValueDefinition).Value.ObjectName)); } var typedValue = new ValueDefinition(lastElem.Element.GetADBBaseObjectType(_DBContext.DBTypeManager).Clone((mySelectValueAssignment.TermDefinition as ValueDefinition).Value.Value)); mySelectValueAssignment.TermDefinition = typedValue; } #endregion lastElem.SelectValueAssignment = mySelectValueAssignment; } #endregion return Exceptional.OK; }
public void AddFollowingFunction(SelectionElementFunction myFollowingFunction) { var curFunc = this; while (curFunc.FollowingFunction != null) { curFunc = curFunc.FollowingFunction; } curFunc.FollowingFunction = myFollowingFunction; }