/// <summary> /// Creates an code expression for a coded value /// </summary> private string CreateCodeExpression(ICodedValue code) { StringBuilder expr = new StringBuilder(); // Represent as IHTSDO format expr.AppendFormat("{0}", Util.ToWireFormat(code.CodeValue)); //if (code.DisplayName != null) // expr.AppendFormat("|{0}|", code.DisplayName); return(expr.ToString()); }
/// <summary> /// Determines if this instance of CV is semantically equal to another /// </summary> public override BL SemanticEquals(IAny other) { var baseSem = base.SemanticEquals(other); if (!(bool)baseSem) { return(baseSem); } ICodedValue otherCv = other as ICodedValue; if (otherCv != null) // CS? If so call it's equality { return(otherCv.CodeSystem == null ? this.CodeSystem == null : otherCv.CodeSystem.Equals(this.CodeSystem)); } return(baseSem); }
/// <summary> /// Parse IHTSDO expression code /// </summary> private CD <String> ParseCodeExpression(string expression, ICodedValue context) { if (expression.StartsWith("(") && expression.EndsWith(")")) { expression = expression.Substring(1, expression.Length - 2); } else if (expression.StartsWith("(")) { throw new InvalidOperationException(); } Regex tokenReg = new Regex(@"^([0-9]+)[|]?(.*?)[|]?([:{])(.*)$"); var tokenMatch = tokenReg.Match(expression); if (!tokenMatch.Success) { return new CD <string>(expression, context.CodeSystem, context.CodeSystemName, context.CodeSystemVersion) { ValueSet = context.ValueSet, ValueSetVersion = context.ValueSetVersion } } ; // Create retVal CD <String> retVal = new CD <string>(tokenMatch.Groups[1].Value, context.CodeSystem, context.CodeSystemName, context.CodeSystemVersion) { DisplayName = String.IsNullOrEmpty(tokenMatch.Groups[2].Value) ? null : tokenMatch.Groups[2].Value, ValueSet = context.ValueSet, ValueSetVersion = context.ValueSetVersion }; // Determine how the qualifier is identified var qualifierExpression = tokenMatch.Groups[4].Value; if (tokenMatch.Groups[3].Value == "{") { qualifierExpression = "{" + qualifierExpression; } retVal.Qualifier = ParseCodeExpressionQualifier(qualifierExpression, retVal); return(retVal); }
/// <summary> /// Graph object <paramref name="o"/> onto stream <paramref name="s"/> /// </summary> /// <param name="s">The XmlWriter to graph to</param> /// <param name="o">The object to graph</param> public void Graph(System.Xml.XmlWriter s, object o, DatatypeFormatterGraphResult result) { // Get an instance ref ICodedValue instance_ics = (ICodedValue)o; // Do a base format CSFormatter baseFormatter = new CSFormatter(); baseFormatter.Graph(s, o, result); // Format the coded simple if (instance_ics.CodeSystem != null) { s.WriteAttributeString("codeSystem", Util.ToWireFormat(instance_ics.CodeSystem)); } if (instance_ics.CodeSystemName != null) { s.WriteAttributeString("codeSystemName", Util.ToWireFormat(instance_ics.CodeSystemName)); } if (instance_ics.CodeSystemVersion != null) { s.WriteAttributeString("codeSystemVersion", Util.ToWireFormat(instance_ics.CodeSystemVersion)); } if (instance_ics.DisplayName != null) { s.WriteAttributeString("displayName", Util.ToWireFormat(instance_ics.DisplayName)); } if (instance_ics.OriginalText != null) // Original Text { EDFormatter edFormatter = new EDFormatter(); s.WriteStartElement("originalText", "urn:hl7-org:v3"); edFormatter.Graph(s, instance_ics.OriginalText, result); s.WriteEndElement(); } if (!String.IsNullOrEmpty(instance_ics.ValueSet)) { result.AddResultDetail(new UnsupportedDatatypeR1PropertyResultDetail(ResultDetailType.Warning, "ValueSet", "CV", s.ToString())); } if (!String.IsNullOrEmpty(instance_ics.ValueSetVersion)) { result.AddResultDetail(new UnsupportedDatatypeR1PropertyResultDetail(ResultDetailType.Warning, "ValueSetVersion", "CV", s.ToString())); } }
/// <summary> /// Graph <paramref name="o"/> onto <paramref name="s"/> /// </summary> public void Graph(System.Xml.XmlWriter s, object o, DatatypeR2FormatterGraphResult result) { // Base formatter ANYFormatter baseFormatter = new ANYFormatter(); baseFormatter.Graph(s, o, result); // Next, start to format the properties ICodedSimple cs = o as ICodedSimple; ICodedValue cv = o as ICodedValue; ICodedEquivalents ce = o as ICodedEquivalents; IConceptDescriptor cd = o as IConceptDescriptor; ST displayName = cv.DisplayName; IAny any = o as IAny; // Unless "other" is specified don't serialize if (any.NullFlavor != null && !((NullFlavor)any.NullFlavor).IsChildConcept(NullFlavor.Other)) { return; } // First we need to serialize code, now Code in R2 is a little wierd // It is an IHTSDO standard as described: // http://www.ihtsdo.org/fileadmin/user_upload/Docs_01/Technical_Docs/abstract_models_and_representational_forms.pdf // Serialize attributes first if (cs.CodeValue != null) { try { if (cd != null && cd.Qualifier != null && cd.Qualifier.Count > 0) { s.WriteAttributeString("code", CreateCodeExpression(cd)); displayName = null; } else { s.WriteAttributeString("code", Util.ToWireFormat(cs.CodeValue)); } } catch (Exception e) { result.AddResultDetail(new VocabularyIssueResultDetail(ResultDetailType.Error, e.Message, s.ToString(), e)); } } if (cv.CodeSystem != null) { s.WriteAttributeString("codeSystem", Util.ToWireFormat(cv.CodeSystem)); } if (cv.CodeSystemName != null) { s.WriteAttributeString("codeSystemName", Util.ToWireFormat(cv.CodeSystemName)); } if (cv.CodeSystemVersion != null) { s.WriteAttributeString("codeSystemVersion", Util.ToWireFormat(cv.CodeSystemVersion)); } if (cv.ValueSet != null) { s.WriteAttributeString("valueSet", Util.ToWireFormat(cv.ValueSet)); } if (cv.ValueSetVersion != null) { s.WriteAttributeString("valueSetVersion", Util.ToWireFormat(cv.ValueSetVersion)); } if (cv.CodingRationale != null) { s.WriteAttributeString("codingRationale", Util.ToWireFormat(cv.CodingRationale)); } // Elements // Display name if (displayName != null) { s.WriteStartElement("displayName", "urn:hl7-org:v3"); var hostResult = this.Host.Graph(s, displayName as IGraphable); result.Code = hostResult.Code; result.AddResultDetail(hostResult.Details); s.WriteEndElement(); } // Original text if (cv.OriginalText != null) { s.WriteStartElement("originalText", "urn:hl7-org:v3"); var hostResult = this.Host.Graph(s, cv.OriginalText); result.Code = hostResult.Code; result.AddResultDetail(hostResult.Details); s.WriteEndElement(); } // Translation if (ce != null && ce.Translation != null) { foreach (var translation in ce.Translation) { s.WriteStartElement("translation", "urn:hl7-org:v3"); var hostResult = this.Host.Graph(s, translation); result.Code = hostResult.Code; result.AddResultDetail(hostResult.Details); s.WriteEndElement(); } } // Done }
/// <summary> /// Parse IHTSDO Expression CR List /// </summary> private LIST <CR <String> > ParseCodeExpressionQualifier(string expression, ICodedValue context) { if (expression.StartsWith("{") && expression.EndsWith("}")) { expression = expression.Substring(1, expression.Length - 2); } else if (expression.StartsWith("{")) { throw new InvalidOperationException(); } List <String> crExpressions = new List <string>(10); Regex splitReg = new Regex("^([0-9]*.*?)([=,{}():])(.*?)$", RegexOptions.Multiline); int bDepth = 0; string cExpr = String.Empty; while (expression.Length > 0) { var splitMatch = splitReg.Match(expression); // Successful match? if (!splitMatch.Success) { break; } // Determine the delimiter switch (splitMatch.Groups[2].Value) { case "{": // Increases scope case "(": bDepth++; cExpr += splitMatch.Groups[1].Value + splitMatch.Groups[2].Value; break; case "}": // Decreases scope case ")": bDepth--; cExpr += splitMatch.Groups[1].Value + splitMatch.Groups[2].Value; break; case ",": // Seperator if (bDepth == 0) { cExpr += splitMatch.Groups[1].Value; crExpressions.Add(cExpr); cExpr = String.Empty; } else { cExpr += splitMatch.Groups[1].Value + splitMatch.Groups[2].Value; } break; default: cExpr += splitMatch.Groups[1].Value + splitMatch.Groups[2].Value; break; } expression = splitMatch.Groups[3].Value; } // Last match? splitReg = new Regex("([0-9]+.*)"); var lastMatch = splitReg.Match(expression); // Successful match? if (lastMatch.Success) { cExpr += lastMatch.Groups[1].Value; } // Depth if (bDepth > 1) { throw new InvalidOperationException("Missing closing bracket in expression"); } crExpressions.Add(cExpr); // Prepare return value LIST <CR <String> > retVal = new LIST <CR <string> >(crExpressions.Count); // Now Process each expression splitReg = new Regex("^([0-9]+)[|]?(.*?)[|]?=([(]?.*)$", RegexOptions.Multiline); Regex codeMnemReg = new Regex("^([0-9]+)[|](.*?)[|]$", RegexOptions.Multiline); foreach (var expr in crExpressions) { // Each expression must match var exprMatch = splitReg.Match(expr); if (!exprMatch.Success) { throw new InvalidOperationException("Qualifier expression does not follow format of name=value"); } // Process the name CV <String> name = new CV <string>(exprMatch.Groups[1].Value, context.CodeSystem, context.CodeSystemName, context.CodeSystemVersion) { DisplayName = String.IsNullOrEmpty(exprMatch.Groups[2].Value) ? null : exprMatch.Groups[2].Value, ValueSet = context.ValueSet, ValueSetVersion = context.ValueSetVersion }; // Process value CD <String> value = null; decimal id; // Try to match the exact pattern of a code with description var codeMnemMatch = codeMnemReg.Match(exprMatch.Groups[3].Value); if (codeMnemMatch.Success) { value = new CD <string>(codeMnemMatch.Groups[1].Value, context.CodeSystem, context.CodeSystemName, context.CodeSystemVersion) { DisplayName = String.IsNullOrEmpty(codeMnemMatch.Groups[2].Value) ? null : codeMnemMatch.Groups[2].Value, ValueSet = context.ValueSet, ValueSetVersion = context.ValueSetVersion } } ; else if (decimal.TryParse(exprMatch.Groups[3].Value, out id)) // Simple code { value = new CD <string>(exprMatch.Groups[3].Value, context.CodeSystem, context.CodeSystemName, context.CodeSystemVersion) { ValueSet = context.ValueSet, ValueSetVersion = context.ValueSetVersion } } ; else // IHTSDO expression tree { string valueExpression = exprMatch.Groups[3].Value; value = ParseCodeExpression(valueExpression, context); } retVal.Add(new CR <string>(name, value)); } return(retVal); }