DIRECTORY Buttons USING [ButtonProc], Containers USING [ChildYBound], DB, DefaultNutUtilities, Menus USING [AppendMenuEntry, CreateMenu, Menu, MenuProc], Nut, NutOps, NutViewer, Rope, SchemaNut, ViewerOps, ViewerTools, ViewerClasses; DomainNutImpl: CEDAR PROGRAM IMPORTS Containers, DB, DefaultNutUtilities, Nut, NutOps, Menus, SchemaNut, NutViewer, Rope, ViewerOps, ViewerTools = BEGIN OPEN DB, NutViewer, ViewerTools; Viewer: TYPE = ViewerClasses.Viewer; AttributeFieldObject: TYPE = RECORD[ attribute: Attribute, property: Attribute ]; AttributeFieldHandle: TYPE = REF AttributeFieldObject; displayerMenu: Menus.Menu = Menus.CreateMenu[]; editorMenu: Menus.Menu = Menus.CreateMenu[]; EntitySetInfo: TYPE = REF EntitySetInfoRec; EntitySetInfoRec: TYPE = RECORD[ es: EntitySet _ NIL, currentPos: INT _ 0, totalLength: INT _ 0 ]; BuildMenus: PROC = BEGIN OPEN NutViewer; Menus.AppendMenuEntry[ displayerMenu, MakeMenuEntry[DBQueue[], "Edit", EditProc]]; Menus.AppendMenuEntry[ displayerMenu, MakeMenuEntry[DBQueue[], "Freeze", DefaultFreezeProc]]; Menus.AppendMenuEntry[ displayerMenu, MakeMenuEntry[DBQueue[], "ShowDomainInfo", ShowDomainInfoProc]]; 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 = BEGIN viewer: Viewer = NARROW[parent]; entity: ROPE; segment: DB.Segment; [segment: segment, entity: entity] _ Nut.GetNutInfo[viewer]; [] _ DomainEditor[eName: entity, domain: "Domain", segment: segment, lastSpawned: viewer]; END; ShowDomainInfoProc: Menus.MenuProc = { vp: Viewer = NARROW[parent]; mode: ATOM _ NARROW[ ViewerOps.FetchProp[vp, $DisplayMode]]; segment: DB.Segment; entity, domain: Rope.ROPE; [segment, domain, entity] _ Nut.GetNutInfo[vp]; vp.child_ NIL; -- Throw away children IF mode=$Entities AND NOT NutOps.IsSystemDomain[domain] THEN { vp.scrollable_ TRUE; ViewerOps.AddProp[vp, $DisplayMode, $Info]; []_ BuildInfoWindowButtons[NutViewer.Initialize[vp], DB.DeclareDomain[entity, segment]] } ELSE { vp.scrollable_ FALSE; ViewerOps.AddProp[vp, $DisplayMode, $Entities]; ShowEntitiesInWindow[vp, DB.DeclareDomain[entity, segment], segment]; }; ViewerOps.EstablishViewerPosition[vp, vp.wx, vp.wy, vp.ww, vp.wh]; ViewerOps.PaintViewer[viewer: vp, hint: client, clearClient: TRUE]; }; DomainQueryer: PUBLIC Nut.NutProc = BEGIN [] _ NutViewer.Message[NIL, "Domain queryers not implemented!"]; END; DomainDisplayer: PUBLIC Nut.NutProc = BEGIN e: DB.Entity _ DB.DeclareDomain[eName, segment, OldOnly]; v _ NutViewer.ReplaceViewer[eName, domain, segment, lastSpawned]; ViewerOps.SetMenu[v, displayerMenu]; ViewerOps.AddProp[v, $DisplayMode, $Entities]; ViewerOps.AddProp[v, $Domain, e]; IF ViewerOps.FetchProp[v, $DomainInfo] = NIL THEN ViewerOps.AddProp[v, $DomainInfo, NEW[SchemaNut.DomainInfoRecord]]; ShowEntitiesInWindow[v, e, segment]; ViewerOps.PaintViewer[v, all]; END; GetDomain: PROC[v: Viewer] RETURNS[d: DB.Domain] = { d _ DB.V2E[ViewerOps.FetchProp[v, $Domain]]; IF NOT DB.Null[d] THEN RETURN; { segment: DB.Segment; entity: Rope.ROPE; domain: DB.Domain; [entity: entity, segment: segment] _ Nut.GetNutInfo[v]; domain _ DB.DeclareDomain[entity, segment, OldOnly]; ViewerOps.AddProp[v, $Domain, domain]; RETURN[ domain ] } }; BuildInfoWindowButtons: PROC[lastViewer: Viewer, e: Entity] RETURNS[newLastViewer: Viewer] = BEGIN rs: RelshipSet; r: Relship; other: Domain; myAttrs: AttributeList = GetDomainRefAttributes[e]; lastViewer_ NutViewer.MakeLabel[ name: "* Relation / attribute / uniqueness for attributes that reference this domain *", sib: lastViewer]; 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: 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: other, sib: lastViewer]; ENDLOOP; ReleaseRelshipSet[rs]; RETURN[lastViewer] END; ShowEntitiesInWindow: PROC[parent: Viewer, e: Entity, seg: Segment] = BEGIN count: INT_ 0; lastViewer: Viewer; myEntities: EntitySet; IF Eq[e, DomainDomain] THEN { lastViewer _ NutViewer.Initialize[parent]; lastViewer _ NewEntity[DataTypeDomain, lastViewer]; lastViewer _ NewEntity[RelationDomain, lastViewer]; myEntities _ DomainSubset[d: e, searchSegment: seg]; UNTIL Null[e_ NextEntity[myEntities]] DO lastViewer_ NewEntity[e, lastViewer] ENDLOOP; ReleaseEntitySet[myEntities]; RETURN}; IF Eq[e, RelationDomain] THEN { lastViewer _ NutViewer.Initialize[parent]; myEntities _ DomainSubset[d: e, searchSegment: seg]; UNTIL Null[e_ NextEntity[myEntities]] DO lastViewer_ NewEntity[e, lastViewer] ENDLOOP; ReleaseEntitySet[myEntities]; RETURN}; IF Eq[e, DataTypeDomain] THEN { lastViewer _ NutViewer.Initialize[parent]; lastViewer _ NewEntity[RopeType, lastViewer]; lastViewer _ NewEntity[IntType, lastViewer]; lastViewer _ NewEntity[BoolType, lastViewer]; lastViewer _ NewEntity[TimeType, lastViewer]; RETURN}; IF Eq[e, AttributeDomain] OR Eq[e, IndexDomain] OR Eq[e, IndexFactorDomain] THEN RETURN; parent.scrollable_ FALSE; -- Scrollbar will be provided by MBWindow lastViewer_ NutViewer.CreateMBWindow[ count: GetThingCount, thumb: DomainThumb, next: DomainNextProc, prev: DomainPrevProc, buttonProc: ProcessEntitySelection, info: [parent: parent, wx: 0, wy: 0, ww: parent.ww, wh: 800, border: FALSE], q: NIL ]; Containers.ChildYBound[container: parent, child: lastViewer]; END; GetThingCount: NutViewer.CountProc = { parent: Viewer = DefaultNutUtilities.GetTopLevel[v]; eName: Rope.ROPE = Nut.GetNutInfo[parent].entity; SELECT TRUE FROM eName.Equal["Person"] => RETURN[1000]; eName.Equal["Organization"] => RETURN[500]; ENDCASE => RETURN[EntitySetSize[DomainSubset[GetDomain[parent], "", "\177"], FALSE]]; }; EntitySetSize: PROC [awesome: EntitySet, forSure: BOOL] RETURNS [totally: INT] = { totally_ 0; UNTIL DB.NextEntity[awesome]=NIL DO IF (totally_ totally+1)>100 AND NOT forSure THEN {totally_ 500; EXIT}; -- just estimate ENDLOOP; DB.ReleaseEntitySet[awesome]; RETURN[totally] }; DomainNextProc: NutViewer.EnumProc = TRUSTED BEGIN info: NutViewer.EntitySetInfo _ NARROW[enum]; e: Entity _ NIL; IF info.currentPos <= info.totalLength THEN e _ NextEntity[info.es]; RETURN[NutOps.SafeNameOf[e], e]; END; DomainPrevProc: NutViewer.EnumProc = TRUSTED BEGIN info: NutViewer.EntitySetInfo _ NARROW[enum]; e: Entity _ NIL; IF info.currentPos <= info.totalLength THEN e _ PrevEntity[info.es]; RETURN[NutOps.SafeNameOf[e], e]; END; DomainThumb: NutViewer.ThumbProc = TRUSTED BEGIN info: NutViewer.EntitySetInfo _ NARROW[enum]; domain: DB.Domain = GetDomain[ DefaultNutUtilities.GetTopLevel[v] ]; IF info # NIL THEN DB.ReleaseEntitySet[info.es] ELSE info _ NEW[NutViewer.EntitySetInfoRec]; IF where<10 THEN BEGIN info.es_ DB.DomainSubset[domain, "", "\177", First]; IF where=0 THEN BEGIN -- set up first enumerated thing info.currentPos _ 1; info.totalLength _ GetThingCount[v, info.es]; END; END ELSE IF where>90 THEN { info.es_ DB.DomainSubset[domain, "", "\177", Last]; []_ PrevEntity[info.es]; []_ PrevEntity[info.es]; []_ PrevEntity[info.es]} ELSE { howFar: INT = where*GetThingCount[v, info.es]/100; info.es_ DB.DomainSubset[domain, "", "\177", First]; THROUGH [0..howFar) DO []_ NextEntity[info.es] ENDLOOP; }; RETURN[info] END; NewEntity: PROC[e: Entity, sib: Viewer] RETURNS[Viewer] = {RETURN[NutViewer.MakeButton[ q: NutViewer.DBQueue[], name: DB.NameOf[e], proc: ProcessEntitySelection, data: e, sib: sib, newLine: TRUE]]}; ProcessEntitySelection: Buttons.ButtonProc = BEGIN e: Entity = V2E[clientData]; viewer: Viewer = DefaultNutUtilities.GetTopLevel[NARROW[parent]]; segment: DB.Segment = Nut.GetNutInfo[viewer].segment; eName: ROPE _ NutOps.SafeNameOf[e]; IF e=NIL THEN RETURN; -- really not a button [] _ Nut.Display[eName: eName, domain: DB.NameOf[DB.DomainOf[e]], segment: segment, parent: viewer]; END; ProcessAttributeSelection: Buttons.ButtonProc = BEGIN fd: AttributeFieldHandle = NARROW[clientData]; v: Viewer = NARROW[parent]; IF fd.property = NIL THEN Message[v, "Not an entity-valued field"] ELSE BEGIN e: DB.Entity _ V2E[GetP[fd.attribute, fd.property]]; eName: ROPE _ NutOps.SafeNameOf[e]; IF NOT DB.Null[e] THEN [] _ Nut.Display[eName: eName, domain: DB.NameOf[DB.DomainOf[e]], segment: Nut.GetNutInfo[v].segment, parent: v]; END; END; RenameProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; domain: DB.Domain = GetDomain[viewer]; newName: Rope.ROPE = ViewerTools.GetSelectionContents[]; IF domain#NIL THEN DB.ChangeName[domain, newName]; viewer.name_ Rope.Cat["Domain: ", newName]; ViewerOps.PaintViewer[viewer, caption]; Nut.ChangeName[viewer, newName] END; ResetProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; eName: Rope.ROPE; segment: DB.Segment; [entity: eName, segment: segment] _ Nut.GetNutInfo[viewer]; DefaultNutUtilities.Reset[eName: eName, domain: "DomainDomain", seg: segment, viewer: viewer]; END; SaveProc: Menus.MenuProc = BEGIN SaveDomain[NARROW[parent]]; END; EraseProc: Menus.MenuProc = BEGIN viewer: Viewer = NARROW[parent]; domain: Domain = GetDomain[viewer]; IF domain = NIL THEN RETURN; DestroyDomain[domain ! DB.Error => { IF code = NotImplemented THEN Message[viewer, "You must delete the subtypes first."]; CONTINUE }] END; DomainEditor: PUBLIC Nut.NutProc = -- d: Domain, eName: ROPE, lastSpawned: Viewer BEGIN rope: ROPE; rs: RelshipSet; lastV: Viewer; relation: Relation; info: SchemaNut.DomainInfo = NEW[SchemaNut.DomainInfoRecord]; subTypeRS: Relship; isAttribute: Attribute; list: LIST OF Attribute; attributes: AttributeList; d: DB.Domain; IF Rope.Equal[eName, "Attribute", FALSE] OR Rope.Equal[eName, "DataType", FALSE] OR Rope.Equal[eName, "Domain", FALSE] OR Rope.Equal[eName, "Relation", FALSE] THEN BEGIN [] _ NutViewer.Message[NIL, eName, " is a system entity. You may not edit it."]; RETURN END; v _ NutViewer.ReplaceViewer[eName, domain, segment, lastSpawned]; ViewerOps.SetMenu[v, editorMenu]; ViewerOps.AddProp[v, $DomainInfo, info]; d _ GetDomain[v]; lastV_ NutViewer.Initialize[v]; lastV _ NutViewer.MakeLabel["", lastV]; 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: SchemaNut.NewAttribute, sib: lastV, border: TRUE, newLine: TRUE]; IF DB.Null[GetDomain[v]] THEN RETURN; rope _ NIL; rs _ RelationSubset[dSubType, LIST[[dSubTypeOf, d]]]; 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; rope _ NIL; rs _ RelationSubset[dSubType, LIST[[dSubTypeIs, d]]]; 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; list _ NutOps.GetRefAttributes[d]; FOR list _ list, list.rest WHILE list # NIL DO -- find all of the "of" attributes un: Uniqueness; IF Null[list.first] THEN LOOP; IF ~Rope.Equal[GetName[list.first], "of"] THEN LOOP; IF ~Eq[V2E[GetP[list.first, aTypeIs]], d] THEN LOOP; -- skip superclasses IF (un_ LOOPHOLE[V2U[GetP[list.first, aUniquenessIs]], Uniqueness]) # Key THEN LOOP; 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[SchemaNut.DisplayAttribute[relation, isAttribute, lastV], info.properties]; lastV _ info.properties.first.length; ENDLOOP; info.properties _ SchemaNut.Reverse[info.properties]; ViewerOps.PaintViewer[v, all] END; SaveDomain: PROCEDURE[viewer: Viewer] = BEGIN new: Domain; info: SchemaNut.DomainInfo = NARROW[ViewerOps.FetchProp[viewer, $DomainInfo]]; oldDomain: DB.Domain = GetDomain[viewer]; eName: Rope.ROPE; segment: DB.Segment; ok, copy: BOOLEAN _ TRUE; [entity: eName, segment: segment] _ Nut.GetNutInfo[viewer]; IF DB.Null[oldDomain] THEN copy _ TRUE ELSE IF ~SchemaNut.Optimized[oldDomain] THEN copy _ FALSE ELSE BEGIN subType: ROPE = SchemaNut.NextName[GetContents[info.subTypes]].token; copy _ (subType.Length[] # 0); END; IF copy THEN new _ DeclareDomain[NIL, segment] ELSE new _ oldDomain; IF ~CheckTypeList[GetContents[info.superTypes], segment] THEN ok _ FALSE; IF ~CheckTypeList[GetContents[info.subTypes], segment] THEN ok _ FALSE; FOR list: LIST OF SchemaNut.AttributeInfo _ info.properties, list.rest WHILE list # NIL DO IF ~SchemaNut.CheckProperty[new, list.first, info.deleted] THEN ok _ FALSE; ENDLOOP; IF ~ok AND copy THEN { DestroyDomain[new]; RETURN }; IF NOT DB.Null[oldDomain] THEN BEGIN RemoveSubTypes[oldDomain]; RemoveSuperTypes[oldDomain]; END; AddSubTypes[new, GetContents[info.subTypes], segment]; AddSuperTypes[new, GetContents[info.superTypes], segment]; FOR list: LIST OF SchemaNut.AttributeInfo _ info.properties, list.rest WHILE list # NIL DO info.deleted _ SchemaNut.RemoveDeleted[oldDomain, list.first, info.deleted]; SchemaNut.SaveProperty[new, list.first]; ENDLOOP; FOR list: LIST OF Relation _ info.deleted, list.rest WHILE list # NIL DO DestroyRelation[list.first]; ENDLOOP; IF NOT DB.Null[oldDomain] AND copy THEN BEGIN SchemaNut.CopyDomainContents[oldDomain, new]; RemoveSubTypes[oldDomain]; DestroyDomain[oldDomain]; END; SetName[new, eName]; ViewerOps.AddProp[viewer, $DomainInfo, NIL]; [] _ DomainDisplayer[eName: eName, domain: "DomainDomain", segment: segment, lastSpawned: viewer]; END; CheckTypeList: PROCEDURE[types: ROPE, seg: Segment] RETURNS[ok: BOOLEAN _ TRUE] = BEGIN d: Domain; type: ROPE; WHILE types.Length[] > 0 DO [type, types, ok] _ SchemaNut.NextName[types]; IF ~ok THEN EXIT; IF type.Length[] = 0 THEN LOOP; d _ FetchEntity[DomainDomain, type, seg]; IF d # NIL THEN LOOP; NutViewer.Message[NIL, Rope.Cat["Bad type: ", type]]; RETURN[FALSE]; ENDLOOP; IF ~ok THEN NutViewer.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, ] _ SchemaNut.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 ~SchemaNut.Optimized[superType] THEN LOOP; new _ DeclareDomain[NIL, NutOps.SafeSegmentOf[d]]; SchemaNut.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, ] _ SchemaNut.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; BuildMenus[]; Nut.Register[ "Domain", NIL, DomainDisplayer, DomainEditor]; END. File: DomainNutImpl.mesa Contents: Implementation of the Domain Nut windows. Last edited by: Willie-Sue on: February 22, 1983 3:49 pm Cattell on: October 5, 1983 10:26 am Maxwell on: June 3, 1982 9:27 am Donahue on: July 17, 1984 4:58:17 pm PDT Butler on: August 16, 1984 3:26:48 pm PDT Need to call ReleaseEntitySet[myEntities] when viewer destroyed! Can't use MBQueue's clientData Replace client portion of window, to show entities instead of schema info for domain, or vice versa. this procedure returns either the cached $Domain property or it computes the domain from the NutInfo values cache the result Display information about domain if showSchemaNut.DomainInfo, else show entities. Display all the entities in domain e Estimate total size of an EntitySet. If it's larger than 100, just guess 500. Get there the hard way, through NextEntity calls Used with NutViewer buttons Domain Editor -- -- print the subtypes of the domain -- Print the supertypes of the domain -- Print the current properties -- We have a likely candidate Will we have to copy the domain? Check to see if this is a legal edit WE ARE COMMITTED BEYOND THIS POINT handle the SubTypeRelations Insert the new properties Destroy the properties deleted by the user Copy the domain's contents Start code Ê#˜Jšœ™Jšœ3™3šœ™Jšœ(™(Jšœ$™$Jšœ ™ Jšœ(™(Jšœ)™)J˜J˜—šÏk ˜ Jšœœ˜Jšœ œ˜Jšœ˜J˜Jšœœ/˜:J˜J˜J˜ J˜J˜ J˜&J˜J˜J˜Jšœ@™@Jšœ™J˜J˜J˜—šœœ˜šœ œ*˜@J˜5J˜J˜——Jšœœœ˜&J˜J˜Jšœœ˜$J˜Jšœœœ.˜QJšœœœ˜6J˜J˜/J˜-Jšœœœ˜+šœœœ˜!Jšœœ˜Jšœ œ˜Jšœ œ˜—J˜šÏn œœ˜Jšœœ ˜˜J˜;—˜J˜F—˜J˜O—˜J˜:—˜J˜<—˜J˜8—˜J˜:—Jšœ˜J˜J˜—šÏbœ˜š˜Jšœœ ˜ Jšœœ˜ Jšœ œ ˜J˜Jšœœ˜J˜+Jšœ5œ ˜WJ˜šœ˜Jšœœ˜J˜/Jšœœ*˜EJ˜——J˜BJšœ=œ˜CJ˜J˜—šŸ œœ˜#š˜Jšœœ&˜@—Jšœ˜J˜—šŸœœ˜%š˜Jšœœ œ(˜9J˜AJ˜$J˜.J˜!šœ'˜,Jšœ#œ˜H—J˜$J˜Jšœ˜J˜J˜——šž œœ œœ ˜4Jšœk™kJšœœ&˜,Jš œœœ œœ˜šœ œ ˜Jšœ œ˜Jšœœ˜J˜7Jšœ œ)˜4Jšœ™J˜&Jšœ˜—J˜—šžœœ œ˜\JšœQ™QJšœ+˜0J˜3˜ J˜XJ˜—šœ'œœ˜:˜!J˜IJ˜ Jšœœ1˜:Jšœœ˜!—˜ J˜SJšœœ#œ˜D—˜!J˜EJ˜ Jšœœ?˜H—˜!J˜DJ˜ Jšœœ#œ˜D—Jšœ˜—JšœCœ˜IJšœœ˜4šœ˜!J˜ Jšœ:œ˜@˜!J˜LJ˜—Jšœ˜—J˜Jšœœ˜4šœ˜!J˜ Jšœ8œ˜>˜!J˜LJ˜—Jšœ˜—J˜Jšœ ˜Jšœ˜J˜J˜—šžœœ+˜FJšœ$™$Jš˜Jšœœ˜J˜J˜šœœ˜J˜*J˜3J˜3J˜4šœ!˜(Jšœ%œ˜-—J˜Jšœ˜—šœœ˜J˜*J˜4šœ!˜(Jšœ%œ˜-—J˜Jšœ˜—šœœ˜J˜*J˜-J˜,J˜-J˜-Jšœ˜—šœœœ˜PJšœ˜—Jšœœ )˜C˜%J˜J˜J˜J˜J˜#JšœEœ˜LJšœœ˜ —J˜=Jšœ˜J˜J˜—šŸ œ˜&J˜4Jšœ œ!˜1šœœ˜Jšœœ˜&Jšœœ˜+Jšœœ<œ˜U—J˜J˜J˜—š ž œœœœ œ˜RJšœO™OJ˜ šœœœ˜#Jš œœœ œœ ˜WJšœ˜—Jšœ˜Jšœ ˜J˜J˜—šŸœ˜,š˜Jšœ œ˜-Jšœ œ˜šœ%˜+Jšœ˜—Jšœ˜ Jšœ˜—J˜J˜—šŸœ˜,š˜Jšœ œ˜-Jšœ œ˜šœ%˜+Jšœ˜—Jšœ˜ Jšœ˜—J˜J˜—šŸ œ˜*š˜Jšœ œ˜-Jšœœ:˜DJšœœ˜/Jšœœ˜,šœ œ˜Jšœ œ)˜4šœ œœ  ˜6Jšœ˜Jšœ-˜-Jš˜—Jš˜—šœœ œ˜Jšœ œ(˜3JšœJ˜J—šœ˜Jšœ0™0Jšœœ'˜2Jšœ œ)˜4šœ ˜Jšœ˜Jšœ˜—J˜—Jšœ˜ Jšœ˜—J˜J˜—šž œœœ ˜:šœœ˜Jšœœ*˜JJšœœ˜$J˜—šŸœ˜,Jšœ™š˜J˜Jšœ1œ ˜AJšœ œ*˜5Jšœœ˜#Jš œœœœ ˜,Jšœ'œœ1˜dJšœ˜J˜J˜J˜———šŸœ˜/š˜Jšœœ ˜.Jšœ œ ˜šœœ˜J˜(—šœ˜ Jšœœ/˜4Jšœœ˜#šœœœ˜Jšœ(œœ>˜v—Jšœ˜—Jšœ˜J˜J˜J˜J˜——šŸ œ˜š˜Jšœœ ˜ Jšœœ˜&Jšœœ&˜8Jšœœœœ˜2J˜+J˜'J˜Jšœ˜—J˜J˜—šŸ œ˜š˜Jšœœ ˜ Jšœ œ˜Jšœ œ ˜J˜;J˜^Jšœ˜J˜J˜——šŸœ˜Jš˜Jšœ œ ˜Jšœ˜J˜J˜—šŸ œ˜Jš˜Jšœœ ˜ J˜#Jšœ œœœ˜šœœ ˜"šœœ˜Jšœ8˜Jšœ˜Jšœœ˜ J˜šœ˜J˜,Jšœœœ˜J˜/˜!Jš œœ œœœ ˜M—Jšœ˜—Jšœ˜J˜J˜—Jšœ ™ J˜ Jšœœ!˜