/// <summary> /// Returns standard feature class instance, if the key in the specified feature item is found /// in the map; otherwise returns the specified feature item itself. /// For example: /// If the specified feature item has the key "Gene" then this method returns instance of the Gene class /// with data copied from the specified item. /// </summary> /// <param name="item">Feature item instance to which the standard feature item instance is needed.</param> /// <returns>If found returns appropriate class instance for the specified feature item, otherwise returns /// the specified item itself.</returns> public static FeatureItem GetStandardFeatureItem(FeatureItem item) { Type type = null; if (featureMap.ContainsKey(item.Key)) { type = featureMap[item.Key]; } if (type != null) { FeatureItem newItem = (FeatureItem)Activator.CreateInstance(type, item.Location); foreach (KeyValuePair <string, List <string> > kvp in item.Qualifiers) { newItem.Qualifiers.Add(kvp.Key, kvp.Value); } item = newItem; } return(item); }
private void ParseFeatures(MBFTextReader mbfReader, ref Sequence sequence) { ILocationBuilder locBuilder = LocationBuilder; if (locBuilder == null) { throw new InvalidOperationException(Resource.NullLocationBuild); } // set data indent for features mbfReader.DataIndent = _featureDataIndent; // The sub-items of a feature are referred to as qualifiers. These do not have unique // keys, so they are stored as lists in the SubItems dictionary. SequenceFeatures features = new SequenceFeatures(); IList <FeatureItem> featureList = features.All; while (mbfReader.HasLines) { if (String.IsNullOrEmpty(mbfReader.Line) || mbfReader.LineHeader == "FEATURES") { mbfReader.GoToNextLine(); continue; } if (mbfReader.Line[0] != ' ') { // start of non-feature text break; } if (!mbfReader.LineHasHeader) { string message = Properties.Resource.GenbankEmptyFeature; Trace.Report(message); throw new InvalidDataException(message); } // check for multi-line location string string featureKey = mbfReader.LineHeader; string location = mbfReader.LineData; mbfReader.GoToNextLine(); while (mbfReader.HasLines && !mbfReader.LineHasHeader && mbfReader.LineHasData && !mbfReader.LineData.StartsWith("/", StringComparison.Ordinal)) { location += mbfReader.LineData; mbfReader.GoToNextLine(); } // create features as MetadataListItems FeatureItem feature = new FeatureItem(featureKey, locBuilder.GetLocation(location)); // process the list of qualifiers, which are each in the form of // /key="value" string qualifierKey = string.Empty; string qualifierValue = string.Empty; while (mbfReader.HasLines) { if (!mbfReader.LineHasHeader && mbfReader.LineHasData) { // '/' denotes a continuation of the previous line if (mbfReader.LineData.StartsWith("/", StringComparison.Ordinal)) { // new qualifier; save previous if this isn't the first if (!String.IsNullOrEmpty(qualifierKey)) { AddQualifierToFeature(feature, qualifierKey, qualifierValue); } // set the key and value of this qualifier int equalsIndex = mbfReader.LineData.IndexOf('='); if (equalsIndex < 0) { // no value, just key (this is allowed, see NC_005213.gbk) qualifierKey = mbfReader.LineData.Substring(1); qualifierValue = string.Empty; } else if (equalsIndex > 0) { qualifierKey = mbfReader.LineData.Substring(1, equalsIndex - 1); qualifierValue = mbfReader.LineData.Substring(equalsIndex + 1); } else { string message = String.Format( CultureInfo.CurrentCulture, Properties.Resource.GenbankInvalidFeature, mbfReader.Line); Trace.Report(message); throw new InvalidDataException(message); } } else { // Continuation of previous line; "note" gets a line break, and // everything else except "translation" and "transl_except" gets a // space to separate words. if (qualifierKey == "note") { qualifierValue += Environment.NewLine; } else if (qualifierKey != "translation" && qualifierKey != "transl_except") { qualifierValue += " "; } qualifierValue += mbfReader.LineData; } mbfReader.GoToNextLine(); } else if (mbfReader.Line.StartsWith("\t", StringComparison.Ordinal)) { // this seems to be data corruption; but BioPerl test set includes // (old, 2003) NT_021877.gbk which has this problem, so we // handle it ApplicationLog.WriteLine("WARN: nonstandard line format at line {0}: '{1}'", mbfReader.LineNumber, mbfReader.Line); qualifierValue += " " + mbfReader.Line.Trim(); mbfReader.GoToNextLine(); } else { break; } } // add last qualifier if (!String.IsNullOrEmpty(qualifierKey)) { AddQualifierToFeature(feature, qualifierKey, qualifierValue); } // still add feature, even if it has no qualifiers featureList.Add(StandardFeatureMap.GetStandardFeatureItem(feature)); } if (featureList.Count > 0) { ((GenBankMetadata)sequence.Metadata[Helper.GenBankMetadataKey]).Features = features; } }