ReferToSquirrelHack.Mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Rick Beach, August 6, 1984 1:33:46 pm PDT
DIRECTORY
Commander,
DB,
FS,
IO,
Rope,
UserCredentials,
UserProfile
;
ReferToSquirrelHack: CEDAR PROGRAM
IMPORTS Commander, DB, FS, IO, Rope, UserCredentials, UserProfile = {
ROPE: TYPE = Rope.ROPE;
InitDB: PROC ~ {
ENABLE UNWIND => AbortDB[];
name, password: Rope.ROPE;
DB.Initialize[];
DB.DeclareSegment[filePath: UserProfile.Token["Squirrel.Segment"], segment: $Squirrel];
[name, password] ← UserCredentials.Get[];
DB.OpenTransaction[segment: $Squirrel, userName: name, password: password];
};
personDomain, documentDomain, collectionDomain, writtenWorkDomain, legalEntityDomain, organizationDomain, placeDomain, subjectDomain: DB.Domain;
authorRelation, referenceRelation, paperSourceRelation, physicalSourceRelation, publisherRelation, subjectAreaRelation, publicationDateRelation, editorRelation, locationRelation, noteRelation: DB.Relation;
authorOf, authorIs, paperSourceOf, paperSourceIs, vol, issue, pages, date, physicalSourceOf, physicalSourceIs, publisherOf, publisherIs, publisherId, referenceOf, referenceIs, subjectAreaOf, subjectAreaIs, publicationDateOf, publicationDateIs, editorOf, editorIs, editorAs, locationOf, locationIs, noteOf, noteIs: DB.Attribute;
InitSchema: PROC ~ {
ENABLE UNWIND => AbortDB[];
personDomain ← DB.DeclareDomain["Person", $Squirrel, OldOnly];
documentDomain ← DB.DeclareDomain["Document", $Squirrel, OldOnly];
collectionDomain ← DB.DeclareDomain["Collection", $Squirrel, OldOnly];
writtenWorkDomain ← DB.DeclareDomain["WrittenWork", $Squirrel, OldOnly];
legalEntityDomain ← DB.DeclareDomain["LegalEntity", $Squirrel, OldOnly];
organizationDomain ← DB.DeclareDomain["Organization", $Squirrel, OldOnly];
placeDomain ← DB.DeclareDomain["Place", $Squirrel, OldOnly];
subjectDomain ← DB.DeclareDomain["Subject", $Squirrel, OldOnly];
authorRelation ← DB.DeclareRelation["author", $Squirrel, OldOnly];
authorOf ← DB.DeclareAttribute[authorRelation, "of", documentDomain];
authorIs ← DB.DeclareAttribute[authorRelation, "is", personDomain];
paperSourceRelation ← DB.DeclareRelation["paper-source", $Squirrel, OldOnly];
paperSourceOf ← DB.DeclareAttribute[paperSourceRelation, "of", documentDomain];
paperSourceIs ← DB.DeclareAttribute[paperSourceRelation, "is", collectionDomain];
vol ← DB.DeclareAttribute[paperSourceRelation, "vol", DB.RopeType];
issue ← DB.DeclareAttribute[paperSourceRelation, "issue", DB.RopeType];
pages ← DB.DeclareAttribute[paperSourceRelation, "pages", DB.RopeType];
date ← DB.DeclareAttribute[paperSourceRelation, "date", DB.RopeType];
physicalSourceRelation ← DB.DeclareRelation["physical-source", $Squirrel, OldOnly];
physicalSourceOf ← DB.DeclareAttribute[physicalSourceRelation, "of", writtenWorkDomain];
physicalSourceIs ← DB.DeclareAttribute[physicalSourceRelation, "is", legalEntityDomain];
publisherRelation ← DB.DeclareRelation["publisher", $Squirrel, OldOnly];
publisherOf ← DB.DeclareAttribute[publisherRelation, "of", writtenWorkDomain];
publisherIs ← DB.DeclareAttribute[publisherRelation, "is", organizationDomain];
publisherId ← DB.DeclareAttribute[publisherRelation, "id", DB.RopeType];
referenceRelation ← DB.DeclareRelation["reference", $Squirrel, OldOnly];
referenceOf ← DB.DeclareAttribute[referenceRelation, "of", documentDomain];
referenceIs ← DB.DeclareAttribute[referenceRelation, "is", documentDomain];
subjectAreaRelation ← DB.DeclareRelation["subject-area", $Squirrel, OldOnly];
subjectAreaOf ← DB.DeclareAttribute[subjectAreaRelation, "of", writtenWorkDomain];
subjectAreaIs ← DB.DeclareAttribute[subjectAreaRelation, "is", subjectDomain];
publicationDateRelation ← DB.DeclareRelation["publication-date", $Squirrel, OldOnly];
publicationDateOf ← DB.DeclareAttribute[publicationDateRelation, "of", writtenWorkDomain];
publicationDateIs ← DB.DeclareAttribute[publicationDateRelation, "is", DB.RopeType];
editorRelation ← DB.DeclareRelation["editor", $Squirrel, OldOnly];
editorOf ← DB.DeclareAttribute[editorRelation, "of", collectionDomain];
editorIs ← DB.DeclareAttribute[editorRelation, "is", personDomain];
editorAs ← DB.DeclareAttribute[editorRelation, "as", DB.RopeType];
locationRelation ← DB.DeclareRelation["location", $Squirrel, OldOnly];
locationOf ← DB.DeclareAttribute[locationRelation, "of", legalEntityDomain];
locationIs ← DB.DeclareAttribute[locationRelation, "is", placeDomain];
noteRelation ← DB.DeclareRelation["note", $Squirrel, OldOnly];
noteOf ← DB.DeclareAttribute[noteRelation, "of", DB.AnyDomainType];
noteIs ← DB.DeclareAttribute[noteRelation, "is", DB.RopeType];
};
DoIt: PROC [log: IO.STREAM, fileName: ROPE] ~ {
ENABLE UNWIND => AbortDB[];
referStream: IO.STREAM ~ FS.StreamOpen[fileName];
ReadNextReferCitation: PROC [s: IO.STREAM] ~ {
line: ROPE ← s.GetLineRope[];
key: ReferKey;
FOR key IN ['A..'Z] DO referList[key] ← NIL; ENDLOOP;
WHILE line # NIL AND line.Length > 1 DO
IF line.Length <= 3 OR line.Fetch[0] # '% OR NOT line.Fetch[1] IN ['A..'Z] OR line.Fetch[2] # ' THEN
log.PutF["line missing valid Refer keyword (ignored):\n \"%g\"\n", IO.rope[line]]
ELSE {
key ← line.Fetch[1];
referList[key] ← AppendToList[referList[key], LIST[line.Substr[3]]];
};
IF NOT s.EndOf THEN line ← s.GetLineRope[] ELSE line ← NIL;
ENDLOOP;
};
ReverseAuthorName: PROC [rope: ROPE] RETURNS [ROPE] ~ {
junior: ROPE;
commaLoc: INT ~ rope.Find[","];
spaceLoc: INT;
IF commaLoc # -1 THEN {
junior ← rope.Substr[commaLoc+2];
rope ← rope.Substr[0, commaLoc-1];
};
spaceLoc ← rope.Find[" "];
FOR nextSpace: INT ← rope.Find[" ", spaceLoc+1], rope.Find[" ", spaceLoc+1] WHILE nextSpace # -1 DO
spaceLoc ← nextSpace;
ENDLOOP;
rope ← Rope.Cat[rope.Substr[spaceLoc+1, rope.Length], ", ", rope.Substr[0, spaceLoc]];
IF NOT junior.IsEmpty THEN rope ← rope.Cat[" ", junior];
RETURN [rope]
};
ErrorLog: PROC [message: ROPE] ~ {
log.PutRope["***"];
log.PutRope[message];
log.PutRope["\n"];
errors ← TRUE;
};
errors: BOOLEANFALSE;
document, collection, author, editor, publisher, city, subject, report: DB.Entity;
authorRelship, publicationDateRelship, paperSourceRelship, editorRelship, publisherRelship, locationRelship, noteRelship, subjectAreaRelship: DB.Relship;
attributeList: DB.AttributeValueList;
AppendAttribute: PROC [list: DB.AttributeValueList, attribute: DB.AttributeValue] RETURNS [newList: DB.AttributeValueList] ~ {
z: DB.AttributeValueList ← list;
IF z = NIL THEN RETURN [LIST[attribute]];
newList ← list;
UNTIL (list ← list.rest) = NIL DO
z ← list;
ENDLOOP;
z.rest ← LIST[attribute];
RETURN [newList];
};
ConsistencyCheck: PROC ~ {
Consistency checks on the Refer citation
Only one of each of the following
IF NOT (ZeroOrOneInstance['B] AND ZeroOrOneInstance['C] AND ZeroOrOneInstance['D] AND ZeroOrOneInstance['I] AND ZeroOrOneInstance['J] AND ZeroOrOneInstance['N] AND ZeroOrOneInstance['P] AND ZeroOrOneInstance['R] AND ZeroOrOneInstance['T] AND ZeroOrOneInstance['V]) THEN
ErrorLog["more than one of B, C, D, I, J, N, P, R, T, V fields"];
Either a Book or a Journal but not both
IF OneInstance['B] AND OneInstance['J] THEN
ErrorLog["can't handle both a book and journal title"];
Either a Report or a Journal but not both
IF OneInstance['R] AND OneInstance['N] THEN
ErrorLog["can't handle both a report name and an issue number"];
If a City then there must be an Institution
IF OneInstance['C] AND NoInstance['I] THEN
ErrorLog["can't handle a city field without an instituion"];
If no Title then there must be a Book title
IF NoInstance['T] AND NoInstance['B] THEN
ErrorLog["need a title or book title"];
If an Editor then there must be a Book or Journal
IF OneOrMoreInstances['E] AND (NoInstance['B] AND NoInstance['J]) THEN
ErrorLog["can't handle an editor without a book or journal"];
};
DeclareEntity: PROC [domain: DB.Domain, name: ROPE, version: DB.Version ← NewOrOld] RETURNS [entity: DB.Entity] ~ {
entity ← DB.DeclareEntity[domain, name, OldOnly];
IF entity#NIL THEN {
log.PutF["Entity previously existed: %g\n", IO.rope[name]];
RETURN[entity];
};
IF version = NewOrOld THEN {
entity← DB.DeclareEntity[domain, name, NewOrOld];
};
RETURN[entity];
};
DeclareRelship: PROC [relation: DB.Relation, list: DB.AttributeValueList, version: DB.Version ← NewOrOld] RETURNS [relship: DB.Relship] ~ {
relship ← DB.DeclareRelship[relation, list, OldOnly];
IF relship#NIL THEN {
log.PutF["Relship previously existed\n"];
RETURN[relship];
};
IF version = NewOrOld THEN {
relship← DB.DeclareRelship[relation, list, NewOrOld !
DB.Error => {log.PutF["*** Relship could not be created for some reason\n"]; CONTINUE}];
};
RETURN[relship];
};
EnterReferCitation: PROC ~ {
Nullify those entities used for logic purposes!
document ← collection ← NIL;
IF OneInstance['T] THEN {
document ← DeclareEntity[documentDomain, FirstInstance['T]];
IF OneInstance['B] OR OneInstance['J] THEN
collection ← DeclareEntity[collectionDomain, IF OneInstance['B] THEN FirstInstance['B] ELSE FirstInstance['J]];
}
ELSE {
document ← DeclareEntity[documentDomain, IF OneInstance['B] THEN FirstInstance['B] ELSE FirstInstance['J]];
};
FOR authorName: ROPE ← FirstInstance['A], FirstInstance['A] WHILE NOT authorName.IsEmpty[] DO
author ← DeclareEntity[personDomain, ReverseAuthorName[authorName]];
authorRelship ← DeclareRelship[authorRelation, LIST[[authorOf, document], [authorIs, author]]];
ENDLOOP;
IF collection = NIL THEN {
IF OneInstance['D] THEN
publicationDateRelship ← DeclareRelship[publicationDateRelation, LIST[[publicationDateOf, document], [publicationDateIs, FirstInstance['D]]]];
IF OneInstance['R] THEN {
report ← DeclareEntity[collectionDomain, FirstInstance['R]];
paperSourceRelship ← DeclareRelship[paperSourceRelation, LIST[[paperSourceOf, document], [paperSourceIs, report]]];
};
}
ELSE {
attributeList ← LIST[[paperSourceOf, document], [paperSourceIs, collection]];
IF OneInstance['V] THEN
attributeList ← AppendAttribute[attributeList, [vol, FirstInstance['V]]];
IF OneInstance['D] THEN
attributeList ← AppendAttribute[attributeList, [date, FirstInstance['D]]];
IF OneInstance['N] OR OneInstance['R] THEN
attributeList ← AppendAttribute[attributeList, [issue, IF OneInstance['N] THEN FirstInstance['N] ELSE FirstInstance['R]]];
IF OneInstance['P] THEN
attributeList ← AppendAttribute[attributeList, [pages, FirstInstance['P]]];
paperSourceRelship ← DeclareRelship[paperSourceRelation, attributeList];
FOR editorName: ROPE ← FirstInstance['E], FirstInstance['E] WHILE NOT editorName.IsEmpty[] DO
editor ← DeclareEntity[personDomain, ReverseAuthorName[editorName]];
editorRelship ← DeclareRelship[editorRelation, LIST[[editorOf, collection], [editorIs, editor]]];
ENDLOOP;
};
IF OneInstance['I] THEN {
publisher ← DeclareEntity[organizationDomain, FirstInstance['I]];
publisherRelship ← DeclareRelship[publisherRelation, LIST[[publisherOf, IF collection # NIL THEN collection ELSE document], [publisherIs, publisher]]];
IF OneInstance['C] THEN {
city ← DeclareEntity[placeDomain, FirstInstance['C]];
locationRelship ← DeclareRelship[locationRelation, LIST[[locationOf, publisher], [locationIs, city]]];
};
};
FOR subjectArea: ROPE ← FirstInstance['K], FirstInstance['K] WHILE NOT subjectArea.IsEmpty[] DO
subject ← DeclareEntity[subjectDomain, subjectArea];
subjectAreaRelship ← DeclareRelship[subjectAreaRelation, LIST[[subjectAreaOf, document], [subjectAreaIs, subject]]];
ENDLOOP;
IF OneOrMoreInstances['O] OR OneOrMoreInstances['G] THEN {
noteRope: ROPENIL;
FOR notePiece: ROPE ← FirstInstance['G], FirstInstance['G] WHILE NOT notePiece.IsEmpty[] DO
noteRope ← noteRope.Cat[notePiece, "\n"];
ENDLOOP;
FOR notePiece: ROPE ← FirstInstance['O], FirstInstance['O] WHILE NOT notePiece.IsEmpty[] DO
noteRope ← noteRope.Cat[notePiece, "\n"];
ENDLOOP;
IF NOT noteRope.IsEmpty THEN
noteRelship ← DeclareRelship[noteRelation, LIST[[noteOf, document], [noteIs, noteRope]]];
};
};
PutCitation: PROC [s: IO.STREAM] ~ {
FOR key: ReferKey IN ['A..'Z] DO
IF referList[key] # NIL THEN
FOR list: LIST OF ROPE ← referList[key], list.rest WHILE list # NIL DO
s.PutF["%%%c %g\n", IO.char[key], IO.rope[list.first]];
ENDLOOP;
ENDLOOP;
};
log.PutF["got here at %g\n", IO.time[]];
log.PutRope["got here\n"];
WHILE NOT referStream.EndOf[] DO
ReadNextReferCitation[referStream];
log.PutRope["\nStarting next citation . . .\n"];
PutCitation[log];
errors ← FALSE;
ConsistencyCheck[];
IF errors THEN LOOP;
EnterReferCitation[];
IF NOT EmptyReferList[] THEN {
log.PutRope["*** Citation was not emptied. . . \n"];
PutCitation[log];
};
ENDLOOP;
log.PutRope["\n. . . Done\n"];
};
CloseDB: PROC ~ {
DB.CloseTransaction[trans: DB.GetSegmentInfo[$Squirrel].trans];
};
AbortDB: PROC ~ {
DB.AbortTransaction[trans: DB.GetSegmentInfo[$Squirrel].trans];
};
ReferKey: TYPE = CHARACTER ['A..'Z];
referList: ARRAY ReferKey OF LIST OF ROPE;
NoInstance: PROC [key: ReferKey] RETURNS [BOOL] ~ {
RETURN [referList[key] = NIL];
};
OneOrMoreInstances: PROC [key: ReferKey] RETURNS [BOOL] ~ {
RETURN [NOT NoInstance[key]];
};
OneInstance: PROC [key: ReferKey] RETURNS [BOOL] ~ {
RETURN [referList[key] # NIL AND referList[key].rest = NIL];
};
ZeroOrOneInstance: PROC [key: ReferKey] RETURNS [BOOL] ~ {
RETURN [NoInstance[key] OR OneInstance[key]];
};
FirstInstance: PROC [key: ReferKey] RETURNS [r: ROPE] ~ {
IF NoInstance[key] THEN RETURN [NIL];
r ← referList[key].first;
referList[key] ← referList[key].rest;
RETURN [r];
};
EmptyReferList: PROC RETURNS [BOOL] ~ {
FOR key: ReferKey IN ['A..'Z] DO
IF referList[key] # NIL THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE];
};
AppendToList: PROC [l1, l2: LIST OF ROPE] RETURNS [list: LIST OF ROPE] ~ {
z: LIST OF ROPE ← l1;
IF z = NIL THEN RETURN [l2];
list ← l1;
UNTIL (l1 ← l1.rest) = NIL DO
z ← l1;
ENDLOOP;
z.rest ← l2;
RETURN [list];
};
Command: Commander.CommandProc ~ {
cmdStream: IO.STREAM ~ IO.RIS[cmd.commandLine];
fileName: ROPEIO.GetTokenRope[cmdStream, IO.IDProc].token;
checkOnly: BOOLEANFALSE;
IF fileName.Fetch[0] = '- THEN {
checkOnly ← fileName.Fetch[1] = 'c;
fileName ← IO.GetTokenRope[cmdStream, IO.IDProc].token;
};
InitDB[];
InitSchema[];
DoIt[cmd.out, fileName];
IF checkOnly THEN AbortDB[] ELSE CloseDB[];
};
Commander.Register[key: "ReferToSquirrelHack", proc: Command, doc: "{𡤌heck} <refer-filename> just a quick hack to enter refer-format citations in my Squirrel database"];
}.