/// <summary> /// Graph object <paramref name="o"/> onto stream <paramref name="s"/> /// </summary> /// <param name="s">The stream to graph to</param> /// <param name="o">The object to graph to</param> public ResultCode GraphObject(System.IO.Stream s, MARC.Everest.Interfaces.IGraphable o) { var result = Graph(s, o); this.Details = result.Details; return(result.Code); }
/// <summary> /// Send a request to the remote endpoint with the specified message headers /// </summary> /// <param name="data">The data to be sent to the remote endpoint</param> /// <param name="headers">The SOAP headers to append to the request</param> /// <returns>A <see cref="T:MARC.Everest.Connectors.WCF.WcfSendResult"/> instance containing the result of the send operation</returns> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data, MessageHeaders headers) { //TODO: Convert this into a method call for reuability. // Formatter check if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Create the work that will perform the operations Worker w = new Worker(); w.Formatter = (IXmlStructureFormatter)Formatter; #if WINDOWS_PHONE w.Actions = this.m_actions; #else w.WcfConfiguration = wcfConfiguration; #endif w.MessageVersion = wcfClient.Endpoint.Binding.MessageVersion; w.CustomHeaders = headers; // Work w.WorkSend(data); // Send over the channel if (w.SendResult.Code == ResultCode.Accepted || w.SendResult.Code == ResultCode.AcceptedNonConformant) { lock (results) results.Add(w.SendResult, wcfClient.ProcessInboundMessage(w.SendResult.Message)); } // Return the result return(w.SendResult); }
/// <summary> /// Send a response back to the remote endpoint. /// </summary> /// <param name="data">The data to send back.</param> /// <param name="correlate">The result to correlate this response with.</param> /// <returns>A send result structure that details the result of the send operation.</returns> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data, IReceiveResult correlate) { if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } Worker w = new Worker(); var cresult = correlate as WcfReceiveResult; w.MessageId = cresult.MessageIdentifier; w.MessageVersion = cresult.MessageVersion; // Prepare w.Formatter = (IXmlStructureFormatter)Formatter; w.ResponseHeaders = cresult.ResponseHeaders; w.InvalidResponse = InvalidResponse; w.WorkSend(data); // Work // Publish so WCF connector can send a result lock (results) results.Add(w.MessageId, w.SendResult); // Notify PublishResult(w.MessageId); // Return result return(w.SendResult); }
/// <summary> /// Send the structure <paramref name="data"/> to the file system. /// </summary> /// <param name="data">The <see cref="MARC.Everest.Interfaces.IGraphable"/> data to be sent.</param> /// <returns>The result of the send operation.</returns> /// <example> /// Get the result of a send operation /// <code> /// FileSendResult result = conn.Send(instance); /// if(result.Code != ResultCode.Accepted) // Result was not successful /// foreach(IResultDetail dtl in result.Details) /// Console.WriteLine(dtl.Message); /// </code> /// </example> /// <seealso cref="BeginSend"/> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data) { if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Setup the Worker Worker w = new Worker(); w.Formatter = (IStructureFormatter)this.Formatter.Clone(); w.TargetFile = GenerateTargetFile(data); w.Work(data); return(w.Result); }
public IAsyncResult BeginSend(MARC.Everest.Interfaces.IGraphable data, IReceiveResult correlate, AsyncCallback callback, object state) { // Formatter check if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Setup wroker Worker w = new Worker(); // Create a new instance of the formatter w.Formatter = (IXmlStructureFormatter)Formatter; var cresult = correlate as WcfReceiveResult; w.MessageId = (correlate as WcfReceiveResult).MessageIdentifier; w.MessageVersion = (correlate as WcfReceiveResult).MessageVersion; w.InvalidResponse = InvalidResponse; w.ResponseHeaders = cresult.ResponseHeaders; // Set async result IAsyncResult Result = new SendResultAsyncResult(state, new AutoResetEvent(false)); // Completed delegate w.Completed += delegate(object Sender) { Worker sWorker = Sender as Worker; // Strong type sender // Lookup the result in the dictionary if (!asyncResults.ContainsKey(Result)) { lock (asyncResults) { asyncResults.Add(Result, sWorker.SendResult); } } (Result as SendResultAsyncResult).SetComplete(); // Set completed (Result.AsyncWaitHandle as AutoResetEvent).Set(); // send signal if (callback != null) { callback(Result); // callback } }; // Add to thread pool ThreadPool.QueueUserWorkItem(new WaitCallback(w.WorkSend), data); return(Result); }
/// <summary> /// Publish a message to the currently opened queue /// </summary> /// <param name="data">The data to publish to the queue</param> /// <returns>A <see cref="ISendResult"/> structure representing the result of the send operation </returns> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data) { if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Send Worker w = new Worker(); w.Formatter = Formatter.Clone() as IStructureFormatter; w.Queue = queue; // Perform the work w.Work(data); return(w.Result); }
/// <summary> /// Synchronous send operation /// </summary> /// <param name="data">The data to send</param> /// <returns>The result of the send operation</returns> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data) { // Good practice to check if the connector is open if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen, null); } // Create a new worker Worker w = new Worker(); // Always clone the current formatter w.Formatter = (IStructureFormatter)Formatter.Clone(); // Perform the work w.Work(data); return(w.Result); }
public IAsyncResult BeginSend(MARC.Everest.Interfaces.IGraphable data, AsyncCallback callback, object state) { // Formatter check if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Create the work that will perform the operations Worker w = new Worker(); w.Formatter = (IXmlStructureFormatter)Formatter; #if !WINDOWS_PHONE w.WcfConfiguration = wcfConfiguration; #endif w.MessageVersion = wcfClient.Endpoint.Binding.MessageVersion; // Result IAsyncResult result = new SendResultAsyncResult(state, new AutoResetEvent(false)); // Work w.Completed += new WaitCallback(delegate(object sender) { lock (results) results.Add((sender as Worker).SendResult, wcfClient.ProcessInboundMessage((sender as Worker).SendResult.Message)); lock (asyncResults) asyncResults.Add(result, (sender as Worker).SendResult); (result.AsyncWaitHandle as AutoResetEvent).Set(); if (callback != null) { callback(result); } }); ThreadPool.QueueUserWorkItem(w.WorkSend, data); // Return the result return(result); }
/// <summary> /// Starts an asynchronous send to the file system. /// </summary> /// <param name="data">The <see cref="MARC.Everest.Interfaces.IGraphable"/> data to be sent.</param> /// <param name="callback">The callback to execute when the send is complete.</param> /// <param name="state">An object representing state.</param> /// <returns>An instance of a callback pointer.</returns> /// <example> /// Sending an instance asynchronously using a wait handle /// <code> /// IAsyncResult sendResult = conn.BeginSend(instance, null, null); /// sendResult.AsyncWaitHandle.WaitOne(); // Wait for send to finish /// FileSendResult result = conn.EndSend(sendResult); /// if(result.Code != ResultCode.Accepted) // Result was not successful /// foreach(IResultDetail dtl in result.Details) /// Console.WriteLine(dtl.Message); /// </code> /// </example> /// <seealso cref="Send"/> public IAsyncResult BeginSend(MARC.Everest.Interfaces.IGraphable data, AsyncCallback callback, object state) { if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen); } // Setup wroker Worker w = new Worker(); // Create a new instance of the formatter w.Formatter = Formatter.Clone() as IStructureFormatter; w.TargetFile = GenerateTargetFile(data); // Set async result IAsyncResult Result = new SendResultAsyncResult(state, new AutoResetEvent(false)); // Completed delegate w.Completed += delegate(object Sender) { Worker sWorker = Sender as Worker; // Strong type sender // Lookup the result in the dictionary if (!asyncResults.ContainsKey(Result)) { lock (asyncResults) { asyncResults.Add(Result, sWorker.Result); } } (Result as SendResultAsyncResult).SetComplete(); // Set completed (Result.AsyncWaitHandle as AutoResetEvent).Set(); // send signal if (callback != null) { callback(Result); // callback } }; // Add to thread pool ThreadPool.QueueUserWorkItem(new WaitCallback(w.Work), data); return(Result); }
/// <summary> /// Asynchronous send operation /// </summary> /// <param name="data">The data being sent</param> /// <param name="callback">A callback to execute when the method is complete</param> /// <param name="state">A user state</param> /// <returns>An IAsyncResult representing the asynchronous operation</returns> public IAsyncResult BeginSend(MARC.Everest.Interfaces.IGraphable data, AsyncCallback callback, object state) { // Good practice to check if the connector is open if (!IsOpen()) { throw new ConnectorException(ConnectorException.MSG_INVALID_STATE, ConnectorException.ReasonType.NotOpen, null); } // Create a new worker Worker w = new Worker(); // Always clone the current formatter w.Formatter = (IStructureFormatter)Formatter.Clone(); // Create the async result IAsyncResult result = new SendResultAsyncResult(state, new AutoResetEvent(false)); // Set the callback w.Completed += new WaitCallback(delegate(object sender) { Worker sWorker = sender as Worker; // Set the result in the dictionary lock (this.results) this.results.Add(result, sWorker.Result); // Notify any listeners (result.AsyncWaitHandle as AutoResetEvent).Set(); if (callback != null) { callback(result); } }); // Execute ThreadPool.QueueUserWorkItem(w.Work, data); return(result); }
/// <summary> /// Start an asynchronous send operation /// </summary> /// <param name="data">The data to publish to the queue</param> /// <param name="callback">An <see cref="AsyncCallback"/> delegate to call when the operation is completed</param> /// <param name="state">An object representing user state</param> /// <returns>An <see cref="IAsyncResult"/> structure that represent the asynchronous method</returns> public IAsyncResult BeginSend(MARC.Everest.Interfaces.IGraphable data, AsyncCallback callback, object state) { throw new NotImplementedException(); }
/// <summary> /// Send a request to the remote endpoint. /// </summary> /// <param name="data">The IGraphable data to send.</param> public ISendResult Send(MARC.Everest.Interfaces.IGraphable data) { return(Send(data, null)); }
/// <summary> /// Validates the specified object /// </summary> public bool Validate(MARC.Everest.Interfaces.IGraphable o, string location, out MARC.Everest.Connectors.IResultDetail[] details) { List <IResultDetail> dtls = new List <IResultDetail>(10); bool isValid = true; // Null return bool if (o == null) { details = dtls.ToArray(); return(true); } PropertyInfo nullFlavorAttrib = o.GetType().GetProperty("NullFlavor"); if (nullFlavorAttrib != null && nullFlavorAttrib.GetValue(o, null) != null) { details = dtls.ToArray(); return(true); } // Scan property info for violations foreach (var pi in this.GetBuildProperties(o.GetType())) { if (pi.GetGetMethod().GetParameters().Length != 0) { dtls.Add(new NotImplementedResultDetail( ResultDetailType.Warning, String.Format("Could not validate '{0}' as the property is indexed", pi.Name), location )); continue; } object piValue = pi.GetValue(o, null); object[] propAttributes = pi.GetCustomAttributes(typeof(PropertyAttribute), true); if (propAttributes.Length > 0) { PropertyAttribute pa = propAttributes[0] as PropertyAttribute; if (pa.Conformance == PropertyAttribute.AttributeConformanceType.Mandatory && pi.PropertyType.GetInterface(typeof(IImplementsNullFlavor).FullName, false) != null && (piValue == null || (piValue as IImplementsNullFlavor).NullFlavor != null)) { isValid = false; dtls.Add(new MandatoryElementMissingResultDetail(ResultDetailType.Error, String.Format("Property {0} in {1} is marked mandatory and is either not assigned, or is assigned a null flavor. This is not permitted.", pi.Name, o.GetType().FullName), location)); } else if (pa.Conformance == PropertyAttribute.AttributeConformanceType.Populated && piValue == null) { isValid &= Host.CreateRequiredElements; dtls.Add(new RequiredElementMissingResultDetail(isValid ? ResultDetailType.Warning : ResultDetailType.Error, String.Format("Property {0} in {1} is marked 'populated' and isn't assigned (you must at minimum, assign a nullFlavor for this attribute)!", pi.Name, o.GetType().FullName), location)); } else if (pa.MinOccurs != 0) { int minOccurs = pa.MinOccurs, maxOccurs = pa.MaxOccurs < 0 ? Int32.MaxValue : pa.MaxOccurs; var piCollection = piValue as ICollection; if (piCollection != null && (piCollection.Count > maxOccurs || piCollection.Count < minOccurs)) { isValid = false; dtls.Add(new InsufficientRepetitionsResultDetail(ResultDetailType.Error, String.Format("Property {0} in {2} does not have enough elements in the list, need between {1} and {3} elements!", pi.Name, minOccurs, o.GetType().FullName, maxOccurs), location)); } } } } details = dtls.ToArray(); return(isValid); }
/// <summary> /// Graphs an object to the specified stream /// </summary> public void Graph(System.Xml.XmlWriter s, object o, MARC.Everest.Interfaces.IGraphable context, XmlIts1FormatterGraphResult resultContext) { ResultCode rc = ResultCode.Accepted; Type instanceType = o.GetType(); // Verify o is not null if (o == null) { throw new System.ArgumentNullException("o"); } // Attempt to get null flavor var nfp = o.GetType().GetProperty("NullFlavor"); bool isInstanceNull = false, isEntryPoint = false; if (nfp != null) { isInstanceNull = nfp.GetValue(o, null) != null; } // Interaction? object[] structureAttributes = instanceType.GetCustomAttributes(typeof(StructureAttribute), false); StructureAttribute structureAttribute = structureAttributes[0] as StructureAttribute; if (structureAttribute.StructureType == StructureAttribute.StructureAttributeType.Interaction) { isEntryPoint = true; s.WriteStartElement(structureAttribute.Name, structureAttribute.NamespaceUri); s.WriteAttributeString("ITSVersion", "XML_1.0"); // Add ITS version s.WriteAttributeString("xmlns", "xsi", null, XmlIts1Formatter.NS_XSI); } else if (structureAttribute.IsEntryPoint && (s is MARC.Everest.Xml.XmlStateWriter && (s as MARC.Everest.Xml.XmlStateWriter).ElementStack.Count == 0 || s.WriteState == System.Xml.WriteState.Start)) { isEntryPoint = true; if (isEntryPoint) { s.WriteStartElement(structureAttribute.Name, structureAttribute.NamespaceUri); s.WriteAttributeString("xmlns", "xsi", null, XmlIts1Formatter.NS_XSI); } } // Validate this.Host.ValidateHelper(s, o as IGraphable, this, resultContext); // Reflect the properties and ensure they are in the appropriate order List <PropertyInfo> buildProperties = GetBuildProperties(instanceType); // Attributes first foreach (var pi in buildProperties) { object[] propertyAttributes = pi.GetCustomAttributes(typeof(PropertyAttribute), false); object instance = pi.GetValue(o, null); if (propertyAttributes.Length == 1) // Not a choice { PropertyAttribute pa = propertyAttributes[0] as PropertyAttribute; // Validation Rule Change: We'll require the user to perform this // Is this a required attribute that is null? We'll set a null flavor if ((pa.Conformance == PropertyAttribute.AttributeConformanceType.Required || pa.Conformance == PropertyAttribute.AttributeConformanceType.Populated) && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Structural && pi.PropertyType.GetProperty("NullFlavor") != null && !pi.PropertyType.IsAbstract && pi.CanWrite) { var nullFlavorProperty = pi.PropertyType.GetProperty("NullFlavor"); // Locate the default property if (instance == null && Host.CreateRequiredElements && nullFlavorProperty != null) { ConstructorInfo ci = pi.PropertyType.GetConstructor(Type.EmptyTypes); instance = ci.Invoke(null); nullFlavorProperty.SetValue(instance, Util.FromWireFormat("NI", nullFlavorProperty.PropertyType), null); } } // Property type switch (pa.PropertyType) { case PropertyAttribute.AttributeAttributeType.Structural: if ((Host.Settings & SettingsType.SuppressNullEnforcement) == 0) { if (instance != null && !isInstanceNull) { s.WriteAttributeString(pa.Name, Util.ToWireFormat(instance)); } else if (isInstanceNull && pi.Name == "NullFlavor") { Host.WriteNullFlavorUtil(s, (IGraphable)instance); } } else if (instance != null) { if (instance != null && pi.Name == "NullFlavor") { Host.WriteNullFlavorUtil(s, (IGraphable)instance); } else if (instance != null) { s.WriteAttributeString(pa.Name, Util.ToWireFormat(instance)); } } break; default: // Instance is null if (instance == null) { continue; } else if (isInstanceNull && (Host.Settings & (SettingsType.SuppressNullEnforcement | SettingsType.SuppressXsiNil)) != 0) { resultContext.AddResultDetail(new FormalConstraintViolationResultDetail(ResultDetailType.Information, "The context is null however SuppressNullEnforcement and SuppressXsiNil are set, therefore elements will be graphed. This is not necessarily HL7v3 compliant", s.ToString(), null)); } else if (isInstanceNull) { continue; } // Impose flavors or code? if (pa.DefaultUpdateMode != MARC.Everest.DataTypes.UpdateMode.Unknown && pi.PropertyType.GetProperty("UpdateMode") != null && pi.PropertyType.GetProperty("UpdateMode").GetValue(instance, null) == null && (this.Host.Settings & SettingsType.AllowUpdateModeImposing) == SettingsType.AllowUpdateModeImposing) { pi.PropertyType.GetProperty("UpdateMode").SetValue(instance, Util.FromWireFormat(pa.DefaultUpdateMode, pi.PropertyType.GetProperty("UpdateMode").PropertyType), null); } if (pa.ImposeFlavorId != null && instance is IAny && (Host.Settings & SettingsType.AllowFlavorImposing) == SettingsType.AllowFlavorImposing) { (instance as IAny).Flavor = pa.ImposeFlavorId; } if (pa.SupplierDomain != null && instance is ICodedValue && (instance as ICodedSimple).CodeValue != null && (instance as ICodedValue).CodeSystem == null && (instance as IImplementsNullFlavor).NullFlavor == null && (Host.Settings & SettingsType.AllowSupplierDomainImposing) == SettingsType.AllowSupplierDomainImposing) { (instance as ICodedValue).CodeSystem = pa.SupplierDomain; } // Instance is graphable if (instance is IGraphable) { // Ensure the data is not empty if (instance is IColl && (instance as IColl).IsEmpty && (instance as IImplementsNullFlavor).NullFlavor == null) { continue; } Host.WriteElementUtil(s, pa.NamespaceUri, pa.Name, instance as IGraphable, pi.PropertyType, context, resultContext); } else if (instance is ICollection) { Type genType = pi.PropertyType.GetGenericArguments()[0]; foreach (object itm in (instance as ICollection)) { Host.WriteElementUtil(s, pa.NamespaceUri, pa.Name, itm as IGraphable, genType, context, resultContext); } } else { s.WriteElementString(pa.Name, instance.ToString()); } break; } } else if (propertyAttributes.Length > 1) // Choice { // Instance is null if (instance == null) { continue; } else if (isInstanceNull && (Host.Settings & (SettingsType.SuppressNullEnforcement | SettingsType.SuppressXsiNil)) != 0) { resultContext.AddResultDetail(new FormalConstraintViolationResultDetail(ResultDetailType.Information, "The context is null however SuppressNullEnforcement and SuppressXsiNil are set, therefore elements will be graphed. This is not necessarily HL7v3 compliant", s.ToString(), null)); } else if (isInstanceNull) { continue; } #if WINDOWS_PHONE PropertyAttribute formatAs = propertyAttributes.Find(cpa => (cpa as PropertyAttribute).Type == null) as PropertyAttribute; #else PropertyAttribute formatAs = Array.Find(propertyAttributes, cpa => (cpa as PropertyAttribute).Type == null) as PropertyAttribute; #endif // Search by type and interaction foreach (PropertyAttribute pa in propertyAttributes) { if (pa.Type != null && instance.GetType() == pa.Type && (context != null && context.GetType() == pa.InteractionOwner || (pa.InteractionOwner == null && formatAs == null))) { formatAs = pa; if (context == null || context.GetType() == formatAs.InteractionOwner) { break; } } } // Slow check if (formatAs == null && (this.Host.Settings & SettingsType.AlwaysCheckForOverrides) != 0) { foreach (PropertyAttribute pa in propertyAttributes) { if (pa.Type != null && pa.Type.IsAssignableFrom(instance.GetType()) && (context != null && context.GetType() == pa.InteractionOwner || (pa.InteractionOwner == null && formatAs == null))) { formatAs = pa; if (context == null || context.GetType() == formatAs.InteractionOwner) { break; } } } } //if(formatAs == null) // try to find a regular choice // foreach(PropertyAttribute pa in propertyAttributes) // if (pa.Type != null && instance.GetType() == pa.Type) // { // formatAs = pa; // break; // } // Format if (formatAs == null) { resultContext.AddResultDetail(new NotSupportedChoiceResultDetail(ResultDetailType.Error, String.Format("Type {0} is not a valid choice according to available choice elements and won't be formatted", instance.GetType()), s.ToString(), null)); } else if (instance.GetType().GetInterface("MARC.Everest.Interfaces.IGraphable", false) != null) // Non Graphable { Host.WriteElementUtil(s, formatAs.NamespaceUri, formatAs.Name, (MARC.Everest.Interfaces.IGraphable)instance, formatAs.Type, context, resultContext); } else if (instance.GetType().GetInterface("System.Collections.IEnumerable", false) != null) // List { foreach (MARC.Everest.Interfaces.IGraphable ig in instance as IEnumerable) { Host.WriteElementUtil(s, formatAs.NamespaceUri, formatAs.Name, ig, instance.GetType(), context, resultContext); } } else // Not recognized { s.WriteElementString(formatAs.Name, formatAs.NamespaceUri, instance.ToString()); } } } // Is Entry point if (isEntryPoint) { s.WriteEndElement(); } }