-- File: DomainNutImpl.mesa -- Contents: Implementation of the Domain Nut windows. -- Last edited by: -- Willie-Sue on: February 22, 1983 3:49 pm -- Cattell on: June 6, 1983 1:23 pm -- Maxwell on: June 3, 1982 9:27 am -- Donahue on: April 11, 1983 4:56 pm DIRECTORY Buttons USING [ButtonProc], DB, InputFocus USING [SetInputFocus], Menus USING [AppendMenuEntry, CreateMenu, Menu, MenuProc], Nut, NutOps, NutViewer, Rope, Schema, SystemNuts, ViewerOps, ViewerTools, ViewerClasses; DomainNutImpl: CEDAR PROGRAM IMPORTS DB, Nut, NutOps, InputFocus, Menus, Schema, NutViewer, Rope, ViewerOps, ViewerTools EXPORTS SystemNuts = BEGIN OPEN DB, NutViewer, Schema, ViewerTools; Viewer: TYPE = ViewerClasses.Viewer; AttributeFieldObject: TYPE = RECORD[ attribute: Attribute, property: Attribute ]; AttributeFieldHandle: TYPE = REF AttributeFieldObject; EntityFieldObject: TYPE = RECORD[ entity: Entity ]; EntityFieldHandle: TYPE = REF EntityFieldObject; displayerMenu: Menus.Menu = Menus.CreateMenu[]; editorMenu: Menus.Menu = Menus.CreateMenu[]; BuildMenus: PROC = BEGIN OPEN NutViewer; Menus.AppendMenuEntry[ displayerMenu, MakeMenuEntry[DBQueue[], "Edit", EditProc]]; Menus.AppendMenuEntry[ displayerMenu, MakeMenuEntry[DBQueue[], "Freeze", DefaultFreezeProc]]; Menus.AppendMenuEntry[ editorMenu, MakeMenuEntry[DBQueue[], "Erase", EraseProc]]; Menus.AppendMenuEntry[ editorMenu, MakeMenuEntry[DBQueue[], "Rename", RenameProc]]; Menus.AppendMenuEntry[ editorMenu, MakeMenuEntry[DBQueue[], "Save", SaveProc]]; Menus.AppendMenuEntry[ editorMenu, MakeMenuEntry[DBQueue[], "Reset", ResetProc]]; END; EditProc: Menus.MenuProc = -- Copied from NutDefaultImpl.EditDisplayerProc { viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ ViewerOps.FetchProp[viewer, $DomainInfo] ]; seg: DB.Segment = dInfo.segment; dName: ROPE = dInfo.dName; InputFocus.SetInputFocus[]; [] _ Nut.Edit[d: DomainDomain, eName: dName, parent: viewer, method: replace, seg: seg]}; DomainQueryer: PUBLIC Nut.QueryProc = BEGIN Message[NIL, "Domain queryers not implemented!"]; END; ---------------------------- DomainCreate: PUBLIC Nut.CreateProc = { RETURN[ Nut.DefaultCreate[nutType, d, eName, seg, column] ] }; DomainDisplayer: PUBLIC Nut.DisplayProc = BEGIN lastViewer: Viewer; dInfo: DomainInfo = NEW[ DomainInfoRecord ]; ViewerOps.SetMenu[newV, displayerMenu]; dInfo.dName _ NameOf[e]; dInfo.segment _ seg; dInfo.domain _ e; lastViewer_ NutViewer.Initialize[newV]; ViewerOps.AddProp[newV, $DomainInfo, dInfo]; IF NutOps.IsSystemDomain[e] THEN lastViewer _ NutViewer.MakeLabel["", lastViewer] ELSE {lastViewer_ NutViewer.MakeLabel[ name: "Relation / attribute / uniqueness for attributes that reference this domain:", sib: lastViewer]; lastViewer_ BuildInfoWindowButtons[lastViewer, e]}; BuildEntityWindowButtons[lastViewer, e, seg]; ViewerOps.PaintViewer[newV, client]; END; BuildInfoWindowButtons: PROC[lastViewer: Viewer, e: Entity] RETURNS[newLastViewer: Viewer]= BEGIN rs: RelshipSet; r: Relship; other: Domain; myAttrs: AttributeList = GetDomainRefAttributes[e]; FOR alT: AttributeList_ myAttrs, alT.rest UNTIL alT=NIL DO lastViewer_ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: GetName[V2E[GetP[alT.first, aRelationIs]]], proc: ProcessAttributeSelection, data: NEW[AttributeFieldObject_ [alT.first, aRelationIs]], sib: lastViewer, newLine: TRUE]; lastViewer_ NutViewer.MakeButton [q: NutViewer.DBQueue[], name: GetName[alT.first], proc: ProcessAttributeSelection, data: NEW[AttributeFieldObject_ [alT.first, NIL]], sib: lastViewer]; lastViewer_ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: GetName[V2E[GetP[alT.first, aTypeIs]]], proc: ProcessAttributeSelection, data: NEW[AttributeFieldObject_ [alT.first, aTypeIs]], sib: lastViewer]; lastViewer_ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: NutOps.GetUniquenessString[alT.first], proc: ProcessAttributeSelection, data: NEW[AttributeFieldObject_ [alT.first, NIL]], sib: lastViewer]; ENDLOOP; lastViewer_ NutViewer.MakeLabel["Related domains:", lastViewer, TRUE]; rs_ RelationSubset[dSubType, LIST[[dSubTypeIs, e]]]; UNTIL Null[r_ NextRelship[rs]] DO other_ V2E[GetF[r, dSubTypeOf]]; lastViewer_ NutViewer.MakeLabel["Supertype:", lastViewer, TRUE]; lastViewer_ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: GetName[other], proc: ProcessEntitySelection, data: NEW[EntityFieldObject_ [other]], sib: lastViewer]; ENDLOOP; ReleaseRelshipSet[rs]; rs_ RelationSubset[dSubType, LIST[[dSubTypeOf, e]]]; UNTIL Null[r_ NextRelship[rs]] DO other_ V2E[GetF[r, dSubTypeIs]]; lastViewer_ NutViewer.MakeLabel["Subtype:", lastViewer, TRUE]; lastViewer_ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: GetName[other], proc: ProcessEntitySelection, data: NEW[EntityFieldObject_ [other]], sib: lastViewer]; ENDLOOP; ReleaseRelshipSet[rs]; RETURN[lastViewer] END; BuildEntityWindowButtons: PROC[lastViewer: Viewer, e: Entity, seg: Segment] = -- display all the entities in domain e BEGIN count: INT_ 0; t: Entity; myEntities: EntitySet; lastViewer_ NutViewer.MakeLabel[ name: "List of the entities of this domain:", sib: lastViewer, newLine: TRUE]; IF Eq[e, DomainDomain] THEN { lastViewer _ NewEntity[RelationDomain, lastViewer]; lastViewer _ NewEntity[AttributeDomain, lastViewer]; lastViewer _ NewEntity[DataTypeDomain, lastViewer]; lastViewer _ NewEntity[IndexDomain, lastViewer]; lastViewer _ NewEntity[IndexFactorDomain, lastViewer] }; IF Eq[e, RelationDomain] THEN { lastViewer _ NewEntity[dSubType, lastViewer]; lastViewer _ NewEntity[aRelation, lastViewer]; lastViewer _ NewEntity[aType, lastViewer]; lastViewer _ NewEntity[aUniqueness, lastViewer]; lastViewer _ NewEntity[aLength, lastViewer]; lastViewer _ NewEntity[aLink, lastViewer]; lastViewer _ NewEntity[ifIndex, lastViewer]; lastViewer _ NewEntity[ifAttribute, lastViewer] }; IF Eq[e, AttributeDomain] THEN { [] _ NutViewer.MakeLabel[ name: "(Not implemented)", sib: lastViewer, newLine: TRUE]; RETURN}; IF Eq[e, IndexDomain] THEN { [] _ NutViewer.MakeLabel[ name: "(Not implemented)", sib: lastViewer, newLine: TRUE]; RETURN}; IF Eq[e, IndexFactorDomain] THEN { [] _ NutViewer.MakeLabel[ name: "(Not implemented)", sib: lastViewer, newLine: TRUE]; RETURN}; IF Eq[e, DataTypeDomain] THEN { lastViewer _ NewEntity[StringType, lastViewer]; lastViewer _ NewEntity[IntType, lastViewer]; lastViewer _ NewEntity[BoolType, lastViewer]; lastViewer _ NewEntity[TimeType, lastViewer]; RETURN}; myEntities _ IF Eq[e, DomainDomain] OR Eq[e, RelationDomain] THEN DomainSubset[d: e, searchSegment: seg] ELSE -- sort-- DomainSubset[e, "", "\177"]; UNTIL Null[t_ NextEntity[myEntities]] DO IF (count_ count+1)>200 THEN {lastViewer_ NutViewer.MakeLabel[ "... more than 200 entities: remainder truncated ...", lastViewer, TRUE]; EXIT} ELSE lastViewer_ NewEntity[t, lastViewer]; ENDLOOP; ReleaseEntitySet[myEntities]; END; NewEntity: PROC[t: Entity, sib: Viewer] RETURNS[Viewer] = {RETURN[NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: GetName[t], proc: ProcessEntitySelection, data: NEW[EntityFieldObject_ [t]], sib: sib, newLine: TRUE]]}; ProcessEntitySelection: Buttons.ButtonProc = BEGIN fd: EntityFieldHandle = NARROW[clientData]; viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ ViewerOps.FetchProp[viewer.parent, $DomainInfo] ]; []_ Nut.Display[e: fd.entity, parent: viewer.parent, seg: dInfo.segment] END; ProcessAttributeSelection: Buttons.ButtonProc = BEGIN fd: AttributeFieldHandle = NARROW[clientData]; v: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ ViewerOps.FetchProp[v.parent, $DomainInfo] ]; IF fd.property = NIL THEN Message[v, "Not an entity-valued field"] ELSE []_ Nut.Display[ e: V2E[GetP[fd.attribute, fd.property]], parent: v.parent, seg: dInfo.segment]; END; RenameProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; dInfo.dName_ ViewerTools.GetSelectionContents[]; IF dInfo.domain#NIL THEN SetName[dInfo.domain, dInfo.dName]; viewer.name_ Rope.Cat["Domain: ", dInfo.dName]; ViewerOps.PaintViewer[viewer, caption]; END; ResetProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; viewer.child _ NIL; ViewerOps.PaintViewer[viewer, client]; DomainEditor[DomainDomain, GetContents[dInfo.name], viewer, dInfo.segment]; END; SaveProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; SaveDomain[viewer]; END; EraseProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; dInfo: DomainInfo = NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; name: ROPE = IF dInfo # NIL THEN GetContents[dInfo.name] ELSE NIL; domain: Domain = IF name # NIL THEN DeclareDomain[name, dInfo.segment, OldOnly] ELSE NIL; subTypes: BOOLEAN _ FALSE; IF domain = NIL THEN RETURN; DestroyDomain[domain ! DB.Error => { IF code = NotImplemented THEN {subTypes _ TRUE; CONTINUE} }]; IF subTypes THEN {Message[viewer, "You must delete the subtypes first."]; RETURN} END; -- Domain Editor -- DomainEditor: PUBLIC Nut.EditProc = -- d: Domain, eName: ROPE, newV: Viewer BEGIN rope: ROPE; rs: RelshipSet; lastV: Viewer; relation: Relation; info: DomainInfo = NEW[DomainInfoRecord]; subTypeRS: Relship; isAttribute: Attribute; list: LIST OF Attribute; attributes: AttributeList; segment: Segment = seg; IF Rope.Equal[eName, "Domain", FALSE] THEN { [] _ Nut.Edit[d, "NEW", segment, newV]; RETURN}; IF Rope.Equal[eName, "Relation", FALSE] THEN { [] _ Nut.Edit[RelationDomain, "NEW", segment, newV]; RETURN}; IF Rope.Equal[eName, "Attribute", FALSE] OR Rope.Equal[eName, "DataType", FALSE] THEN {[] _ NutViewer.Message[NIL, eName, " is a system entity. You may not edit it."]; RETURN}; ViewerOps.SetMenu[newV, editorMenu]; lastV_ NutViewer.Initialize[newV]; info.segment _ segment; info.domain _ FetchEntity[d, eName, segment]; lastV _ NutViewer.MakeLabel["", lastV]; info.name_ lastV_ NutViewer.NextRightTextViewer[lastV, 400]; lastV _ NutViewer.MakeLabel["superTypes:", lastV, FALSE]; info.superTypes_ lastV _ NutViewer.NextRightTextViewer[lastV, 400]; lastV _ NutViewer.MakeLabel["subTypes:", lastV, TRUE]; info.subTypes _ NutViewer.NextRightTextViewer[lastV, 400]; lastV _ NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: "NEW PROPERTY", proc: NewAttribute, sib: lastV, border: TRUE, newLine: TRUE]; SetContents[info.name, eName]; IF info.domain = NIL THEN {ViewerOps.AddProp[newV, $DomainInfo, info]; RETURN}; -- print the subtypes of the domain rope _ NIL; rs _ RelationSubset[dSubType, LIST[[dSubTypeOf, info.domain]]]; WHILE (subTypeRS _ NextRelship[rs]) # NIL DO IF rope # NIL THEN rope _ Rope.Concat[rope, ", "]; rope _ Rope.Concat[rope, GetFS[subTypeRS, dSubTypeIs]]; ENDLOOP; ReleaseRelshipSet[rs]; SetContents[info.subTypes, rope]; info.subTypes.newVersion _ FALSE; -- print the supertypes of the domain rope _ NIL; rs _ RelationSubset[dSubType, LIST[[dSubTypeIs, info.domain]]]; WHILE (subTypeRS _ NextRelship[rs]) # NIL DO IF rope # NIL THEN rope _ Rope.Concat[rope, ", "]; rope _ Rope.Concat[rope, GetFS[subTypeRS, dSubTypeOf]]; ENDLOOP; ReleaseRelshipSet[rs]; SetContents[info.superTypes, rope]; info.superTypes.newVersion _ FALSE; -- print the current properties list _ NutOps.GetRefAttributes[info.domain]; FOR list _ list, list.rest WHILE list # NIL DO -- find all of the "of" attributes IF Null[list.first] THEN LOOP; IF ~Rope.Equal[GetName[list.first], "of"] THEN LOOP; IF ~Eq[V2E[GetP[list.first, aTypeIs]], info.domain] THEN LOOP; -- skip superclasses IF LOOPHOLE[V2U[GetP[list.first, aUniquenessIs]], Uniqueness] # Key THEN LOOP; -- we have a likely candidate relation _ NutOps.GetRelation[list.first]; attributes _ NutOps.AttributesOf[relation]; IF attributes = NIL OR attributes.rest = NIL OR attributes.rest.rest # NIL THEN LOOP; isAttribute _ NIL; IF Rope.Equal[GetName[attributes.first], "is"] THEN isAttribute _ attributes.first; IF Rope.Equal[GetName[attributes.rest.first], "is"] THEN isAttribute _ attributes.rest.first; IF isAttribute = NIL THEN LOOP; info.properties _ CONS[DisplayAttribute[relation, isAttribute, lastV], info.properties]; lastV _ info.properties.first.length; ENDLOOP; info.properties _ Reverse[info.properties]; ViewerOps.AddProp[newV, $DomainInfo, info]; END; SaveDomain: PROCEDURE[viewer: Viewer] = BEGIN new: Domain; info: DomainInfo; ok, copy: BOOLEAN _ TRUE; info _ NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; -- will we have to copy the domain? IF info.domain = NIL THEN copy _ TRUE ELSE IF ~Optimized[info.domain] THEN copy _ FALSE ELSE {subType: ROPE; [subType, , ] _ NextName[GetContents[info.subTypes]]; copy _ (subType.Length[] # 0)}; IF copy THEN new _ DeclareDomain[NIL, info.segment] ELSE new _ info.domain; -- check to see if this is a legal edit IF ~CheckTypeList[GetContents[info.superTypes], info.segment] THEN ok _ FALSE; IF ~CheckTypeList[GetContents[info.subTypes], info.segment] THEN ok _ FALSE; FOR list: LIST OF AttributeInfo _ info.properties, list.rest WHILE list # NIL DO IF ~CheckProperty[new, list.first, info.deleted] THEN ok _ FALSE; ENDLOOP; IF ~ok THEN {IF copy THEN DestroyDomain[new]; RETURN}; -- WE ARE COMMITTED BEYOND THIS POINT -- handle the SubTypeRelations IF info.domain # NIL THEN {RemoveSubTypes[info.domain]; RemoveSuperTypes[info.domain]}; AddSubTypes[new, GetContents[info.subTypes], info.segment]; AddSuperTypes[new, GetContents[info.superTypes], info.segment]; -- insert the new properties FOR list: LIST OF AttributeInfo _ info.properties, list.rest WHILE list # NIL DO info.deleted _ RemoveDeleted[list.first, info.deleted]; SaveProperty[new, list.first]; ENDLOOP; -- destroy the properties deleted by the user FOR list: LIST OF Relation _ info.deleted, list.rest WHILE list # NIL DO DestroyRelation[list.first]; ENDLOOP; -- copy the domain's contents IF info.domain # NIL AND copy THEN { Schema.CopyDomainContents[info.domain, new]; RemoveSubTypes[info.domain]; DestroyDomain[info.domain]}; SetName[new, GetContents[info.name]]; viewer.child _ NIL; ViewerOps.AddProp[viewer, $DomainInfo, NIL]; [] _ Nut.Display[e: new, parent: viewer, method: replace, seg: info.segment]; END; CheckTypeList: PROCEDURE[types: ROPE, seg: Segment] RETURNS[ok: BOOLEAN _ TRUE] = BEGIN d: Domain; type: ROPE; WHILE types.Length[] > 0 DO [type, types, ok] _ NextName[types]; IF ~ok THEN EXIT; IF type.Length[] = 0 THEN LOOP; d _ FetchEntity[DomainDomain, type, seg]; IF d # NIL THEN LOOP; Message[NIL, Rope.Cat["BAD TYPE: ", type]]; RETURN[FALSE]; ENDLOOP; IF ~ok THEN Message[NIL, "BAD TYPE LIST."]; END; RemoveSubTypes: PROCEDURE[d: Domain] = BEGIN rs: RelshipSet; subTypeRS: Relship; rs _ RelationSubset[dSubType, LIST[[dSubTypeOf, d]]]; WHILE (subTypeRS _ NextRelship[rs]) # NIL DO DestroySubType[of: d, is: V2E[GetF[subTypeRS, dSubTypeIs]]]; ENDLOOP; ReleaseRelshipSet[rs]; END; RemoveSuperTypes: PROCEDURE[d: Domain] = BEGIN rs: RelshipSet; subTypeRS: Relship; rs _ RelationSubset[dSubType, LIST[[dSubTypeIs, d]]]; WHILE (subTypeRS _ NextRelship[rs]) # NIL DO DestroySubType[is: d, of: V2E[GetF[subTypeRS, dSubTypeOf]]]; ENDLOOP; ReleaseRelshipSet[rs]; END; AddSuperTypes: PROCEDURE[d: Domain, types: ROPE, seg: Segment] = BEGIN type: ROPE; new: Domain; superType: Domain; WHILE types.Length[] > 0 DO [type, types, ] _ NextName[types]; IF type.Length[] = 0 THEN LOOP; superType _ FetchEntity[DomainDomain, type, seg]; DeclareSubType[of: superType, is: d ! DB.Error => IF code=NotImplemented THEN RESUME]; -- we know better than DB! IF ~Optimized[superType] THEN LOOP; new _ DeclareDomain[NIL, SegmentOf[d]]; Schema.CopyDomainContents[superType, new]; RemoveSubTypes[superType]; DestroyDomain[superType]; SetName[new, type]; ENDLOOP; END; AddSubTypes: PROCEDURE[d: Domain, types: ROPE, seg: Segment] = BEGIN type: ROPE; subType: Domain; WHILE types.Length[] > 0 DO [type, types, ] _ NextName[types]; IF type.Length[] = 0 THEN LOOP; subType _ FetchEntity[DomainDomain, type, seg]; DeclareSubType[of: d, is: subType ! DB.Error => IF code=NotImplemented THEN RESUME]; -- we know better than DB! ENDLOOP; END; DomainQuery: PUBLIC Nut.QueryProc = { Nut.DefaultQuery[d, newV, segment] }; -- start code BuildMenus[]; END. Change log. Willie-Sue December 13, 1982: aFooProp => aFooIs, for new system properties Ę$˜JšôĪcfœ.œ&œ&œ(œĪk œ žœžœžœžœŦžœžœžœžœZžœžœžœžœ+žœ0žœžœFžœžœ+žœžœ(žœžœsĪn œžœœž œ žœĨžœĪbœZžœ!žœ6žœ$žœ0œ`  œžœžœ7žœœ  œ] œžœžœ‘žœžœ4žœ˛žœŸœžœ žœžœdžœ'žœžœžœ¤žœPžœˆžœ#žœ°žœâžœ#žœžœDžœ"žœžœžœdžœ‚žœ4žœ:žœžœžœbžœ‚žœ4žœžœžœŸœžœ2(œžœ žœ˜žœžœžœĨžœžœ­žœžœWžœž œžœžœWžœžœžœžœWžœžœžœžœÕžœžœžœžœ,žœ œ žœ!žœžœžœqžœžœ žœ+žœ$žœŸ œžœžœžœnžœ-žœ œžœžœ žœžœžœ œžœžœžœžœ1žœžœžœ+žœhžœ  œžœžœ"žœežœžœžœ‰žœ  œžœžœ"žœ?žœžœ œžœžœ"žœHžœ  œžœžœ"žœ6žœžœ žœžœžœžœžœžœžœ7žœžœžœžœžœ žœžœžœ4žœžœ žœžœ žœ žœBžœžœœ   œžœ(œžœ žœ­žœžœKžœžœžœ2žœžœžœžœ>žœžœ žœžœžœ žœ_žœÆžœžœÆžœ žœ*žœžœžœ.žœ$œ žœ$žœ"žœ!žœžœžœžœžœgžœbžœ&œ žœ$žœ"žœ!žœžœžœžœžœgžœhžœ œ5žœžœžœžœ#œžœžœžœ žœ(žœžœ žœ2žœžœœžœžœ9žœžœ œlžœžœžœžœžœžœžœžœžœ žœ-žœ(žœ2žœ.žœžœžœžœžœwžœfžœ Ÿ œž œžœ6žœžœ žœ0$œžœžœžœžœžœžœžœžœ žœ žœwžœžœžœžœ)œžœ<žœžœžœ:žœžœžœžœžœ,žœžœžœžœ/žœžœ žœžœžœžœžœžœ&œœžœžœžœÍœžœžœžœ,žœžœžœmžœ.œžœžœžœ$žœžœžœ,žœœžœžœžœžœŧžœ-žœYžœ Ÿ œž œžœžœžœžœžœžœžœžœ4žœžœžœ žœžœžœ:žœžœžœžœ<žœžœ žœžœžœ%žœŸœž œžœOžœžœ!žœžœLžœ!žœ Ÿœž œžœOžœžœ!žœžœLžœ!žœŸ œž œžœžœ žœ.žœžœ2žœžœžœqžœ žœžœžœœžœžœžœžœ¨žœžœŸ œž œžœžœ žœžœžœ2žœžœžœmžœ žœžœžœœžœžœ  œBœžœ[˜ĘŒ—…—FLMv