{**************************************************************************************************} { } { Project JEDI Code Library (JCL) } { } { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); } { you may not use this file except in compliance with the License. You may obtain a copy of the } { License at http://www.mozilla.org/MPL/ } { } { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF } { ANY KIND, either express or implied. See the License for the specific language governing rights } { and limitations under the License. } { } { The Original Code is JclEDI_ANSIX12_Ext.pas. } { } { The Initial Developer of the Original Code is Raymond Alexander. } { Portions created by Raymond Alexander are Copyright (C) Raymond Alexander. All rights reserved. } { } { Contributor(s): } { Raymond Alexander (rayspostbox3) } { } {**************************************************************************************************} { } { EDI ANSI X12 - Standard Exchange Format (*.sef) File Extensions } { } { This unit is still in development } { } { Unit owner: Raymond Alexander } { Date created: March 26, 2004 } { Additional Info: } { E-Mail at RaysDelphiBox3 att hotmail dott com } { For latest EDI specific demos see http://sourceforge.net/projects/edisdk } { See home page for latest news & events and online help. } { } {**************************************************************************************************} // $Id: JclEDI_UNEDIFACT_Ext.pas,v 1.7 2005/03/08 08:33:16 marquardt Exp $ unit JclEDI_UNEDIFACT_Ext; {$I jcl.inc} {$IFDEF SUPPORTS_WEAKPACKAGEUNIT} {$WEAKPACKAGEUNIT ON} {$ENDIF SUPPORTS_WEAKPACKAGEUNIT} interface uses SysUtils, Classes, Contnrs, JclResources, JclEDI, JclEDI_UNEDIFACT, JclEDISEF; type // EDI Transaction Set Document and related types and classes TEDIMessageDocumentOptions = set of (doLinkSpecToDataObject); TEDI_UNEDIFACT_Document = class(TEDIMessageLoop) private FEDISEFSet: TEDISEFSet; protected FErrorOccured: Boolean; FEDITSDOptions: TEDIMessageDocumentOptions; FEDILoopStack: TEDILoopStack; // References FEDIMessage: TEDIMessage; FEDIMessageSpec: TObjectList; function ValidateSegSpecIndex(DataSegmentId: string; SpecStartIndex: Integer): Integer; function AdvanceSegSpecIndex(DataIndex, SpecStartIndex, SpecEndIndex: Integer): Integer; procedure AddLoopToDoc(StackRecord: TEDILoopStackRecord; SegmentId, OwnerLoopId, ParentLoopId: string; var EDIObject: TEDIObject); procedure SetSpecificationPointers(DataSegment: TEDISegment; SpecSegment: TEDISEFSegment); protected procedure ValidateData(TSDocument: TEDI_UNEDIFACT_Document; LoopStack: TEDILoopStack; DataSegment: TEDISegment; SpecSegment: TEDISEFSegment; var DataIndex, SpecIndex: Integer; var ErrorOccured: Boolean); virtual; public constructor Create(Parent: TEDIDataObject; AEDIMessage: TEDIMessage; SEFSet: TEDISEFSet); reintroduce; destructor Destroy; override; // // ToDo: More procedures and functions to manage internal structures // procedure FormatDocument; virtual; published property EDITSDOptions: TEDIMessageDocumentOptions read FEDITSDOptions write FEDITSDOptions; property ErrorOccured: Boolean read FErrorOccured; end; implementation // { TEDI_UNEDIFACT_Document } constructor TEDI_UNEDIFACT_Document.Create(Parent: TEDIDataObject; AEDIMessage: TEDIMessage; SEFSet: TEDISEFSet); begin inherited Create(Parent); FEDILoopStack := TEDILoopStack.Create; FEDILoopStack.OnAddLoop := AddLoopToDoc; FEDIMessage := AEDIMessage; FEDISEFSet := SEFSet; FEDIMessageSpec := SEFSet.GetSegmentObjectList; FEDITSDOptions := []; end; destructor TEDI_UNEDIFACT_Document.Destroy; begin FreeAndNil(FEDILoopStack); FEDIMessage := nil; FEDIMessageSpec.Free; inherited Destroy; end; procedure TEDI_UNEDIFACT_Document.FormatDocument; var I, J: Integer; LSR: TEDILoopStackRecord; DataSegment: TEDISegment; SpecSegment: TEDISEFSegment; begin I := 0; J := 0; if doLinkSpecToDataObject in FEDITSDOptions then begin FEDISEFSet.BindTextSets(FEDISEFSet.SEFFile.TEXTSETS); FEDISEFSet.BindSegmentTextSets; end; // Initialize the stack FEDILoopStack.Flags := FEDILoopStack.Flags - [ediLoopRepeated]; LSR := FEDILoopStack.ValidateLoopStack(FEDIMessage.Segment[I].SegmentID, NA_LoopId, NA_LoopId, 0, Self); // while (I <= FEDIMessage.SegmentCount - 1) and (J <= FEDIMessageSpec.Count - 1) do begin FEDILoopStack.Flags := FEDILoopStack.Flags - [ediLoopRepeated]; DataSegment := FEDIMessage.Segment[I]; // If loop has repeated then move the spec index back J := ValidateSegSpecIndex(DataSegment.SegmentID, J); // Check current segment against segment spec SpecSegment := TEDISEFSegment(FEDIMessageSpec[J]); if DataSegment.SegmentID = SpecSegment.SegmentID then begin // Retrieve the correct record to use from the stack LSR := FEDILoopStack.ValidateLoopStack(SpecSegment.SegmentID, SpecSegment.OwnerLoopId, SpecSegment.ParentLoopId, J, LSR.EDIObject); // // Debug - Keep the following here in case someone wants to debug what happens to the stack. // ShowMessage('Current Data Segment: [' + IntToStr(I) + '] ' + DataSegment.SegmentID + #13#10 + // 'Current Spec Segment: [' + IntToStr(J) + '] ' + SpecSegment.SegmentID + #13#10 + // FEDILoopStack.Debug); // // Do error checking and data validation in decendent class ValidateData(Self, FEDILoopStack, DataSegment, SpecSegment, I, J, FErrorOccured); if FErrorOccured then Exit; // Process Segment Id TEDIMessageLoop(LSR.EDIObject).AppendSegment(DataSegment); // if doLinkSpecToDataObject in FEDITSDOptions then begin SpecSegment.BindTextSets(SpecSegment.SEFFile.TEXTSETS); SpecSegment.BindElementTextSets; SetSpecificationPointers(DataSegment, SpecSegment); end; // Move to the next data segment Inc(I); end else begin // Do error checking and data validation in decendent class ValidateData(Self, FEDILoopStack, DataSegment, SpecSegment, I, J, FErrorOccured); if FErrorOccured then Exit; // // Debug - Keep the following here in case someone wants to debug what happens to the stack. // ShowMessage('Current Data Segment: [' + IntToStr(I) + '] ' + DataSegment.SegmentID + #13#10 + // 'Current Spec Segment: [' + IntToStr(J) + '] ' + SpecSegment.SegmentID + #13#10 + // FEDILoopStack.Debug); // // Move to the next specification segment J := AdvanceSegSpecIndex(I, J, FEDIMessageSpec.Count - 1); //Inc(J); end; end; end; procedure TEDI_UNEDIFACT_Document.ValidateData(TSDocument: TEDI_UNEDIFACT_Document; LoopStack: TEDILoopStack; DataSegment: TEDISegment; SpecSegment: TEDISEFSegment; var DataIndex, SpecIndex: Integer; var ErrorOccured: Boolean); begin ErrorOccured := False; end; procedure TEDI_UNEDIFACT_Document.SetSpecificationPointers(DataSegment: TEDISegment; SpecSegment: TEDISEFSegment); var I, J: Integer; begin DataSegment.SpecPointer := SpecSegment; J := SpecSegment.Elements.Count - 1; for I := 0 to DataSegment.ElementCount - 1 do begin if I > J then raise EJclEDIError.CreateResFmt(@RsEDIError058, [IntToStr(I), DataSegment.SegmentId, IntToStr(DataSegment.GetIndexPositionFromParent)]); DataSegment.EDIDataObject[I].SpecPointer := SpecSegment.Elements[I]; // ToDo: Assign SubElement Specs end; end; procedure TEDI_UNEDIFACT_Document.AddLoopToDoc(StackRecord: TEDILoopStackRecord; SegmentId, OwnerLoopId, ParentLoopId: string; var EDIObject: TEDIObject); var I: Integer; Loop: TEDIMessageLoop; begin Loop := TEDIMessageLoop(StackRecord.EDIObject); I := Loop.AddLoop(OwnerLoopId, ParentLoopId); EDIObject := TEDIMessageLoop(Loop[I]); end; function TEDI_UNEDIFACT_Document.ValidateSegSpecIndex(DataSegmentId: string; SpecStartIndex: Integer): Integer; var I: Integer; begin Result := SpecStartIndex; // Find the segment in the stack to determine if a loop has repeated for I := High(FEDILoopStack.Stack) downto Low(FEDILoopStack.Stack) do begin if (DataSegmentId = FEDILoopStack.Stack[I].SegmentId) and (FEDILoopStack.Stack[I].OwnerLoopId <> NA_LoopId) then begin FEDILoopStack.Flags := FEDILoopStack.Flags + [ediLoopRepeated]; Result := FEDILoopStack.Stack[I].SpecStartIndex; Break; end; end; end; function TEDI_UNEDIFACT_Document.AdvanceSegSpecIndex(DataIndex, SpecStartIndex, SpecEndIndex: Integer): Integer; var DataSegment: TEDISegment; TestSegment: TEDISEFSegment; I: Integer; begin Result := SpecEndIndex + 1; DataSegment := FEDIMessage.Segment[DataIndex]; for I := SpecStartIndex + 1 to SpecEndIndex do begin TestSegment := TEDISEFSegment(FEDIMessageSpec[I]); // Find matching segment if ((DataSegment.SegmentID) = (TestSegment.SegmentID)) then begin Result := I; Break; end; end; end; end.