// @(#)root/xml:$Name: $:$Id: TXMLDtdGenerator.cxx,v 1.8 2004/05/17 12:34:26 brun Exp $
// Author: Sergey Linev 10.05.2004
/*************************************************************************
* Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#include "TXMLDtdGenerator.h"
#include "TStreamerElement.h"
#include "TStreamerInfo.h"
#include "TCollection.h"
#include "Riostream.h"
ClassImp(TXMLDtdGenerator);
//______________________________________________________________________________
TXMLDtdGenerator::TXMLDtdGenerator() : TXMLSetup() {
}
//______________________________________________________________________________
TXMLDtdGenerator::TXMLDtdGenerator(const char* setup) : TXMLSetup(setup) {
}
//______________________________________________________________________________
TXMLDtdGenerator::TXMLDtdGenerator(const TXMLSetup& setup) : TXMLSetup(setup) {
}
//______________________________________________________________________________
TXMLDtdGenerator::~TXMLDtdGenerator() {
}
//______________________________________________________________________________
void TXMLDtdGenerator::AddClassSpace(TCollection* col) {
if (col==0) col = gROOT->GetListOfClasses();
fClassSpace.AddAll(col);
}
//______________________________________________________________________________
void TXMLDtdGenerator::AddInstrumentedClass(TStreamerInfo* info) {
if (info==0) return;
if (fInstrumentedClasses.FindObject(info)==0)
fInstrumentedClasses.Add(info);
TClass* cl = (TClass*) fBlackClasses.FindObject(info->GetClass());
if (cl!=0) {
fBlackClasses.Remove(cl);
fBlackClasses.Compress();
}
}
//______________________________________________________________________________
void TXMLDtdGenerator::AddBlackClass(TClass* cl) {
if (cl==0) return;
if (fBlackClasses.FindObject(cl)!=0) return;
for(int n=0;n<=fInstrumentedClasses.GetLast();n++) {
TStreamerInfo* info = (TStreamerInfo*) fInstrumentedClasses.At(n);
if (cl==info->GetClass()) return;
}
fBlackClasses.Add(cl);
}
//______________________________________________________________________________
void TXMLDtdGenerator::AddUsedClass(TClass * cl) {
if ((cl!=0) && (fUsedClasses.FindObject(cl)==0))
fUsedClasses.Add(cl);
}
//______________________________________________________________________________
void TXMLDtdGenerator::Produce(const char* fname, TClass* onlyclass) {
if (fname==0) return;
ofstream fs(fname);
if (GetXmlLayout()==kGeneralized)
ProduceGeneralDtd(fs, onlyclass);
else
ProduceSpecificDtd(fs, onlyclass);
}
//______________________________________________________________________________
Int_t TXMLDtdGenerator::dtdType(TStreamerElement* el) {
if (el==0) return dtd_none;
Int_t typ = el->GetType();
switch (typ) {
// write basic types
case TStreamerInfo::kChar:
case TStreamerInfo::kShort:
case TStreamerInfo::kInt:
case TStreamerInfo::kLong:
case TStreamerInfo::kLong64:
case TStreamerInfo::kFloat:
case TStreamerInfo::kDouble:
case TStreamerInfo::kUChar:
case TStreamerInfo::kUShort:
case TStreamerInfo::kUInt:
case TStreamerInfo::kULong:
case TStreamerInfo::kULong64:
case TStreamerInfo::kDouble32:
if (GetXmlLayout()==0) return dtd_attr;
else return dtd_elem;
case TStreamerInfo::kOffsetL + TStreamerInfo::kChar:
case TStreamerInfo::kOffsetL + TStreamerInfo::kShort:
case TStreamerInfo::kOffsetL + TStreamerInfo::kInt:
case TStreamerInfo::kOffsetL + TStreamerInfo::kLong:
case TStreamerInfo::kOffsetL + TStreamerInfo::kLong64:
case TStreamerInfo::kOffsetL + TStreamerInfo::kFloat:
case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble:
case TStreamerInfo::kOffsetL + TStreamerInfo::kUChar:
case TStreamerInfo::kOffsetL + TStreamerInfo::kUShort:
case TStreamerInfo::kOffsetL + TStreamerInfo::kUInt:
case TStreamerInfo::kOffsetL + TStreamerInfo::kULong:
case TStreamerInfo::kOffsetL + TStreamerInfo::kULong64:
case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble32:
return dtd_fixarray;
// write pointer to an array of basic types array[n]
case TStreamerInfo::kOffsetP + TStreamerInfo::kChar:
case TStreamerInfo::kOffsetP + TStreamerInfo::kShort:
case TStreamerInfo::kOffsetP + TStreamerInfo::kInt:
case TStreamerInfo::kOffsetP + TStreamerInfo::kLong:
case TStreamerInfo::kOffsetP + TStreamerInfo::kLong64:
case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat:
case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble:
case TStreamerInfo::kOffsetP + TStreamerInfo::kUChar:
case TStreamerInfo::kOffsetP + TStreamerInfo::kUShort:
case TStreamerInfo::kOffsetP + TStreamerInfo::kUInt:
case TStreamerInfo::kOffsetP + TStreamerInfo::kULong:
case TStreamerInfo::kOffsetP + TStreamerInfo::kULong64:
case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble32:
return dtd_array;
// array counter [n]
// info used by TBranchElement::FillLeaves
case TStreamerInfo::kCounter:
if (GetXmlLayout()==0) return dtd_attr;
else return dtd_elem;
// char*
case TStreamerInfo::kCharStar:
return dtd_charstar;
// special case for TObject::fBits in case of a referenced object
case TStreamerInfo::kBits:
if (GetXmlLayout()==0) return dtd_attr;
else return dtd_elem;
case TStreamerInfo::kTString:
if (GetXmlLayout()==0) return dtd_attr;
else return dtd_elem;
// Class* Class not derived from TObject and with comment field //->
case TStreamerInfo::kAnyp:
case TStreamerInfo::kAnyp + TStreamerInfo::kOffsetL:
// Class * Class derived from TObject and with comment field //->
case TStreamerInfo::kObjectp:
case TStreamerInfo::kObjectp + TStreamerInfo::kOffsetL:
return dtd_fastobj1;
// Class* Class not derived from TObject and no comment
case TStreamerInfo::kAnyP:
case TStreamerInfo::kAnyP + TStreamerInfo::kOffsetL:
// Class* Class derived from TObject
case TStreamerInfo::kObjectP:
case TStreamerInfo::kObjectP + TStreamerInfo::kOffsetL:
return dtd_fastobj2;
// Class* Class not derived from TObject and no virtual table and no comment
case TStreamerInfo::kAnyPnoVT:
case TStreamerInfo::kAnyPnoVT + TStreamerInfo::kOffsetL:
return dtd_everyobj;
// Pointer to container with no virtual table (stl) and no comment
case TStreamerInfo::kSTLp:
// array of pointers to container with no virtual table (stl) and no comment
case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL:
return dtd_stlp;
// container with no virtual table (stl) and no comment
case TStreamerInfo::kSTL:
// array of containers with no virtual table (stl) and no comment
case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL:
case TStreamerInfo::kTObject + TStreamerInfo::kOffsetL:
case TStreamerInfo::kTNamed + TStreamerInfo::kOffsetL:
case TStreamerInfo::kObject: // Class derived from TObject
case TStreamerInfo::kAny: // Class NOT derived from TObject
case TStreamerInfo::kObject + TStreamerInfo::kOffsetL:
case TStreamerInfo::kAny + TStreamerInfo::kOffsetL:
return dtd_objects;
case TStreamerInfo::kTString + TStreamerInfo::kOffsetL:
return dtd_fixarray;
case TStreamerInfo::kTObject:
case TStreamerInfo::kTNamed:
case TStreamerInfo::kBase:
if (el->InheritsFrom(TStreamerBase::Class())) return dtd_base;
return dtd_object;
case TStreamerInfo::kStreamer:
case TStreamerInfo::kStreamLoop:
return dtd_any;
} // switch
return dtd_none;
}
//______________________________________________________________________________
const char* TXMLDtdGenerator::dtdBaseTypeName(int typ) {
switch (typ) {
case 0: fDtdBuf = xmlNames_Bool; break;
case TStreamerInfo::kChar: fDtdBuf = xmlNames_Char; break;
case TStreamerInfo::kShort: fDtdBuf = xmlNames_Short; break;
// case TStreamerInfo::kCounter:
case TStreamerInfo::kInt: fDtdBuf = xmlNames_Int; break;
case TStreamerInfo::kLong: fDtdBuf = xmlNames_Long; break;
case TStreamerInfo::kLong64: fDtdBuf = xmlNames_Long64; break;
case TStreamerInfo::kFloat: fDtdBuf = xmlNames_Float; break;
case TStreamerInfo::kDouble: fDtdBuf = xmlNames_Double; break;
case TStreamerInfo::kUChar: fDtdBuf = xmlNames_UChar; break;
case TStreamerInfo::kUShort: fDtdBuf = xmlNames_UShort; break;
// case TStreamerInfo::kBits:
case TStreamerInfo::kUInt: fDtdBuf = xmlNames_UInt; break;
case TStreamerInfo::kULong: fDtdBuf = xmlNames_ULong; break;
case TStreamerInfo::kULong64: fDtdBuf = xmlNames_ULong64; break;
// case TStreamerInfo::kDouble32: fDtdBuf = "Double_t"; break;
case 20: fDtdBuf = xmlNames_String; break;
default:
fDtdBuf = "";
}
return fDtdBuf.Data();
}
//______________________________________________________________________________
const char* TXMLDtdGenerator::dtdUseBaseType(TStreamerElement* el) {
if (el==0) return 0;
int typ = el->GetType() % 20;
if ((typ==TStreamerInfo::kUChar) &&
(el->GetTypeNameBasic()[0]=='B')) typ=0;
if (typ==TStreamerInfo::kCounter) typ = TStreamerInfo::kInt;
if (typ==TStreamerInfo::kBits) typ = TStreamerInfo::kUInt;
if (typ==TStreamerInfo::kDouble32) typ = TStreamerInfo::kDouble;
if (el->GetType() == TStreamerInfo::kTString + TStreamerInfo::kOffsetL) typ = 20;
fUsedBaseTypes[typ] = kTRUE;
return dtdBaseTypeName(typ);
}
void TXMLDtdGenerator::ProduceDtdForItem(ofstream& fs, const char* itemname) {
switch (GetXmlLayout()) {
case kSpecialized:
fs << "<!ELEMENT " << itemname << " EMPTY>" << endl;
fs << "<!ATTLIST " << itemname << " v CDATA #REQUIRED>" << endl;
break;
case kGeneralized:
break;
}
}
//______________________________________________________________________________
void TXMLDtdGenerator::ProduceObjectElement(ofstream& fs, const char* name, TClass* cl, Bool_t isPointer) {
TString elname(name);
if (!isPointer) {
fs << "<!ELEMENT " << elname << " (" << XmlConvertClassName(cl) << ")>" << endl;
return;
}
fs << "<!ELEMENT " << elname << " (#PCDATA";
TIter iter(&fClassSpace);
TClass* cl1;
while ((cl1 = (TClass*) iter()) != 0)
if ((cl==0) || cl1->InheritsFrom(cl))
fs << "|" << XmlConvertClassName(cl1);
fs << ")*>" << endl;
fs << "<!ATTLIST " << elname << " " << xmlNames_Ptr << " IDREF #IMPLIED>" << endl;
}
//______________________________________________________________________________
void TXMLDtdGenerator::ProduceDtdForBlackClass(ofstream& fs, TClass* cl) {
if (cl==0) return;
TString clname = XmlConvertClassName(cl);
fs << "<!ELEMENT " << clname << " (#PCDATA|" << xmlNames_Xmlobject << "|" << xmlNames_XmlBlock;
fs << "|" << xmlNames_Array;
for (int n=0;n<MaxBaseTypeNum;n++) {
const char* iname = dtdBaseTypeName(n);
if (strlen(iname)>0)
fs << "|" << iname;
}
fs << ")*>" << endl;
fs << "<!ATTLIST " << clname << endl;
if (IsUseNamespaces())
fs << " xmlns:" << clname << " CDATA "" << XmlClassNameSpaceRef(cl) << """ << endl;
fs << " " << xmlNames_ClassVersion << " CDATA #IMPLIED" << endl;
fs << " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
}
//______________________________________________________________________________
void TXMLDtdGenerator::ProduceDtdForInstrumentedClass(ofstream& fs, TStreamerInfo* info) {
if (info==0) return;
TString clname = XmlConvertClassName(info->GetClass());
fs << "<!ELEMENT " << clname << " ";
TObjArray* elements = info->GetElements();
if (elements==0) return;
bool first = true, canhasblock = true;
// producing list of elements inside class element
Int_t n;
for (n=0;n<=elements->GetLast();n++) {
TStreamerElement* el = dynamic_cast<TStreamerElement*> (elements->At(n));
Int_t typ = dtdType(el);
switch(typ) {
case dtd_none:
case dtd_attr:
continue;
case dtd_base:
fs << (first ? "(" : ","); first=false;
fs << XmlConvertClassName(el->GetClass());
canhasblock = true;
continue;
default:
fs << (first ? "(" : ","); first=false;
if (IsUseNamespaces())
fs << clname << ":";
fs << GetElName(el);
canhasblock = canhasblock ||
((typ!=dtd_elem) && (typ!=dtd_fixarray) && (typ!=dtd_array));
} // switch
}
if (canhasblock) {
fs << (first ? "(" : ","); first=false;
fs << xmlNames_XmlBlock << "?";
}
if (first) fs << "EMPTY>" << endl;
else fs << ")>" << endl;
// produce attribute list for class element
fs << "<!ATTLIST " << clname << endl;
if (IsUseNamespaces())
fs << " xmlns:" << clname << " CDATA "" << XmlClassNameSpaceRef(info->GetClass()) << """ << endl;
fs << " " << xmlNames_ClassVersion << " CDATA #IMPLIED" << endl;
for (n=0;n<=elements->GetLast();n++) {
TStreamerElement* el = dynamic_cast<TStreamerElement*> (elements->At(n));
if (dtdType(el) == dtd_attr)
fs << " " << GetElName(el) << " CDATA #REQUIRED" << endl;
}
fs << " " << xmlNames_Ref << " ID #IMPLIED>" << endl;
// produce description for each element
for (n=0;n<=elements->GetLast();n++) {
TStreamerElement* el = dynamic_cast<TStreamerElement*> (elements->At(n));
int eltype = dtdType(el);
Int_t arrlen = el->GetArrayLength();
TString elname(GetElName(el));
if (IsUseNamespaces())
elname = clname + ":" + elname;
switch(eltype) {
case dtd_none:
case dtd_attr:
continue;
case dtd_elem:
ProduceDtdForItem(fs, elname);
continue;
case dtd_charstar:
ProduceDtdForItem(fs, elname);
fs << "<!ATTLIST " << elname << " " << xmlNames_Size << " CDATA #REQUIRED>" << endl;
continue;
case dtd_fixarray: {
fs << "<!ELEMENT " << elname;
if (arrlen==0) fs << " EMPTY"; else
if (arrlen>10) fs << " (" << dtdUseBaseType(el) << "+)"; else {
fs << " (" << dtdUseBaseType(el);
for (int n=1;n<arrlen;n++)
fs << "," << dtdUseBaseType(el);
fs << ")";
}
fs << ">" << endl;
continue;
}
case dtd_array:
fs << "<!ELEMENT " << elname << " (" << dtdUseBaseType(el) << "*)>" << endl;
continue;
case dtd_fastobj1:
case dtd_fastobj2:
case dtd_everyobj:
case dtd_stlp:
case dtd_objects: {
if ((el->GetStreamer()!=0) && (eltype!=dtd_everyobj)) {
fs << "<!ELEMENT " << elname << " ANY>" << endl;
continue;
}
TString elitemname(GetElItemName(el));
if (IsUseNamespaces())
elitemname = clname + ":" + elitemname;
if (arrlen>1) {
fs << "<!ELEMENT " << elname << " (" << elitemname;
if (arrlen>10) fs << "+)>" << endl; else
for (int n=1;n<arrlen;n++)
fs << "," << elitemname;
fs << ")>" << endl;
ProduceObjectElement(fs, elitemname, el->GetClass(), eltype!=dtd_objects);
} else
ProduceObjectElement(fs, elname, el->GetClass(), eltype!=dtd_objects);
continue;
}
case dtd_object:
ProduceObjectElement(fs, elname, el->GetClass(), kFALSE);
continue;
case dtd_any:
fs << "<!ELEMENT " << elname << " ANY>" << endl;
continue;
default:
continue;
} // switch
}
fs << endl;
}
//______________________________________________________________________________
void TXMLDtdGenerator::ProduceGeneralDtd(ofstream& fs, TClass* onlyclass) {
if (onlyclass!=0) {
fs << "<!ELEMENT " << xmlNames_Root << " (" << xmlNames_Object << ")>" << endl;
fs << "<!ATTLIST " << xmlNames_Root << endl
<< " " << xmlNames_Setup << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
} else {
fs << "<!ELEMENT " << xmlNames_Root << " (" << xmlNames_Xmlkey << "*)>" << endl;
fs << "<!ATTLIST " << xmlNames_Root << endl
<< " " << xmlNames_Setup << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
fs << "<!ELEMENT " << xmlNames_Xmlkey << " (" << xmlNames_Object << ")>" << endl;
fs << "<!ATTLIST " << xmlNames_Xmlkey << endl
<< " " << xmlNames_Name << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Cycle << " CDATA #REQUIRED>" << endl << endl;
}
fs << "<!ELEMENT " << xmlNames_Object << " (" << xmlNames_Object << "|"
<< xmlNames_Member << "|"
<< xmlNames_Item << ")*>" << endl;
fs << "<!ATTLIST " << xmlNames_Object << endl
<< " " << xmlNames_Class << " CDATA #REQUIRED" << endl
<< " " << xmlNames_ClassVersion << " CDATA #IMPLIED" << endl
<< " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
fs << "<!ELEMENT " << xmlNames_Member << " (" << xmlNames_Object << "|" << xmlNames_Item << ")*>" << endl;
fs << "<!ATTLIST " << xmlNames_Member << endl;
fs << " " << xmlNames_Name << " CDATA #REQUIRED" << endl;
fs << " " << xmlNames_Type << " CDATA #REQUIRED" << endl;
fs << " " << xmlNames_Value << " CDATA #IMPLIED" << endl;
fs << " " << xmlNames_Size << " CDATA #IMPLIED" << endl;
fs << " " << xmlNames_Ptr << " IDREF #IMPLIED>" << endl << endl;
fs << "<!ELEMENT " << xmlNames_Item << " (" << xmlNames_Object << "|" << xmlNames_Item << ")*>" << endl;
fs << "<!ATTLIST " << xmlNames_Item << endl;
fs << " " << xmlNames_Type << " CDATA #REQUIRED" << endl;
fs << " " << xmlNames_Value << " CDATA #IMPLIED" << endl;
fs << " " << xmlNames_Size << " CDATA #IMPLIED" << endl;
fs << " " << xmlNames_Ptr << " IDREF #IMPLIED>" << endl << endl;
}
//______________________________________________________________________________
void TXMLDtdGenerator::ProduceSpecificDtd(ofstream& fs, TClass* onlyclass) {
int n;
for (n=0;n<MaxBaseTypeNum;n++)
fUsedBaseTypes[n] = kFALSE;
fClassSpace.Clear();
fClassSpace.AddAll(&fBlackClasses);
TIter iter(&fInstrumentedClasses);
TStreamerInfo* info = 0;
while ((info = (TStreamerInfo*)iter())!=0)
fClassSpace.Add(info->GetClass());
if (onlyclass!=0) {
if (fClassSpace.FindObject(onlyclass)==0)
fClassSpace.Add(onlyclass);
if (fInstrumentedClasses.FindObject(onlyclass->GetStreamerInfo())==0)
fInstrumentedClasses.Add(onlyclass->GetStreamerInfo());
fs << "<!ELEMENT " << xmlNames_Root << " (" << XmlConvertClassName(onlyclass) << ")>" << endl;
fs << "<!ATTLIST " << xmlNames_Root << endl
<< " " << xmlNames_Setup << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
} else {
fs << "<!ELEMENT " << xmlNames_Root << " (" << xmlNames_Xmlkey << "*)>" << endl;
fs << "<!ATTLIST " << xmlNames_Root << endl
<< " " << xmlNames_Setup << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Ref << " ID #IMPLIED>" << endl << endl;
fs << "<!ELEMENT " << xmlNames_Xmlkey << " (";
TIter it(&fClassSpace);
TClass* cl = 0;
bool first = true;
while ((cl = (TClass*) it()) != 0)
fs << (first ? first=false, "" : "|") << XmlConvertClassName(cl);
fs << ")>" << endl;
fs << "<!ATTLIST " << xmlNames_Xmlkey << endl
<< " " << xmlNames_Name << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Cycle << " CDATA #REQUIRED>" << endl << endl;
}
iter.Reset();
while ((info = (TStreamerInfo*)iter())!=0)
ProduceDtdForInstrumentedClass(fs, info);
TIter iter2(&fBlackClasses);
TClass* cl = 0;
while ((cl = (TClass*)iter2())!=0)
ProduceDtdForBlackClass(fs, cl);
/* if (fUsedBaseTypes[TStreamerInfo::kDouble32]) {
fUsedBaseTypes[TStreamerInfo::kDouble32] = kFALSE;
fUsedBaseTypes[TStreamerInfo::kDouble] = kTRUE;
}
*/
for (n=0;n<MaxBaseTypeNum;n++) {
const char* iname = dtdBaseTypeName(n);
if (strlen(iname)>0)
ProduceDtdForItem(fs, iname);
}
fs << "<!ELEMENT " << xmlNames_Array << " ";
bool first = true;
for (n=0;n<MaxBaseTypeNum;n++) {
const char* iname = dtdBaseTypeName(n);
if (strlen(iname)>0) {
fs << (first ? "(": "|") << iname;
first = false;
}
}
fs << ")*>" << endl;
fs << "<!ATTLIST " << xmlNames_Array << " " << xmlNames_Size << " CDATA #IMPLIED>" << endl;
if (fBlackClasses.GetLast()>=0) {
fs << endl << "<!ELEMENT " << xmlNames_XmlBlock << " (#PCDATA)>" << endl;
fs << "<!ATTLIST " << xmlNames_XmlBlock << endl
<< " " << xmlNames_Size << " CDATA #REQUIRED" << endl
<< " " << xmlNames_Zip << " CDATA #IMPLIED>" << endl;
ProduceObjectElement(fs, xmlNames_Xmlobject, 0, kTRUE);
}
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.