public bool IsSupportedMutation(string nodeName, NodeMutationType mutation) { string mutationPrefix = string.Empty; switch (mutation) { case NodeMutationType.Create: mutationPrefix = "Create"; break; case NodeMutationType.Update: mutationPrefix = "Update"; break; case NodeMutationType.Delete: mutationPrefix = "Delete"; break; } var mutationName = mutationPrefix + nodeName; if (_schemaCache == null) { _schemaCache = GetSchema(); } var mutationField = _schemaCache.GetMutations(nodeName).FirstOrDefault(m => m.Name == mutationName); return(mutationField != null); }
/// <summary> /// Get a dictionary of paramters and values which match those required by the node type /// defined in the schema /// </summary> /// <param name="node"></param> /// <param name="elm"></param> /// <param name="clientMapping"></param> /// <returns></returns> public static Dictionary <string, object> GetNodePropsWithElementProps(Node node, Element elm, IBuildingGraphSchema schema, BuildingGraphMapping clientMapping, bool includeOnlyMappedFields) { var elmParms = node.GetAllProperties(); if (elm != null && elm.Location is LocationPoint) { var lpt = (elm.Location as LocationPoint); var insPt = lpt.Point; if (!elmParms.ContainsKey("Location")) { elmParms.Add("Location", insPt.ToBuildingGraph()); } //if (!elmParms.ContainsKey("LocationRotation")) elmParms.Add("LocationRotation", lpt.Rotation); } else if (elm != null && elm.Location is LocationCurve) { //just start and end points for now var asCurve = (elm.Location as LocationCurve).Curve; var insPt = asCurve.GetEndPoint(0); if (!elmParms.ContainsKey("Location")) { elmParms.Add("Location", insPt.ToBuildingGraph()); } var endPt = asCurve.GetEndPoint(1); if (!elmParms.ContainsKey("LocationEnd")) { elmParms.Add("LocationEnd", endPt.ToBuildingGraph()); } var length = asCurve.Length; if (!elmParms.ContainsKey("length")) { elmParms.Add("Length", length); } var slope = Math.Abs(endPt.Z - insPt.Z) / length; if (!elmParms.ContainsKey("slope")) { elmParms.Add("slope", length); } } IBuildingGraphType bqType = schema != null?schema.GetBuildingGraphType(node.Label) : null; BuildingGraphMappedType clType = clientMapping != null?clientMapping.Types.FirstOrDefault(ct => ct.Name == node.Label) : null; foreach (var param in elm.Parameters.OfType <Parameter>()) { var hp = new HLRevitParameter(param); var paramName = Utils.GetGraphQLCompatibleFieldName(param.Definition.Name); var val = RevitToGraphValue(hp); if (bqType != null && clientMapping != null) { //resolve mapped field name if present if (clType != null) { var mappedFielName = clType.ValueMap.FirstOrDefault(vm => vm.Value == paramName); if (mappedFielName.Value == paramName) { paramName = mappedFielName.Key; } } var paramField = bqType.Fields.FirstOrDefault(fb => fb.Name == paramName); if (includeOnlyMappedFields && paramField == null) { continue; } //attempt to convert units if (val is double) { var fieldUnit = paramField.Args.FirstOrDefault(arg => arg.Name == "unit"); if (fieldUnit == null) { continue; } //var fieldUnitType = schema.GetBuildingGraphType(fieldUnit.TypeName); var unitMapping = clientMapping.Types.FirstOrDefault(tp => tp.Name == fieldUnit.TypeName); var defaultValue = fieldUnit.DefaultValue != null?fieldUnit.DefaultValue.ToString() : string.Empty; if (unitMapping != null && unitMapping.ValueMap.ContainsKey(fieldUnit.DefaultValue.ToString())) { var revitValue = unitMapping.ValueMap[defaultValue]; DisplayUnitType revitUnitTypeEnum; if (Enum.TryParse(revitValue, out revitUnitTypeEnum)) { //var type = Type.GetType(unitMapping.NativeType);// "Namespace.MyClass, MyAssembly"); val = UnitUtils.ConvertFromInternalUnits((double)val, revitUnitTypeEnum); } } } } if (!elmParms.ContainsKey(paramName)) { elmParms.Add(paramName, val); } } return(elmParms); }
private void MutateRelationship(PendingNode fromNodeId, PendingNode toNodeId, string relTypeName, Dictionary <string, object> variables, string rMutType) { if (_schemaCache == null) { _schemaCache = GetSchema(); } //basic name pattern match, nothing fancy... could use mapping in JSON file but keep it simple for now var mutations = _schemaCache.GetMutations();// toNodeId.NodeName); //var relTypeName = relType.ToString(); var mutationName = $"{rMutType}_{fromNodeId.NodeName}_{relTypeName}_{toNodeId.NodeName}"; var mutationField = mutations.FirstOrDefault(m => m.Name == mutationName); //find matching interfaces? just support for AbstractElement for now var toNodeType = _schemaCache.GetBuildingGraphType(toNodeId.NodeName); var fromNodeType = _schemaCache.GetBuildingGraphType(fromNodeId.NodeName); if (mutationField == null) { foreach (var toNodInf in toNodeType.Interfaces) { //var toNodInf = toNodeType.Interfaces.FirstOrDefault(); foreach (var fromNodInf in fromNodeType.Interfaces) { //var fromNodInf = fromNodeType.Interfaces.FirstOrDefault(); if (mutationField == null && !string.IsNullOrEmpty(fromNodInf)) { mutationName = $"{rMutType}_{fromNodInf}_{relTypeName}_{toNodeId.NodeName}"; mutationField = mutations.FirstOrDefault(m => m.Name == mutationName); } if (mutationField == null && !string.IsNullOrEmpty(toNodInf)) { mutationName = $"{rMutType}_{fromNodeId.NodeName}_{relTypeName}_{toNodInf}"; mutationField = mutations.FirstOrDefault(m => m.Name == mutationName); } if (mutationField == null && !string.IsNullOrEmpty(fromNodInf) && !string.IsNullOrEmpty(toNodInf)) { mutationName = $"{rMutType}_{fromNodInf}_{relTypeName}_{toNodInf}"; mutationField = mutations.FirstOrDefault(m => m.Name == mutationName); } if (mutationField != null) { break; } } if (mutationField != null) { break; } } } var mutationArgs = variables != null ? new Dictionary <string, object>(variables) : new Dictionary <string, object>(); mutationArgs.Add("fromId", fromNodeId); mutationArgs.Add("toId", toNodeId); //mutationArgs.Add("MutationDateTime", ""); //mutationArgs.Add("MutationUser", ""); if (mutationField != null) { MutationRequest mr = new MutationRequest(mutationField, toNodeId, mutationArgs); _mutationRelateQueue.Enqueue(mr); } else { throw new Exception("No supported mutations for " + relTypeName); } }
/// <summary> /// Adds or Updates a node in the graph /// </summary> /// <param name="node">The node to add/update</param> /// <param name="variables">Variables to add/update for this node</param> /// <param name="mergeOn">To update a node, add Ids or other identifying variables to match the existing node. Leave null to create a new node.</param> /// <returns>The pending node which can be used to relate it to other pending nodes</returns> public PendingNode Push(string nodeName, Dictionary <string, object> variables, Dictionary <string, object> mergeOn) { //find create mutation //find parameters //translate values? //map node name to GrapgQL type BuildingGraphMappedType mappedType = null; if (_clientMapping != null) { mappedType = _clientMapping.Types.FirstOrDefault(t => t.NativeType == nodeName); } var IsUpdate = (mergeOn != null); var mutationPrefix = IsUpdate ? "Update" : "Create"; var mutationName = mutationPrefix + nodeName; if (_schemaCache == null) { _schemaCache = GetSchema(); } var mutationField = _schemaCache.GetMutations(nodeName).FirstOrDefault(m => m.Name == mutationName); if (mutationField == null) { return(new PendingNode(nodeName)); // throw new Exception("Unknown mutation type: " + mutationName); } //map node variable name to GraphQL variable name Dictionary <string, object> mutationArgs = null; if (mappedType == null) { mutationArgs = new Dictionary <string, object>(variables); } else { mutationArgs = new Dictionary <string, object>(variables); } if (IsUpdate) { //find matching id arguments for merge operation var mergeArgs = mutationField.Args.Where(arg => arg.TypeName == "ID!" && mergeOn.ContainsKey(arg.Name)); foreach (var marg in mergeArgs) { if (!mutationArgs.ContainsKey(marg.Name)) { mutationArgs.Add(marg.Name, mergeOn[marg.Name]); } } } var pn = new PendingNode(nodeName); MutationRequest mr = new MutationRequest(mutationField, pn, mutationArgs) { ReturnFields = "Id" }; _mutationPushQueue.Enqueue(mr); return(pn); }
public IBuildingGraphSchema GetSchema() { var schema = ExecuteQuery(@" { __schema { types { interfaces { name } kind name description fields { name description type { name kind ofType{ name } } args{ name defaultValue type{ name kind ofType{ name } } } } enumValues{ name description } } } }", null); if (schema is Exception) { throw new Exception("There was an error querying the API", (schema as Exception)); } IBuildingGraphSchema bdSchema = null; try { if (schema == null || schema.__schema == null) { throw new Exception("Error querying schema " + (schema is string?schema: string.Empty)); } bdSchema = new BuildingGraphSchema(schema.__schema); } catch (Exception ex) { throw new Exception("There was an error querying the API", ex); } return(bdSchema); }