* Register DataPacketReaders

git-svn-id: trunk@11837 -
This commit is contained in:
joost 2008-09-28 19:53:00 +00:00
parent 8c9baed5cb
commit c79e23c5eb
3 changed files with 107 additions and 34 deletions

View File

@ -170,7 +170,7 @@ type
property BookmarkSize : integer read GetBookmarkSize; property BookmarkSize : integer read GetBookmarkSize;
end; end;
TDataPacketFormat = (dfBinary,dfXML,dfXMLUTF8); TDataPacketFormat = (dfBinary,dfXML,dfXMLUTF8,dfAny);
{ TDoubleLinkedBufIndex } { TDoubleLinkedBufIndex }
@ -303,6 +303,7 @@ type
{ TDataPacketReader } { TDataPacketReader }
TDatapacketReaderClass = class of TDatapacketReader;
TDataPacketReader = class(TObject) TDataPacketReader = class(TObject)
FStream : TStream; FStream : TStream;
public public
@ -320,23 +321,20 @@ type
procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); virtual; abstract; procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); virtual; abstract;
procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); virtual; abstract; procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); virtual; abstract;
property Stream: TStream read FStream; property Stream: TStream read FStream;
class function RecognizeStream(AStream : TStream) : boolean; virtual; abstract;
end; end;
{ TXMLBufDatasetReader } { TXMLDatapacketReader }
TXMLDatapacketReader = class(TDataPacketReader) TXMLDatapacketReader = class(TDataPacketReader)
FFileName : String;
XMLDocument : TXMLDocument; XMLDocument : TXMLDocument;
DataPacketNode : TDOMElement; DataPacketNode : TDOMElement;
MetaDataNode : TDOMNode; MetaDataNode : TDOMNode;
FieldsNode : TDOMNode; FieldsNode : TDOMNode;
FChangeLogNode, FChangeLogNode,
FParamsNode, FParamsNode,
FRowDataNode, FRowDataNode,
FRecordNode : TDOMNode; FRecordNode : TDOMNode;
public public
destructor destroy; override; destructor destroy; override;
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override; procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
@ -351,14 +349,12 @@ type
function GetCurrentElement: pointer; override; function GetCurrentElement: pointer; override;
procedure RestoreRecord(ADataset : TBufDataset); override; procedure RestoreRecord(ADataset : TBufDataset); override;
procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override; procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override;
class function RecognizeStream(AStream : TStream) : boolean; override;
// property FileName : string read FFileName write FFileName;
end; end;
{ TFpcBinaryBufDatasetReader } { TFpcBinaryDatapacketReader }
TFpcBinaryDatapacketReader = class(TDataPacketReader) TFpcBinaryDatapacketReader = class(TDataPacketReader)
FFileName : String;
public public
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override; procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override; procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
@ -372,8 +368,7 @@ type
function GetCurrentElement: pointer; override; function GetCurrentElement: pointer; override;
procedure RestoreRecord(ADataset : TBufDataset); override; procedure RestoreRecord(ADataset : TBufDataset); override;
procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override; procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override;
class function RecognizeStream(AStream : TStream) : boolean; override;
property FileName : string read FFileName write FFileName;
end; end;
TBufDataset = class(TDBDataSet) TBufDataset = class(TDBDataSet)
@ -494,10 +489,10 @@ type
procedure SetDatasetPacket(AReader : TDataPacketReader); procedure SetDatasetPacket(AReader : TDataPacketReader);
procedure GetDatasetPacket(AWriter : TDataPacketReader); procedure GetDatasetPacket(AWriter : TDataPacketReader);
procedure LoadFromStream(AStream : TStream); procedure LoadFromStream(AStream : TStream; Format: TDataPacketFormat = dfAny);
procedure SaveToStream(AStream : TStream; Format: TDataPacketFormat = dfBinary); procedure SaveToStream(AStream : TStream; Format: TDataPacketFormat = dfBinary);
procedure LoadFromFile(const AFileName: string = ''); procedure LoadFromFile(AFileName: string = ''; Format: TDataPacketFormat = dfAny);
procedure SaveToFile(const FileName: string = ''; Format: TDataPacketFormat = dfBinary); procedure SaveToFile(AFileName: string = ''; Format: TDataPacketFormat = dfBinary);
procedure CreateDataset; procedure CreateDataset;
property ChangeCount : Integer read GetChangeCount; property ChangeCount : Integer read GetChangeCount;
@ -511,10 +506,46 @@ type
property IndexFieldNames : String read GetIndexFieldNames write SetIndexFieldNames; property IndexFieldNames : String read GetIndexFieldNames write SetIndexFieldNames;
end; end;
procedure RegisterDatapacketReader(ADatapacketReaderClass : TDatapacketReaderClass; AFormat : TDataPacketFormat);
implementation implementation
uses variants, dbconst, xmlwrite, xmlread; uses variants, dbconst, xmlwrite, xmlread;
Type TDatapacketReaderRegistration = record
ReaderClass : TDatapacketReaderClass;
Format : TDataPacketFormat;
end;
var RegisteredDatapacketReaders : Array of TDatapacketReaderRegistration;
procedure RegisterDatapacketReader(ADatapacketReaderClass : TDatapacketReaderClass; AFormat : TDataPacketFormat);
begin
setlength(RegisteredDatapacketReaders,length(RegisteredDatapacketReaders)+1);
with RegisteredDatapacketReaders[length(RegisteredDatapacketReaders)-1] do
begin
Readerclass := ADatapacketReaderClass;
Format := AFormat;
end;
end;
function GetRegisterDatapacketReader(AStream : TStream; AFormat : TDataPacketFormat; var ADataReaderClass : TDatapacketReaderRegistration) : boolean;
var i : integer;
begin
Result := False;
for i := 0 to length(RegisteredDatapacketReaders)-1 do if ((AFormat=dfAny) or (AFormat=RegisteredDatapacketReaders[i].Format)) then
begin
if (AStream=nil) or (RegisteredDatapacketReaders[i].ReaderClass.RecognizeStream(AStream)) then
begin
ADataReaderClass := RegisteredDatapacketReaders[i];
Result := True;
if (AStream <> nil) then AStream.Seek(0,soFromBeginning);
break;
end;
AStream.Seek(0,soFromBeginning);
end;
end;
function DBCompareText(subValue, aValue: pointer; options: TLocateOptions): LargeInt; function DBCompareText(subValue, aValue: pointer; options: TLocateOptions): LargeInt;
begin begin
@ -2340,11 +2371,12 @@ const
); );
procedure TBufDataset.SaveToFile(const FileName: string; procedure TBufDataset.SaveToFile(AFileName: string;
Format: TDataPacketFormat); Format: TDataPacketFormat);
var AFileStream : TFileStream; var AFileStream : TFileStream;
begin begin
AFileStream := TFileStream.Create(FileName,fmCreate); if AFileName='' then AFileName := FFileName;
AFileStream := TFileStream.Create(AFileName,fmCreate);
try try
SaveToStream(AFileStream, Format); SaveToStream(AFileStream, Format);
finally finally
@ -2462,10 +2494,16 @@ begin
end; end;
end; end;
procedure TBufDataset.LoadFromStream(AStream: TStream); procedure TBufDataset.LoadFromStream(AStream: TStream; Format: TDataPacketFormat);
var APacketReader : TDataPacketReader; var APacketReaderReg : TDatapacketReaderRegistration;
APacketReader : TDataPacketReader;
begin begin
APacketReader := TFpcBinaryDatapacketReader.create(AStream); if GetRegisterDatapacketReader(AStream,format,APacketReaderReg) then
APacketReader := APacketReaderReg.ReaderClass.create(AStream)
else if TFpcBinaryDatapacketReader.RecognizeStream(AStream) then
APacketReader := TFpcBinaryDatapacketReader.create(AStream)
else
DatabaseError(SStreamNotRecognised);
try try
SetDatasetPacket(APacketReader); SetDatasetPacket(APacketReader);
finally finally
@ -2474,12 +2512,15 @@ begin
end; end;
procedure TBufDataset.SaveToStream(AStream: TStream; Format: TDataPacketFormat); procedure TBufDataset.SaveToStream(AStream: TStream; Format: TDataPacketFormat);
var APacketWriter : TDataPacketReader; var APacketReaderReg : TDatapacketReaderRegistration;
APacketWriter : TDataPacketReader;
begin begin
case Format of if GetRegisterDatapacketReader(Nil,format,APacketReaderReg) then
dfBinary : APacketWriter := TFpcBinaryDatapacketReader.create(AStream); APacketWriter := APacketReaderReg.ReaderClass.create(AStream)
dfXML : APacketWriter := TXMLDatapacketReader.create(AStream); else if Format = dfBinary then
end; APacketWriter := TFpcBinaryDatapacketReader.create(AStream)
else
DatabaseError(SNoReaderClassRegistered);
try try
GetDatasetPacket(APacketWriter); GetDatasetPacket(APacketWriter);
finally finally
@ -2487,12 +2528,13 @@ begin
end; end;
end; end;
procedure TBufDataset.LoadFromFile(const AFileName: string); procedure TBufDataset.LoadFromFile(AFileName: string; Format: TDataPacketFormat);
var AFileStream : TFileStream; var AFileStream : TFileStream;
begin begin
if AFileName='' then AFileName := FFileName;
AFileStream := TFileStream.Create(AFileName,fmOpenRead); AFileStream := TFileStream.Create(AFileName,fmOpenRead);
try try
LoadFromStream(AFileStream); LoadFromStream(AFileStream, Format);
finally finally
AFileStream.Free; AFileStream.Free;
end; end;
@ -3277,6 +3319,20 @@ begin
FRowDataNode.AppendChild(ARecordNode); FRowDataNode.AppendChild(ARecordNode);
end; end;
class function TXMLDatapacketReader.RecognizeStream(AStream: TStream): boolean;
const XmlStart = '<?xml';
var s : string;
len : integer;
begin
Len := length(XmlStart);
setlength(s,len);
if (AStream.Read (s[1],len) = len)
and (s=XmlStart) then
Result := True
else
Result := False;
end;
procedure TXMLDatapacketReader.GotoNextRecord; procedure TXMLDatapacketReader.GotoNextRecord;
begin begin
FRecordNode := FRecordNode.NextSibling; FRecordNode := FRecordNode.NextSibling;
@ -3295,15 +3351,12 @@ const FpcBinaryIdent = 'BinBufDataset';
procedure TFpcBinaryDatapacketReader.LoadFieldDefs(AFieldDefs: TFieldDefs); procedure TFpcBinaryDatapacketReader.LoadFieldDefs(AFieldDefs: TFieldDefs);
var s : string; var FldCount : word;
FldCount : word;
i : integer; i : integer;
begin begin
setlength(s,sizeof(FpcBinaryIdent)); if not RecognizeStream(Stream) then
Stream.Read(s[1],length(FpcBinaryIdent)); DatabaseError(SStreamNotRecognised);
if s <> FpcBinaryIdent then
DatabaseError('Not a TFpdBinaryBufDatasetReader file:' + s);
FldCount:=Stream.ReadWord; FldCount:=Stream.ReadWord;
for i := 0 to FldCount -1 do with TFieldDef.create(AFieldDefs) do for i := 0 to FldCount -1 do with TFieldDef.create(AFieldDefs) do
@ -3391,5 +3444,23 @@ begin
Stream.WriteBuffer(ADataset.GetCurrentBuffer^,ADataset.FRecordSize); Stream.WriteBuffer(ADataset.GetCurrentBuffer^,ADataset.FRecordSize);
end; end;
class function TFpcBinaryDatapacketReader.RecognizeStream(AStream: TStream
): boolean;
var s : string;
len : integer;
begin begin
Len := length(FpcBinaryIdent);
setlength(s,len);
if (AStream.Read (s[1],len) = len)
and (s=FpcBinaryIdent) then
Result := True
else
Result := False;
end;
initialization
setlength(RegisteredDatapacketReaders,0);
RegisterDatapacketReader(TXMLDatapacketReader,dfXML);
finalization
setlength(RegisteredDatapacketReaders,0);
end. end.

View File

@ -103,6 +103,8 @@ Resourcestring
SNotIndexField = 'Field ''%s'' is not indexed and cannot be modified'; SNotIndexField = 'Field ''%s'' is not indexed and cannot be modified';
SErrUnknownConnectorType = 'Unknown connector type'; SErrUnknownConnectorType = 'Unknown connector type';
SNoIndexFieldNameGiven = 'There are no fields selected to base the index on'; SNoIndexFieldNameGiven = 'There are no fields selected to base the index on';
SStreamNotRecognised = 'The data-stream format is not recognized';
SNoReaderClassRegistered = 'There is no TDatapacketReaderClass registered for this kind of data-stream';
SErrCircularDataSourceReferenceNotAllowed = 'Circular datasource references are not allowed.'; SErrCircularDataSourceReferenceNotAllowed = 'Circular datasource references are not allowed.';

View File

@ -1181,7 +1181,7 @@ var tel, fieldc : integer;
ReadFromFile: Boolean; ReadFromFile: Boolean;
begin begin
try try
ReadFromFile:=FileName<>''; ReadFromFile:=IsReadFromPacket;
FOpenDidPrepare:=Not Prepared; FOpenDidPrepare:=Not Prepared;
If FOpenDidPrepare then If FOpenDidPrepare then
Prepare; Prepare;