home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftptest.leeds.ac.uk
/
2015.02.ftptest.leeds.ac.uk.tar
/
ftptest.leeds.ac.uk
/
bionet
/
CAE-GROUP
/
SCL-WIN3x
/
SCLTEST.EXE
/
SCL2HTML
/
SCL2HTML.CC
< prev
next >
Wrap
Text File
|
1994-12-13
|
13KB
|
336 lines
/*
* scl2html.cc
*
* Ian Soboroff, NIST
* June, 1994
*
* scl2html is a program to lay out a given schema in HTML, suitable for
* hypertext browsing using Mosaic or any other HTML viewer/WWW surfboard.
* While this particular code as designed is linked to the Example schema
* (via tests.h), it can be "fed" any fedex_plus-compiled schema and give
* appropriate output.
*
* The Makefile defaults to building the app to use the example schema. To
* link to another schema, build the appropriate libraries for it and
* 'make SCHEMA_NAME=my-schema'. See the Makefile for more details.
*
* The executable is named after the schema you use, e.g., scl2html.example.
* This can be renamed to whatever you want.
*
* This program works by using the registry to walk through each entity type.
* At each entity, the supertypes, subtypes, and attributes are probed out
* and mapped into a relatively nifty-looking HTML format.
*
* This code was heavily inspired by the original scltest program,
* distributed with the DataProbe, v2.0.x.
*/
/* Since scl2html doesn't use any schema-specific things except the init
function, we don't need to include the schema's header file inside
tests.h */
#define DONT_NEED_HEADER
#include <tests.h>
#include "MyRegistry.h"
// PrintAttrTypeWithAnchor()
// Given an atribute, print out its immediate type (not fundamental).
// Ah, but if life were so simple. If this attribute is _not_ of a
// fundamental type, put in an anchor to somewhere with info on the type.
// This could be either the index page Type list, or an entity's page if
// the attribute is an entity.
// BUGS: (sort of) IMHO, the handling of aggregates here is a kludge, but
// it's a kludge without a solution I can see. While the dictionary has
// ways to show you what kinds of things an aggregate holds, it won't tell
// you what kind of _aggragation_ (no pun intended) you have, as in giving
// you a code or "Bag" or something by itself. It probably doesn't work
// aesthetically for compound aggregates (i.e., a list of lists).
void PrintAttrTypeWithAnchor(const TypeDescriptor *typeDesc, ofstream &outhtml)
{
// The type, as an integer. See src/clstepcore/baseType.h for info
int base = typeDesc->Type();
// the type descriptor for the "referent type," if any.
// This is NULL if the attribute is a fundamental type.
// All we use it for now is checking for NULL.
const TypeDescriptor *reference = typeDesc->ReferentType();
// Do we need an anchor?
int anchor = 0;
// First, figure out if we need an anchor...
if (reference) // if this has a referent type (i.e., is a non-base type)
{
if (base != 4) // anchor all non-bases except for aggregates
anchor = 1; // which we'll take care of recursively
}
else {
// entities and enumerations show up as base, but we want to
// anchor them anyway
if (base == 3 || base == 5) anchor = 1;
}
// Now, print type, with anchor if necessary
if (anchor && base != 3) {
// for regular TYPEs, anchor to the index at that definition
outhtml << "<A HREF=\"" << "index.html#";
outhtml << typeDesc->Name() << "\">";
}
else if (anchor && base == 3)
{
// for entities, anchor to that entity's page
outhtml << "<A HREF=\"" << typeDesc->Name();
outhtml << ".html\">";
}
outhtml << typeDesc->AttrTypeName();
if (base == 4)
{
outhtml << " (contains elements of type ";
PrintAttrTypeWithAnchor(typeDesc->AggrElemTypeDescriptor(), outhtml);
outhtml << ")" << endl;
}
if (anchor)
outhtml << "</A>";
}
// PrintAttrsHTML()
// Given an entity, print out to the HTML file an unordered list of
// the entity's attributes and their types. It returns the number of
// explicit attributes that the entity has.
int PrintAttrsHTML(const EntityDescriptor *ent, ofstream &outhtml)
{
int attrCount = 0;
// To traverse the attributes of the entity, we're going to use
// an iterator native to the class library. This could also have
// been done using GetHead() and NextNode() of the entity's attribute
// list (nearly identical to how the entity lists are traversed), see
// PrintParentAttrsHTML() and also main() below.
AttrDescItr aditr(ent->ExplicitAttr());
const AttrDescriptor *attrDesc = aditr.NextAttrDesc();
if (attrDesc != 0)
{
outhtml << "\n<! -- These are the attributes for entity ";
outhtml << ent->Name() << " >\n\n";
outhtml << "<UL>" << endl;
while (attrDesc != 0)
{
attrCount++;
outhtml << "<LI>" << attrDesc->Name() << " : ";
if ((LOGICAL)attrDesc->Optional() == sdaiTRUE)
outhtml << "optional ";
PrintAttrTypeWithAnchor(attrDesc->ReferentType(), outhtml);
outhtml << endl;
attrDesc = aditr.NextAttrDesc();
}
outhtml << "</UL>" << endl;
}
return attrCount;
}
// PrintParentAttrsHTML()
// This function, given an entity and its parent, recursively travels up
// the inheritance tree of the entity, printing to the HTML file a
// description-list structre showing all ancestors. For each ancestor,
// the attributes are printed using the PrintAttrsHTML() function above.
void PrintParentAttrsHTML (const EntityDescriptor* ent,
const EntityDescriptor *parent, ofstream &outhtml)
{
// Passing this function the pointer to ent is really cosmetic, so
// we can easily print out this 'header' information.
outhtml << "\n<! -- This is a parent of " << ent->Name() << ">\n\n";
outhtml << "<DL>" << endl;
outhtml << "<DT>" << ent->Name() << " inherits from ";
outhtml << "<A HREF=\"" << parent->Name() << ".html\">";
outhtml << parent->Name() << "</A>" << endl;
// Here we're going to traverse the list of supertypes of the parent
// using the EntityDescriptorList
const EntityDescriptorList *grandpaList = &(parent->Supertypes());
EntityDescLinkNode *grandpaNode =
(EntityDescLinkNode*)grandpaList->GetHead();
while (grandpaNode)
{
// for each "grandparent" of ent, inside a descriptor body (<DD>)
// recursively call this function... the 'while' takes care of
// multiple inheritance: for each grandparent, trace back.
outhtml << "<DD>" << endl;
const EntityDescriptor *grandpa = grandpaNode->EntityDesc();
PrintParentAttrsHTML(parent, grandpa, outhtml);
grandpaNode = (EntityDescLinkNode*)grandpaNode->NextNode();
}
// Now print the parent's atributes. This calls PrintAttrsHTML() to
// actually print any existing attributes, but to see if there are
// any, we'll check to see if the head of the atribute descriptor list
// exists. Conversely, once grabbing the head we could print out
// the attributes by following the list (attrNode->NextNode()).
const AttrDescriptorList *attrList = &(parent->ExplicitAttr());
AttrDescLinkNode *attrNode = (AttrDescLinkNode*)attrList->GetHead();
if (attrNode)
{
outhtml << "<DT>" << parent->Name();
outhtml << " has the following attributes" << endl;
outhtml << "<DD>" << endl;
if (PrintAttrsHTML(parent, outhtml) == 0)
outhtml << "<EM>none</EM>" << endl;
}
outhtml << "</DL>" << endl;
}
/******************** main() ****************************/
main()
{
// This has to be done before anything else. This initializes
// all of the registry information for the schema you are using.
// The SchemaInit() function is generated by fedex_plus... see
// extern statement above.
MyRegistry *registry = new MyRegistry(SchemaInit);
// Rather than using the standard Registry class here, as in the treg
// example, we are using MyRegistry, which is derived from the original.
// Registry doesn`t contain a facility for browsing the types, as it
// does schemas and entities... so I added it. See the file
// MyRegistry.h for details on how this was done.
// "Reset" has tables for browsing
registry->ResetEntities();
registry->ResetSchemas();
registry->ResetTypes();
const SchemaDescriptor *schema = registry->NextSchema();
int num_ents = registry->GetEntityCnt();
cout << "Processing schema " << schema->Name();
cout << " with " << num_ents << " entities." << endl;
// Set up root-level index of the schema, in a file called
// "index.html". In this document are links to all objects in
// the schema.
cout << "Creating 'index.html'" << endl;
ofstream root("index.html");
root << "<TITLE>" << schema->Name() << "</TITLE>" << endl;
root << "<H1>Schema: " << schema->Name() << "</H1>" << endl;
// Do Type-list
cout << "Processing types ";
root << "<HR>" << endl;
root << "<H2>Types</H2>" << endl;
root << "<UL>" << endl;
const TypeDescriptor *type;
SCLstring tmp;
type = registry->NextType();
root << "<! -- The following is a list of types, which are>\n";
root << "<! -- cross-referenced from the entities.>\n";
while (type != 0)
{
cout << ".";
root << "<LI><A NAME=\"" << type->Name() << "\">";
root << type->Name() << "</A>: ";
root << type->Description() << endl;
type = registry->NextType();
}
root << "</UL>" << endl;
cout << endl;
// Do entity root-section and pages
root << "<HR>" << endl;
root << "<H2>Entities</H2>" << endl;
root << "<UL>" << endl;
root << "<! -- These all lead to a page for each entity>\n";
// These are all pointers we need to wander around the registry
// information. We'll want to not only look at the current entity
// and its attributes, but also which entites are super- and subclasses
// of the current entity. Here, supers isn't really used beyond checking
// for ancestors, but we'll use subs to list subclasses and make links
// to them.
const EntityDescriptor *ent;
const EntityDescriptorList *supers;
const EntityDescriptorList *subs;
EntityDescLinkNode *entNode;
for (int i=0; i<num_ents; i++)
{
ent = registry->NextEntity();
cout << "Processing " << ent->Name() << endl;
// add anchor to root page
root << "<LI><A HREF=\"" << ent->Name() << ".html\">";
root << ent->Name() << "</A>" << endl;
// construct page for entity
char *tmpstr = new char[strlen(ent->Name()) + 6];
ofstream entout(strcat(strcpy(tmpstr,ent->Name()),".html"));
delete [] tmpstr;
entout << "<TITLE>Entity " << ent->Name() << "</TITLE>" << endl;
entout << "<H1>" << ent->Name() << "</H1>" << endl;
// supertypes
entout << "<HR>\n<H2>Inherited Attributes</H2>" << endl;
entout << "<! -- Below is the direct ancestry (if any) of ";
entout << ent->Name() << ">\n";
supers = &(ent->Supertypes());
entNode = (EntityDescLinkNode*)supers->GetHead();
if (!entNode)
entout << "<EM>none</EM>" << endl;
while (entNode)
{
// call PrintParentAttrsHTML to explore the parents
// of the entity, for each parent.
const EntityDescriptor *parent = entNode->EntityDesc();
PrintParentAttrsHTML(ent, parent, entout);
entNode = (EntityDescLinkNode*)entNode->NextNode();
}
// local attributes
entout << "<HR>\n<H2>Local Attributes</H2>" << endl;
if (PrintAttrsHTML(ent, entout) == 0)
entout << "<EM>none</EM>" << endl;
// subtypes
// We're going to traverse the subtypes by using the subtype list
// of the entity, a little more simply than in PrintParentAttrsHTML()
entout << "<HR>\n<H2>Subtypes</H2>" << endl;
entout << "<! -- The following entities inherit from this one>\n";
subs = &(ent->Subtypes());
entNode = (EntityDescLinkNode*)subs->GetHead();
if (entNode)
{
entout << "<UL>" << endl;
EntityDescriptor *child;
while (entNode)
{
child = entNode->EntityDesc();
entout << "<LI><A HREF=\"" << child->Name() << ".html\">";
entout << child->Name() << "</A>" << endl;
entNode = (EntityDescLinkNode*)entNode->NextNode();
}
entout << "</UL>" << endl;
}
else entout << "<EM>none</EM>" << endl;
entout << "<HR>" << endl;
entout << "Click <A HREF=\"index.html\">here</A> to ";
entout << "return to the index." << endl;
}
root << "</UL>" << endl;
cout << "Done!" << endl;
}