/// <summary> /// Processes the node references to calculate all relevant properties. Must be called after finishing import of all the parent models. /// </summary> /// <param name="nodeFactory">The node container.</param> /// <param name="traceEvent">A delegate <see cref="Action{TraceMessage}"/> encapsulates an action to report any errors and trace processing progress.</param> internal void CalculateNodeReferences(INodeFactory nodeFactory, Action <TraceMessage> traceEvent) { m_ModelingRule = new Nullable <ModelingRules>(); List <UAReferenceContext> _children = new List <UAReferenceContext>(); Dictionary <string, UANodeContext> _derivedChildren = null; foreach (UAReferenceContext _rfx in m_AddressSpaceContext.GetMyReferences(this)) { switch (_rfx.ReferenceKind) { case ReferenceKindEnum.Custom: XmlQualifiedName _ReferenceType = _rfx.GetReferenceTypeName(traceEvent); if (_ReferenceType == XmlQualifiedName.Empty) { BuildError _err = BuildError.DanglingReferenceTarget; traceEvent(TraceMessage.BuildErrorTraceMessage(_err, "Information")); } IReferenceFactory _or = nodeFactory.NewReference(); _or.IsInverse = !_rfx.Reference.IsForward; _or.ReferenceType = _ReferenceType; _or.TargetId = _rfx.BrowsePath(traceEvent); break; case ReferenceKindEnum.HasComponent: if (_rfx.SourceNodeContext == this) { _children.Add(_rfx); } break; case ReferenceKindEnum.HasProperty: if ((_rfx.SourceNodeContext == this) && (!(_rfx.SourceNodeContext.UANode is UADataType) || _rfx.TargetNodeContext.UANode.BrowseName.CompareTo("EnumStrings") != 0)) { _children.Add(_rfx); } break; case ReferenceKindEnum.HasModellingRule: m_ModelingRule = _rfx.GetModelingRule(); break; case ReferenceKindEnum.HasSubtype: //TODO Part 3 7.10 HasSubtype - add test cases #35 m_BaseTypeNode = _rfx.SourceNodeContext; break; case ReferenceKindEnum.HasTypeDefinition: //Recognize problems with P3.7.13 HasTypeDefinition ReferenceType #39 m_BaseTypeNode = _rfx.TargetNodeContext; _derivedChildren = _rfx.TargetNodeContext.GetDerivedChildren(); Debug.Assert(!IsProperty, "Has property "); m_IsProperty = _rfx.TargetNodeContext.IsPropertyVariableType; break; } } _children = _children.Where <UAReferenceContext>(x => _derivedChildren == null || !_derivedChildren.ContainsKey(x.TargetNodeContext.m_BrowseName.Name)).ToList <UAReferenceContext>(); foreach (UAReferenceContext _rc in _children) { Validator.ValidateExportNode(_rc.TargetNodeContext, nodeFactory, _rc, traceEvent); } }
private static void CreateModelDesignStub(INodeContainer factory) { BuildError _err = BuildError.DanglingReferenceTarget; IPropertyInstanceFactory _pr = factory.AddNodeFactory <IPropertyInstanceFactory>(); _pr.SymbolicName = new XmlQualifiedName(string.Format("{0}{1}", _err.Focus.ToString(), m_ErrorNumber++), "http://commsvr.com/OOIUA/SemanticData/UANodeSetValidation"); _pr.AddDescription("en-en", _err.Descriptor); _pr.AddDisplayName("en-en", string.Format("ERROR{0}", m_ErrorNumber)); }
/// <summary> /// Validates <paramref name="nodeContext"/> and exports it using an object of <see cref="IModelFactory"/> type. /// </summary> /// <param name="nodeContext">The node context to be validated and exported.</param> /// <param name="exportFactory">A model export factory.</param> /// <param name="parentReference">The reference to parent node.</param> /// <param name="traceEvent">The trace event.</param> /// <returns>An object of <see cref="INodeFactory"/>.</returns> internal static void ValidateExportNode(IUANodeBase nodeContext, INodeContainer exportFactory, UAReferenceContext parentReference, Action <TraceMessage> traceEvent) { Debug.Assert(nodeContext != null, "Validator.ValidateExportNode the argument nodeContext is null."); //TODO Handle HasComponent ReferenceType errors. #42 if (nodeContext.UANode == null) { string _msg = string.Format("The node {0} is undefined", nodeContext.NodeIdContext); BuildError _be = null; if (parentReference == null || parentReference.ReferenceKind == ReferenceKindEnum.HasProperty) { _be = BuildError.UndefinedHasPropertyTarget; } else { _be = BuildError.UndefinedHasComponentTarget; } TraceMessage _traceMessage = TraceMessage.BuildErrorTraceMessage(_be, _msg); traceEvent(_traceMessage); CreateModelDesignStub(exportFactory); } else { string nodeType = nodeContext.UANode.GetType().Name; switch (nodeType) { case "UAReferenceType": CreateNode <IReferenceTypeFactory, UAReferenceType>(exportFactory.AddNodeFactory <IReferenceTypeFactory>, nodeContext, (x, y) => Update(x, y, traceEvent), UpdateType, traceEvent); break; case "UADataType": CreateNode <IDataTypeFactory, UADataType>(exportFactory.AddNodeFactory <IDataTypeFactory>, nodeContext, (x, y) => Update(x, y, nodeContext.UAModelContext, traceEvent), UpdateType, traceEvent); break; case "UAVariableType": CreateNode <IVariableTypeFactory, UAVariableType>(exportFactory.AddNodeFactory <IVariableTypeFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, traceEvent), UpdateType, traceEvent); break; case "UAObjectType": CreateNode <IObjectTypeFactory, UAObjectType>(exportFactory.AddNodeFactory <IObjectTypeFactory>, nodeContext, Update, UpdateType, traceEvent); break; case "UAView": CreateNode <IViewInstanceFactory, UAView>(exportFactory.AddNodeFactory <IViewInstanceFactory>, nodeContext, (x, y) => Update(x, y, traceEvent), UpdateInstance, traceEvent); break; case "UAMethod": CreateNode <IMethodInstanceFactory, UAMethod>(exportFactory.AddNodeFactory <IMethodInstanceFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, parentReference, traceEvent), UpdateInstance, traceEvent); break; case "UAVariable": if (parentReference == null || parentReference.ReferenceKind == ReferenceKindEnum.HasProperty) { CreateNode <IPropertyInstanceFactory, UAVariable>(exportFactory.AddNodeFactory <IPropertyInstanceFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, parentReference, traceEvent), UpdateInstance, traceEvent); } else { CreateNode <IVariableInstanceFactory, UAVariable>(exportFactory.AddNodeFactory <IVariableInstanceFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, parentReference, traceEvent), UpdateInstance, traceEvent); } break; case "UAObject": CreateNode <IObjectInstanceFactory, UAObject>(exportFactory.AddNodeFactory <IObjectInstanceFactory>, nodeContext, (x, y) => Update(x, y, traceEvent), UpdateInstance, traceEvent); break; default: Debug.Assert(false, "Wrong node type"); break; } } }
/// <summary> /// Processes the node references to calculate all relevant properties. Must be called after finishing import of all the parent models. /// </summary> /// <param name="nodeFactory">The node container.</param> /// <param name="validator">The validator.</param> /// <exception cref="ArgumentNullException"><paramref name="nodeFactory"/> must not be null.</exception> void IUANodeBase.CalculateNodeReferences(INodeFactory nodeFactory, IValidator validator) { if (nodeFactory == null) { throw new ArgumentNullException(nameof(nodeFactory), $"{nodeFactory} must not be null in {nameof(IUANodeBase.CalculateNodeReferences)}"); } if (validator is null) { throw new ArgumentNullException(nameof(validator), $"{nameof(validator)} must not be null in {nameof(IUANodeBase.CalculateNodeReferences)}"); } List <UAReferenceContext> _children = new List <UAReferenceContext>(); foreach (UAReferenceContext _rfx in m_AddressSpaceContext.GetMyReferences(this)) { switch (_rfx.ReferenceKind) { case ReferenceKindEnum.Custom: XmlQualifiedName _ReferenceType = _rfx.GetReferenceTypeName(); if (_ReferenceType == XmlQualifiedName.Empty) { BuildError _err = BuildError.DanglingReferenceTarget; Log.TraceEvent(TraceMessage.BuildErrorTraceMessage(_err, "Information")); } IReferenceFactory _or = nodeFactory.NewReference(); _or.IsInverse = !_rfx.Reference.IsForward; _or.ReferenceType = _ReferenceType; _or.TargetId = _rfx.BrowsePath(); break; case ReferenceKindEnum.HasComponent: if (_rfx.SourceNode == this) { _children.Add(_rfx); } break; case ReferenceKindEnum.HasProperty: if ((_rfx.SourceNode == this) && (_rfx.SourceNode.UANode.NodeClassEnum != NodeClassEnum.UADataType)) { _children.Add(_rfx); } break; case ReferenceKindEnum.HasModellingRule: break; case ReferenceKindEnum.HasSubtype: break; case ReferenceKindEnum.HasTypeDefinition: //Recognize problems with P3.7.13 HasTypeDefinition ReferenceType #39 IsProperty = _rfx.TargetNode.IsPropertyVariableType; break; } } Dictionary <string, IUANodeBase> _derivedChildren = m_BaseTypeNode == null ? new Dictionary <string, IUANodeBase>() : m_BaseTypeNode.GetDerivedInstances(); foreach (UAReferenceContext _rc in _children) { try { IUANodeBase _instanceDeclaration = null; if (!string.IsNullOrEmpty(_rc.TargetNode.BrowseName.Name)) { _instanceDeclaration = _derivedChildren.ContainsKey(_rc.TargetNode.BrowseName.Name) ? _derivedChildren[_rc.TargetNode.BrowseName.Name] : null; } if (_rc.TargetNode.Equals(_instanceDeclaration)) { continue; } _rc.TargetNode.RemoveInheritedValues(_instanceDeclaration); validator.ValidateExportNode(_rc.TargetNode, nodeFactory, _rc); } catch (Exception) { throw; } } }
/// <summary> /// Validates <paramref name="nodeContext" /> and exports it using an object of <see cref="IModelFactory" /> type. /// </summary> /// <param name="nodeContext">The node context to be validated and exported.</param> /// <param name="exportFactory">A model export factory.</param> /// <param name="parentReference">The reference to parent node.</param> /// <exception cref="ApplicationException">In {nameof(ValidateExportNode)}</exception> public void ValidateExportNode(IUANodeBase nodeContext, INodeContainer exportFactory, UAReferenceContext parentReference) { Debug.Assert(nodeContext != null, "Validator.ValidateExportNode the argument nodeContext is null."); //TODO Handle HasComponent ReferenceType errors. #42 if (Object.ReferenceEquals(nodeContext.UANode, null)) { string _msg = string.Format("The node {0} is undefined", nodeContext.NodeIdContext); BuildError _be = null; if (parentReference == null || parentReference.ReferenceKind == ReferenceKindEnum.HasProperty) { _be = BuildError.UndefinedHasPropertyTarget; } else { _be = BuildError.UndefinedHasComponentTarget; } TraceMessage _traceMessage = TraceMessage.BuildErrorTraceMessage(_be, _msg); Log.TraceEvent(_traceMessage); CreateModelDesignStub(exportFactory); } else { switch (nodeContext.UANode.NodeClassEnum) { case NodeClassEnum.UADataType: CreateNode <IDataTypeFactory, UADataType>(exportFactory.AddNodeFactory <IDataTypeFactory>, nodeContext, (x, y) => Update(x, y), UpdateType); break; case NodeClassEnum.UAMethod: CreateNode <IMethodInstanceFactory, UAMethod>(exportFactory.AddNodeFactory <IMethodInstanceFactory>, nodeContext, (x, y) => Update(x, y, parentReference), UpdateInstance); break; case NodeClassEnum.UAObject: CreateNode <IObjectInstanceFactory, UAObject>(exportFactory.AddNodeFactory <IObjectInstanceFactory>, nodeContext, (x, y) => Update(x, y), UpdateInstance); break; case NodeClassEnum.UAObjectType: CreateNode <IObjectTypeFactory, UAObjectType>(exportFactory.AddNodeFactory <IObjectTypeFactory>, nodeContext, Update, UpdateType); break; case NodeClassEnum.UAReferenceType: CreateNode <IReferenceTypeFactory, UAReferenceType>(exportFactory.AddNodeFactory <IReferenceTypeFactory>, nodeContext, (x, y) => Update(x, y), UpdateType); break; case NodeClassEnum.UAVariable: if (parentReference.ReferenceKind == ReferenceKindEnum.HasProperty) { CreateNode <IPropertyInstanceFactory, UAVariable>(exportFactory.AddNodeFactory <IPropertyInstanceFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, parentReference), UpdateInstance); } else { CreateNode <IVariableInstanceFactory, UAVariable>(exportFactory.AddNodeFactory <IVariableInstanceFactory>, nodeContext, (x, y) => Update(x, y, nodeContext, parentReference), UpdateInstance); } break; case NodeClassEnum.UAVariableType: CreateNode <IVariableTypeFactory, UAVariableType>(exportFactory.AddNodeFactory <IVariableTypeFactory>, nodeContext, (x, y) => Update(x, y), UpdateType); break; case NodeClassEnum.UAView: CreateNode <IViewInstanceFactory, UAView>(exportFactory.AddNodeFactory <IViewInstanceFactory>, nodeContext, (x, y) => Update(x, y), UpdateInstance); break; case NodeClassEnum.Unknown: throw new ApplicationException($"In {nameof(ValidateExportNode)} unexpected NodeClass value"); } } }
/// <summary> /// creates new <see cref="TraceMessage" /> to be used for diagnostic purpose /// </summary> /// <param name="error">The <see cref="BuildError"/> to be added to the <see cref="TraceMessage"/>.</param> /// <param name="message">The new <see cref="TraceMessage" /> containing the <paramref name="message" />.</param> /// <returns>The new <see cref="TraceMessage" /> diagnostic message.</returns> public static TraceMessage BuildErrorTraceMessage(BuildError error, string message) { return new TraceMessage(error, TraceEventType.Information, message); }
private TraceMessage(BuildError buildError, TraceEventType traceLevel, string message) { BuildError = buildError; TraceLevel = traceLevel; Message = message; }
/// <summary> /// Returns a <see cref="System.String" /> that represents this instance. /// </summary> /// <returns>A <see cref="System.String" /> that represents this instance.</returns> public override string ToString() { return(String.Format("Trace: {0}, Error {1} {2}", TraceLevel, BuildError.ToString(), Message)); }
/// <summary> /// creates new <see cref="TraceMessage" /> to be used for diagnostic purpose /// </summary> /// <param name="error">The <see cref="BuildError"/> to be added to the <see cref="TraceMessage"/>.</param> /// <param name="message">The new <see cref="TraceMessage" /> containing the <paramref name="message" />.</param> /// <returns>The new <see cref="TraceMessage" /> diagnostic message.</returns> public static TraceMessage BuildErrorTraceMessage(BuildError error, string message) { return(new TraceMessage(error, TraceEventType.Information, message)); }