/// <summary> /// The element <paramref name="myNewElement"/> is new if /// - it is not a special type 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 /// </summary> /// <param name="myExistingElement"></param> /// <param name="myNewElement"></param> /// <returns></returns> private Boolean IsNewSelectionElement(SelectionElement myExistingElement, SelectionElement myNewElement) { #region The existing is an asterisk and the new one is NOT a SpecialTypeAttribute if (myExistingElement.Selection == TypesOfSelect.Asterisk && !myNewElement.RelatedIDChainDefinition.IsSpecialTypeAttribute()) { return false; } #endregion #region The same level is already selected var item = myExistingElement; var selElem = myNewElement; if (item.Alias == selElem.Alias && // same depth or Undefined and one lower depth Friends.Undefined is Depth 1 and Friends.Age is Depth 2 but at the same selection level (item.RelatedIDChainDefinition.Depth == selElem.RelatedIDChainDefinition.Depth || (selElem.RelatedIDChainDefinition.IsUndefinedAttribute && item.RelatedIDChainDefinition.Depth == selElem.RelatedIDChainDefinition.Depth + 1)) ) { return false; } #endregion return true; }
/// <summary> Gets an attribute value - references will be resolved. </summary> /// /// <remarks> Stefan, 16.04.2010. </remarks> /// /// <param name="myType"> Type. </param> /// <param name="myTypeAttribute"> my type attribute. </param> /// <param name="myDBObject"> my database object. </param> /// <param name="myDepth"> Depth of my. </param> /// <param name="myLevelKey"> my level key. </param> /// <param name="reference"> The reference. </param> /// <param name="myUsingGraph"> true to my using graph. </param> /// <param name="attributeValue"> [out] The attribute value. </param> /// /// <returns> true if it succeeds, false if the DBO does not have the attribute. </returns> private Boolean GetAttributeValueAndResolve(GraphDBType myType, SelectionElement mySelectionelement, DBObjectStream myDBObject, Int64 myDepth, EdgeList myLevelKey, String reference, Boolean myUsingGraph, out Object attributeValue, String myUndefAttrName = null) { var typeAttribute = mySelectionelement.Element; if (typeAttribute.TypeCharacteristics.IsBackwardEdge) { #region IsBackwardEdge EdgeKey edgeKey = typeAttribute.BackwardEdgeDefinition; var contBackwardExcept = myDBObject.ContainsBackwardEdge(edgeKey, _DBContext, _DBContext.DBObjectCache, myType); if (contBackwardExcept.Failed()) throw new GraphDBException(contBackwardExcept.IErrors); if (contBackwardExcept.Value) { if (myDepth > 0) { var dbos = myDBObject.GetBackwardEdges(edgeKey, _DBContext, _DBContext.DBObjectCache, typeAttribute.GetDBType(_DBContext.DBTypeManager)); if (dbos.Failed()) throw new GraphDBException(dbos.IErrors); if (dbos.Value != null) { attributeValue = ResolveAttributeValue(typeAttribute, dbos.Value, myDepth, myLevelKey, myDBObject, reference, myUsingGraph); return true; } } else { attributeValue = GetNotResolvedBackwardEdgeReferenceAttributeValue(myDBObject, typeAttribute, edgeKey, myLevelKey, myUsingGraph, _DBContext); return true; } } #endregion } else if (myDBObject.HasAttribute(typeAttribute, _DBContext)) { #region SelectValueAssignment - kind of static assignment of selected attribute if (mySelectionelement.SelectValueAssignment != null && mySelectionelement.SelectValueAssignment.ValueAssignmentType == SelectValueAssignment.ValueAssignmentTypes.Always) { // Currently the prior add SelectionElement verifies that TermDefinition is always a ValueDefinition - if others will become valid this must be changed! attributeValue = (mySelectionelement.SelectValueAssignment.TermDefinition as ValueDefinition).Value.Value; return true; } #endregion #region ELSE (!IsBackwardEdge) #region not a reference attribute value if (!typeAttribute.IsUserDefinedType(_DBContext.DBTypeManager)) { var attrVal = myDBObject.GetAttribute(typeAttribute, myType, _DBContext); if (attrVal.Failed()) { throw new GraphDBException(attrVal.IErrors); } // currently, we do not want to return a ADBBaseObject but the real value if (attrVal.Value is ADBBaseObject) attributeValue = (attrVal.Value as ADBBaseObject).GetReadoutValue(); else if (attrVal.Value is IBaseEdge) attributeValue = (attrVal.Value as IBaseEdge).GetReadoutValues(); else attributeValue = attrVal.Value; return true; } #endregion #region ELSE Reference attribute value else { if (myDepth > 0) { var attrValue = myDBObject.GetAttribute(typeAttribute.UUID, myType, _DBContext); attributeValue = ResolveAttributeValue(typeAttribute, attrValue, myDepth, myLevelKey, myDBObject, reference, myUsingGraph); return true; } else { attributeValue = GetNotResolvedReferenceAttributeValue(myDBObject, typeAttribute, myType, myLevelKey, myUsingGraph, _DBContext); return true; } } #endregion #endregion } else if (mySelectionelement.SelectValueAssignment != null) { // Currently the prior add SelectionElement verifies that TermDefinition is always a ValueDefinition - if others will become valid this must be changed! attributeValue = (mySelectionelement.SelectValueAssignment.TermDefinition as ValueDefinition).Value.Value; return true; } attributeValue = null; return false; }
/// <summary> /// Adds the typeNode as an asterisk *, rhomb # or minus - or ad /// </summary> /// <param name="typeNode"></param> public Exceptional AddSelectionType(String myReference, GraphDBType myType, TypesOfSelect mySelType, TypeUUID myTypeID = null) { var selElem = new SelectionElement(mySelType, myTypeID); if (!_Selections.ContainsKey(myReference)) _Selections.Add(myReference, new Dictionary<EdgeList, List<SelectionElement>>()); var level = new EdgeList(new EdgeKey(myType.UUID, null)); if (!_Selections[myReference].ContainsKey(level)) _Selections[myReference].Add(level, new List<SelectionElement>()); if (!_Selections[myReference][level].Exists(item => item.Selection == mySelType)) { _Selections[myReference][level].Add(selElem); } return Exceptional.OK; }
/// <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 SelectionElementFunction(SelectionElement mySelectionElement, ChainPartFuncDefinition myFunction, List<AExpressionDefinition> myParameters) { this.Alias = mySelectionElement.Alias; this.EdgeList = mySelectionElement.EdgeList; this.Element = mySelectionElement.Element; this.Selection = mySelectionElement.Selection; this.IsGroupedOrAggregated = mySelectionElement.IsGroupedOrAggregated; this.LevelKey = mySelectionElement.LevelKey; this.RelatedIDChainDefinition = mySelectionElement.RelatedIDChainDefinition; Function = myFunction; Parameters = myParameters; }