/// <summary> /// THis is to split the HL loops appropriately /// </summary> /// <param name="edi"></param> /// <param name="loopID"></param> /// <param name="position"></param> /// <param name="value"></param> /// <returns></returns> public static List <String> LoopSplit(this string edi, EDILoop loopInfo, EDIDelim seperator) { string[] segments = edi.Split(seperator.Segment); bool inLoop = false; List <string> loops = new List <string>(); List <string> tmp = new List <string>(); foreach (string segment in segments) { if (segment.StartsWith(loopInfo.GetFormat())) { string[] elements = segment.Split(seperator.Element); if (elements[loopInfo.GetPosition()].Equals(loopInfo.GetSelectionValue())) { if (tmp.Count > 0) { loops.Add(String.Join("" + seperator.Segment, tmp)); tmp.Clear(); } inLoop = true; } } if (inLoop) { tmp.Add(segment); } } if (tmp.Count > 0) { loops.Add(String.Join("" + seperator.Segment, tmp)); } return(loops); }
/// <summary> /// This is the default write method. /// In Case of the EBSegment it needs to overwrite this /// </summary> /// <returns></returns> internal string ToEDIString(EDIDelim seperators) { StringBuilder rtnVal = new StringBuilder(_segmentID + seperators.Element); foreach (PropertyInfo propertyInfo in GetType().GetProperties()) { if (propertyInfo.CanRead) { //Attribute[] attrs = Attribute.GetCustomAttributes(propertyInfo); //Custom types need to be done outside. object propertyValue = propertyInfo.GetValue(this, null); if (propertyValue != null) { if (propertyInfo.PropertyType.BaseType == typeof(CompositeBase)) { //Grab the function we are going to use MethodInfo method = propertyValue.GetType().GetMethod("ToEDIString", internalFlags); //Invoke the function of that class on the class rtnVal.Append(method.Invoke(propertyValue, new object[] { seperators.Subelement }).ToString()); } else { //TODO: Implement a custome ConveterType here. //Location to add the TypecOnverter... allows for input of one from outside rtnVal.Append(propertyInfo.EDI2String(propertyValue)); } } rtnVal.Append(seperators.Element); } } return(rtnVal.ToString().TrimEnd(seperators.Element)); }
/// <summary> /// Call this with about the first 175 characters. ISA contains 106 so the extra is just safety. /// </summary> /// <param name="original"></param> /// <returns></returns> public static EDIDelim GetFileDelimiters(this string original) { EDIDelim rtnVal = new EDIDelim(); rtnVal.Element = original[3]; rtnVal.Segment = original[105]; rtnVal.Subelement = original[104]; rtnVal.Repitition = original[82]; return(rtnVal); }
/// <summary> /// THis is the raw generic you should use from your programs /// </summary> /// <param name="ediFile"></param> public void FromEDIFile(string ediFile, bool createAck = false) { //get the seperators //then call the from EDI string.... EDIDelim currDelim = ediFile.SafeSubstring(0, 175).GetFileDelimiters(); originalDelims = currDelim; try { FromEDIString(ediFile, currDelim); } catch (Exception) { //Do something for the Ack throw; } if (createAck) { CreateAcknowledgement(ediFile); } }
/// <summary> /// Expectation is that a single ISA-IEA come to this function /// </summary> /// <param name="ediFile"></param> /// <returns></returns> public static List <String> SplitByGS(string ediFile) { EDIDelim currDelim = ediFile.SafeSubstring(0, 175).GetFileDelimiters(); List <string> rtnVal = new List <string>(); string[] strSegments = ediFile.Split(new char[] { currDelim.Segment }, StringSplitOptions.RemoveEmptyEntries); List <String> holder = new List <string>(); int[] pntrs = strSegments.FindAllIndexOf(a => a.StartsWith("GS")); int[] gePntrs = strSegments.FindAllIndexOf(a => a.StartsWith("GE")); for (int p = 0; p < pntrs.Length; p++) { holder.Add(strSegments[0]); holder.AddRange(strSegments.GetRange(pntrs[p], gePntrs[p])); holder.Add(strSegments[strSegments.Count() - 1]); rtnVal.Add(String.Join(("" + currDelim.Segment), holder) + currDelim.Segment); holder.Clear(); } return(rtnVal); }
//TODO: Determine how to pass delimiters easily. internal string ToEDIString(EDIDelim seperators) { //Always set these values so that we ensure file is consistent. SetISADelimiters(seperators.Repitition, seperators.Subelement); List <string> strSegments = new List <string>(); foreach (PropertyInfo propertyInfo in GetType().GetProperties()) { if (propertyInfo.CanRead) { //Foreach loop add since it is a list the "FromEDIString" object propertyValue = propertyInfo.GetValue(this, null); if (propertyValue != null) { if (IsPropertyACollection(propertyInfo)) { //loop through it. var collection = (IEnumerable)propertyInfo.GetValue(this, null); foreach (var item in collection) { MethodInfo method = item.GetType().GetMethod("ToEDIString", internalFlags); //Invoke the function of that class on the class strSegments.Add(method.Invoke(item, new object[] { seperators }).ToString()); } } else { //Grab the function we are going to use MethodInfo method = propertyValue.GetType().GetMethod("ToEDIString", internalFlags); //Invoke the function of that class on the class strSegments.Add(method.Invoke(propertyValue, new object[] { seperators }).ToString()); } } } } return(String.Join(("" + seperators.Segment), strSegments)); }
/// <summary> /// THis is the recursive function that is called. /// </summary> /// <param name="ediData"></param> /// <param name="seperators"></param> internal void FromEDIString(string ediData, EDIDelim seperators) { string[] strSegments = ediData.Split(new char[] { seperators.Segment }, StringSplitOptions.RemoveEmptyEntries); //Hopefully allows us to determine if the segment even belongs in the current object. List <string> objSegments = GetAvailableSegments(); int p = 0; //TODO: How do we align the inbound to the object... for (int objPntr = 0; objPntr < GetType().GetProperties().Length; objPntr++) { PropertyInfo propertyInfo = GetType().GetProperties()[objPntr]; if (propertyInfo.CanRead) { Attribute[] attrs = Attribute.GetCustomAttributes(propertyInfo); bool IsGeneric = false; if (attrs.Any(x => x.GetType() == typeof(EDILoop))) { EDILoop currentLoop = ((EDILoop)attrs.FirstOrDefault(z => z.GetType() == typeof(EDILoop))); currentLoop.AdjustFormat(seperators.Element); //Check to see if the segment starts this way... //string segStart = currentLoop.GetFormat() + seperators.Element; if (strSegments[p].StartsWith(currentLoop.GetFormat())) { //This should be the amount of Segments we need to group together in order to split properly. int es = strSegments.Count() - p - currentLoop.GetEndSkip(); //we know that the current loop is at least one we want... //es cannot be less than 1 if (es == 0) { es = 1; } //TODO: Multiple altsegment ending ID's how to handle here... if (currentLoop.GetAltSegmentID().Any()) { for (int i = p + 1; i < strSegments.Count(); i++) { //if (strSegments[i].StartsWith(currentLoop.GetAltSegmentID())) if ( currentLoop.GetAltSegmentID() .Any(alt => strSegments[i].StartsWith(alt + seperators.Element))) { es = i - p; break; } } } //We need to determine the end point of the alt ending if present. List <string> loopValues = String.Join("" + seperators.Segment, strSegments, p, es) .TransactionSplit(currentLoop, seperators); //Foreach loop add since it is a list the "FromEDIString" object propertyValue = propertyInfo.GetValue(this, null); //This should always do the later but for testing have it here... if (propertyValue == null) { //How do we put this as the property value ConstructorInfo ctor = propertyInfo.PropertyType.GetConstructor(System.Type.EmptyTypes); object instance = ctor.Invoke(null); propertyInfo.SetValue(this, Convert.ChangeType(instance, propertyInfo.PropertyType), null); propertyValue = propertyInfo.GetValue(this, null); } if (IsPropertyACollection(propertyInfo)) { MethodInfo Addmethod = propertyValue.GetType().GetMethod("Add"); Type t = propertyValue.GetType().GetGenericArguments()[0]; //EDIBase call MethodInfo ediMethod = t.GetMethod("FromEDIString", internalFlags); foreach (string lValues in loopValues) { var tmp = t.GetConstructor(new Type[] {}).Invoke(new object[] {}); //Invoke the EDI string parser ediMethod.Invoke(tmp, new object[] { lValues, seperators }); //Add the new item to the list. Addmethod.Invoke(propertyValue, new object[] { tmp }); } } else { //This should only be called once... but we shall see... foreach (string lValues in loopValues) { MethodInfo ediMethod = propertyValue.GetType() .GetMethod("FromEDIString", internalFlags); ediMethod.Invoke(propertyValue, new object[] { lValues, seperators }); } } //p = strSegments.Count() - currentLoop.GetEndSkip(); p = p + es; } else { //If EDI file we are reading has an extra segment that is not part of the object //then we need to skip it and go on to the next one, while keeping our place //in the current file to properly unmarshal the rest of the file if (!IsValidSegment(strSegments[p], objSegments, objPntr)) { p++; objPntr--; } } } else { //Handle single and list of simple segments. string segmentID = propertyInfo.PropertyType.Name.Replace("Seg", ""); if (segmentID.ToUpper().StartsWith("LIST")) { segmentID = propertyInfo.PropertyType.GetGenericArguments()[0].Name.Replace("Seg", ""); if (propertyInfo.PropertyType.GetGenericArguments()[0].Name.StartsWith("Generic")) { IsGeneric = true; } } if (p > strSegments.Count() - 1) { break; } if (strSegments[p].StartsWith(segmentID) || IsGeneric) { //Actually Grab the class of what we are trying to do object propertyValue = propertyInfo.GetValue(this, null); if (propertyValue == null) { //How do we put this as the property value ConstructorInfo ctor = propertyInfo.PropertyType.GetConstructor(System.Type.EmptyTypes); object instance = ctor.Invoke(null); propertyInfo.SetValue(this, Convert.ChangeType(instance, propertyInfo.PropertyType), null); propertyValue = propertyInfo.GetValue(this, null); } //Collection of single objects if (IsPropertyACollection(propertyInfo)) { //This is the list of objects and function for the adding MethodInfo Addmethod = propertyValue.GetType().GetMethod("Add"); //THis is the type of object and the method we need plus the segment ID Type t = propertyValue.GetType().GetGenericArguments()[0]; MethodInfo ediMethod = t.GetMethod("FromEDIString", internalFlags); string segID = t.Name.Replace("Seg", ""); //Start looping through the segments while (strSegments[p].StartsWith(segID) || IsGeneric) { //Create an instance of the list object var tmp = t.GetConstructor(new Type[] {}).Invoke(new object[] {}); //Invoke the EDI string parser ediMethod.Invoke(tmp, new object[] { strSegments[p], seperators }); //Add the new item to the list. Addmethod.Invoke(propertyValue, new object[] { tmp }); p++; if ((p >= strSegments.Count()) || (IsGeneric && (p >= strSegments.Count() - 1))) { break; } } } else { //This didn't work so good.... but we are not loop through the segments of the base type.. if (propertyValue.GetType().BaseType == typeof(EDIBase)) { string inputValue = String.Join("" + seperators.Segment, strSegments, p, strSegments.Count() - 1); MethodInfo ediMethod = propertyValue.GetType() .GetMethod("FromEDIString", internalFlags); //This should always do the later but for testing have it here... ediMethod.Invoke(propertyValue, new object[] { inputValue, seperators }); p = (strSegments.Count() - 1); } else { //Grab the function we are going to use // Type[] paramTypes = _countMethodParams.Select(p => p.GetType()).ToArray(); MethodInfo method = propertyValue.GetType() .GetMethod("FromEDIString", internalFlags); //Invoke the function of that class on the class //strSegments.Add(method.Invoke(propertyValue, new object[] { '*' }).ToString()); method.Invoke(propertyValue, new object[] { strSegments[p], seperators }); p++; } } } else { //If EDI file we are reading has an extra segment that is not part of the object //then we need to skip it and go on to the next one, while keeping our place //in the current file to properly unmarshal the rest of the file if (!IsValidSegment(strSegments[p], objSegments, objPntr)) { p++; objPntr--; } } } } if (p > strSegments.Count() - 1) { break; } } }
public static List <string> TransactionSplit(this string edi, EDILoop loopInfo, EDIDelim delims) { if (String.IsNullOrWhiteSpace(loopInfo.GetSelectionValue())) { if (String.IsNullOrWhiteSpace(loopInfo.GetIgnoreStartID())) { return(edi.TransactionSplit(loopInfo.GetSplitFormat(), delims.Segment)); } return(edi.DoTransactionSplit(loopInfo, delims)); } return(edi.LoopSplit(loopInfo, delims)); }
public static List <string> DoTransactionSplit(this string edi, EDILoop loopInfo, EDIDelim seperators) { List <string> rtnVal = new List <string>(); string[] segments = edi.Split(seperators.Segment); List <string> tmp = new List <string>(); bool doCheck = true; int startSeg = 0; int endSeg = 0; //assumption is that this will be called when the first segment meets the initial criteria tmp.Add(segments[0]); for (int i = 1; i < segments.Count(); i++) { if (segments[i].StartsWith(loopInfo.GetFormat()) && doCheck) { rtnVal.Add(string.Join("" + seperators.Segment, tmp)); tmp.Clear(); } if (segments[i].StartsWith(loopInfo.GetIgnoreStartID())) { doCheck = false; } if (segments[i].StartsWith(loopInfo.GetIgnoreEndID())) { doCheck = true; } tmp.Add(segments[i]); } if (tmp.Count > 0) { rtnVal.Add(string.Join("" + seperators.Segment, tmp)); } return(rtnVal); }
/// <summary> /// In order to try to avoid issues with someone calling this wrong /// Make it internal as reflection should all happen here... /// </summary> /// <param name="segment"></param> /// <param name="seperators"></param> /// <param name="isGeneric">Only used for Acknowledgements</param> internal void FromEDIString(string segment, EDIDelim seperators) { string[] elements = segment.Split(seperators.Element); if (GetType() == typeof(GenericSeg)) { _segmentID = elements[0]; RawData = segment; } else { int x = 1; foreach (PropertyInfo propertyInfo in GetType().GetProperties()) { if (propertyInfo.CanRead) { Attribute[] attrs = Attribute.GetCustomAttributes(propertyInfo); object propertyValue = propertyInfo.GetValue(this, null); var bType = propertyInfo.PropertyType.BaseType; if (bType == typeof(CompositeBase)) { if (propertyValue == null) { //How do we put this as the property value ConstructorInfo ctor = propertyInfo.PropertyType.GetConstructor(System.Type.EmptyTypes); object instance = ctor.Invoke(null); propertyInfo.SetValue(this, Convert.ChangeType(instance, propertyInfo.PropertyType), null); propertyValue = propertyInfo.GetValue(this, null); } //This allowed us to get past the 834 issue... if (!string.IsNullOrWhiteSpace(elements[x])) { MethodInfo ediMethod = propertyValue.GetType().GetMethod("FromEDIString", internalFlags); //This should always do the later but for testing have it here... ediMethod.Invoke(propertyValue, new object[] { elements[x], seperators.Subelement }); } x++; if (x > elements.Count() - 1) { break; } } else { if (!String.IsNullOrWhiteSpace(elements[x]) || attrs.Any(ax => ax.GetType() == typeof(EDIFixedLen))) { //The extension of FromEDIString is the actual converter... we need to do this differently //get converter and set value propertyInfo.SetValue(this, elements[x].FromEDIString(propertyInfo.PropertyType, attrs), null); } x++; if (x > elements.Count() - 1) { break; } } } } } }