home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / namespace / namespace.tcl < prev    next >
Text File  |  2000-11-02  |  16KB  |  539 lines

  1.  
  2. package require unique
  3.  
  4. # namespaceServer --
  5. #    This class implements the namespace component of the Comanche
  6. # architecture.
  7.  
  8. class namespaceServer {
  9.  
  10.     # Stores nodes xuiObjects, keys are nodeIds
  11.  
  12.     variable xuiNodesArray
  13.  
  14.     # Array keys are node ids, values are the parent node of the node id.
  15.  
  16.     variable parentNodesArray
  17.     
  18.     # Array keys are node ids, values are a list of all children node ids
  19.     
  20.     variable childrenNodeArray
  21.  
  22.     # Contains nodes with no children and whose children have never been
  23.     # requested. It is used to on the fly tree population.
  24.     
  25.     variable virginNodesArray
  26.     
  27.     # Stores the name of the plugin object that added the node
  28.     
  29.     variable nodeOwnerArray
  30.     
  31.     # All the view objects that are browsing the namespace
  32.     
  33.     variable registeredViewsList {}
  34.  
  35.     # Array that stores in the keys pairs [list $node $view] to indicate
  36.     # a certain view has browsed the node
  37.  
  38.     variable browsedNodesArray
  39.  
  40.     # plugin Database object that holds information related to
  41.     # plugins (i.e which plugins are interested in node of type
  42.     # virtualhost?)
  43.     
  44.     variable pgDb
  45.  
  46.     # xuiObjects used in communication with plugIns 
  47.     #
  48.     # To request requestXuiDocument
  49.     
  50.     variable xuiDocumentQuery 
  51.  
  52.     # To deliver answer xuiDocument
  53.  
  54.     variable xuiDocumentAnswer
  55.  
  56.     # xuiObjects used in communication with View
  57.     # to inform view nodes have been added.
  58.     
  59.     variable xuiAddNotify
  60.     variable xuiAddNotifyNode
  61.     variable xuiAddNotifyParentNode
  62.     
  63.     # xuiObjects used in communication with View
  64.     # to inform view nodes have been deleted
  65.     
  66.     variable xuiRemoveNotify
  67.     variable xuiRemoveNotifyNode
  68.     
  69.     # xuiObjects used to inform of delete queries
  70.     variable xuiDeleteRequest
  71.     variable xuiDeleteRequestNode
  72.     variable xuiDeleteRequestCaller
  73.     
  74.     # xuiList containing list of children tof a certain node used in
  75.     # returning getChildren calls
  76.     
  77.     variable childrenList
  78.     
  79.     constructor { } {
  80.     array set browsedNodesArray {}
  81.     set pgDb [ plugInDatabase ::#auto]
  82.     
  83.     set text  {
  84.      <structure name="documentQuery">
  85.          <syntax>
  86.              <structure name="data">
  87.              <syntax>
  88.              </syntax>
  89.          </structure>
  90.          <label name="caller" />
  91.          </syntax>
  92.          </structure>     
  93.     }
  94.     set xuiDocumentQuery [libgui::createXuiFromText $text]
  95.     $xuiDocumentQuery.caller setValue $this
  96.     
  97.     
  98.     set text  {
  99.         <structure name="documentAnswer">
  100.             <syntax>
  101.                 <structure name="data">
  102.                     <syntax>
  103.                     </syntax>
  104.                 </structure>
  105.                 <label name="caller" />
  106.             </syntax>
  107.         </structure>     
  108.     }
  109.     set xuiDocumentAnswer [libgui::createXuiFromText $text]
  110.     $xuiDocumentAnswer.caller setValue $this
  111.  
  112.      
  113.     set xuiAddNotifyParentNode [xuiNode ::#auto]
  114.     $xuiAddNotifyParentNode setName parentNode
  115.     
  116.     set xuiAddNotifyNode [xuiNode ::#auto]
  117.     $xuiAddNotifyNode setName addedNode
  118.     
  119.     set xuiAddNotify [xuiStructure ::#auto]
  120.     $xuiAddNotify setName notifyNodeAddedResponse
  121.     $xuiAddNotify addComponent $xuiAddNotifyParentNode
  122.     $xuiAddNotify addComponent $xuiAddNotifyNode
  123.     
  124.     set xuiRemoveNotifyNode [xuiNode ::#auto]
  125.     $xuiRemoveNotifyNode setName node
  126.     
  127.     set xuiRemoveNotify [xuiStructure ::#auto]
  128.     $xuiRemoveNotify setName notifyNodeRemovedResponse
  129.     $xuiRemoveNotify addComponent $xuiRemoveNotifyNode
  130.  
  131.         set xuiDeleteRequest [xuiStructure ::#auto]
  132.         set xuiDeleteRequestData [xuiStructure ::#auto]
  133.         $xuiDeleteRequestData setName data
  134.     
  135.     set xuiDeleteRequestCaller [xuiLabel ::#auto]
  136.         $xuiDeleteRequestCaller setName caller
  137.     
  138.     set xuiDeleteRequestNode [xuiNode ::#auto]
  139.     $xuiDeleteRequestNode setName node
  140.     
  141.     $xuiDeleteRequest addComponent $xuiDeleteRequestCaller
  142.     $xuiDeleteRequest addComponent $xuiDeleteRequestData
  143.     $xuiDeleteRequestData addComponent $xuiDeleteRequestNode
  144.  
  145.     set childrenList [xuiList ::#auto]
  146.     $childrenList setXuiClass list
  147.     $childrenList setPrototype [xuiNode ::#auto]
  148.     
  149.     set root [xuiNode ::#auto]
  150.     $root setXuiClass node
  151.     $root addClass container
  152.     $root setName rootNode
  153.     $root setOpenIcon computer
  154.     $root setClosedIcon computer
  155.     $root setId root
  156.     $root setLabel  [info hostname]
  157.  
  158.     array set parentNodesArray {root {}}
  159.     array set childrenNodeArray {root {}}
  160.     array set xuiNodesArray "root $root"
  161.     array set nodeOwnerArray {root {}}
  162.     array set virginNodesArray {root 0}
  163.     }
  164.     
  165.     method getRootNode {} { return $xuiNodesArray(root) }
  166.     method addNode { xuiData }
  167.     method configureNode { xuiData caller}
  168.     method removeNode { xuiData }
  169.     method deleteNodeRequest { xuiData caller}
  170.     method getChildren { xuiData caller}
  171.  
  172.     method requestXuiDocument {xuiData caller}
  173.     method answerXuiDocument {xuiData caller}
  174.  
  175.     method _notifyAddedNode { nodeId }
  176.     method _notifyRemovedNode { nodeId }
  177.     method _notifyModifiedNode { nodeId }
  178.     method _nodeExists { nodeId }
  179.  
  180.     method registerView { xuiData caller }
  181.  
  182.     method registerPlugInInterests { xuiData caller }
  183. }
  184.  
  185. # namespaceServer::addNode --
  186. #     Adds a node to the namespace server
  187. # Arguments
  188. #    xuiData
  189. #    xuiData is the standard XML structure for exchanging data
  190. #    
  191. #    It has the following structure:
  192. #
  193. #    xuiData (xuiStructure)
  194. #       |
  195. #       |- caller (xuiLabel)
  196. #       |
  197. #       \_ data (xuiStructure)
  198. #            |
  199. #            |- node (xuiNode)  Parent node
  200. #            \_ newNode (xuiNode) New node to be added
  201. # Returns
  202. #     
  203. #    node    xuiNode containing the information about the node added
  204.  
  205.  
  206. body namespaceServer::addNode { xuiData } {
  207.     set data [ ::plugInUtils::getDataField $xuiData ]
  208.     set caller [ ::plugInUtils::getCallerName $xuiData ]
  209.     set parentNodeId [[$data getComponentByName node] getId]
  210.     if ![_nodeExists $parentNodeId] {
  211.     error "Tried to add a node whose parent $parentNodeId does not exists!"
  212.     }
  213.     set newId [unique::newId]
  214.     set newNode [[$data getComponentByName newNode] clone]
  215.     $newNode setId $newId
  216.     set parentNodesArray($newId) $parentNodeId
  217.     lappend childrenNodeArray($parentNodeId) $newId
  218.     set childrenNodeArray($newId) {}
  219.     set xuiNodesArray($newId) $newNode
  220.     set nodeOwnerArray($newId) $caller
  221.     set virginNodesArray($newId) 1
  222.     set virginNodesArray($parentNodeId) 0
  223.     _notifyAddedNode $newId
  224.     return $newNode
  225. }
  226.  
  227. # namespaceServer::deleteNodeRequest --
  228. #    Request deletion of a node from the namespace server.
  229.  
  230. body namespaceServer::deleteNodeRequest { xuiData caller} {
  231.     set nodeId [$xuiData getId]
  232.     $xuiDeleteRequestNode setId $nodeId 
  233.     $nodeOwnerArray($nodeId) deleteNodeRequest $xuiDeleteRequest
  234.     return
  235. }
  236.  
  237. # namespaceServer::configureNode --
  238. #    Changes properties of an existing node (image, label...).
  239. # TO-DO: Use new API (get rid caller)
  240.  
  241. body namespaceServer::configureNode { xuiData caller} {
  242.     set nodeId [$xuiData getId]
  243.     if ![_nodeExists $nodeId] {
  244.     error "Tried to configure $nodeId which does not exists!"
  245.     }
  246.     set xuiNode $xuiNodesArray($nodeId)
  247.     $xuiData copyClone $xuiNode 
  248.     _notifyModifiedNode $nodeId
  249.     return $nodeId
  250. }
  251.  
  252. # namespaceServer::removeNode --
  253. #    Remove node from the namespace server.
  254. # TO-DO: Use new API (get rid caller)
  255.  
  256. body namespaceServer::removeNode { xuiData } {
  257.     set data [::plugInUtils::getDataField $xuiData]
  258.     set nodeId [[$data getComponentByName node] getId]
  259.     if ![_nodeExists $nodeId] {
  260.     error "Tried to delete $nodeId which does not exists!"
  261.     }
  262.     if [llength $childrenNodeArray($nodeId)] {
  263.     error "You can not remove a non-empty node"
  264.     
  265.     } else {
  266.         unset virginNodesArray($nodeId)
  267.     unset childrenNodeArray($nodeId)
  268.     delete object $xuiNodesArray($nodeId)
  269.     unset xuiNodesArray($nodeId)
  270.     unset nodeOwnerArray($nodeId)
  271.     set parentNodeId $parentNodesArray($nodeId)
  272.     set idx [lsearch -exact $childrenNodeArray($parentNodeId) $nodeId]
  273.     set childrenNodeArray($parentNodeId) \
  274.             [lreplace $childrenNodeArray($parentNodeId) $idx $idx]
  275.     unset parentNodesArray($nodeId)
  276.     _notifyRemovedNode $nodeId
  277.     }
  278. }
  279.  
  280. # namespaceServer::getChildren --
  281. #    Get all children of a given node.
  282. # TO-DO: Use new API (get rid caller)
  283.  
  284.  
  285. body namespaceServer::getChildren { xuiData caller} {
  286.     set parentNodeId [$xuiData getId]
  287.     if $virginNodesArray($parentNodeId) {
  288.     
  289.     # If the node was virgin (it was never requested) we give the parent
  290.     # an opportunity to add new nodes (this is useful for navigating 
  291.     # a directory tree on demand)
  292.     
  293.     set virginNodesArray($parentNodeId) 0
  294.     $nodeOwnerArray($parentNodeId) populateNodeRequest $xuiData $this
  295.     }
  296.     
  297.     # Take node the caller object has browsed this node, so we will inform
  298.     # it when nodes are added or deleted to it.
  299.     
  300.     set browsedNodesArray([list $parentNodeId $caller]) 1
  301.     $childrenList clear
  302.     foreach item $childrenNodeArray($parentNodeId) {
  303.     set ch [$childrenList newChild]
  304.     $xuiNodesArray($item) copyClone $ch
  305.     set browsedNodesArray([list [$xuiNodesArray($item) getId] $caller]) 1
  306.     $childrenList insertChild $ch
  307.     }
  308.     return $childrenList
  309. }
  310.  
  311. # namespaceServer::registerView --
  312. #   Register a view with the namespace so we can inform of updates
  313.  
  314. body namespaceServer::registerView { xuiData caller} {
  315.     lappend registeredViewsList $caller
  316. }
  317.  
  318. # namespaceServer::_nodeExists --
  319. #    Check if a node exists (it has a valid parent)
  320.  
  321. body namespaceServer::_nodeExists { nodeId } {
  322.     return [info exists parentNodesArray($nodeId)]
  323. }
  324.  
  325. # namespaceServer::_notifyAddedNode -- 
  326. #    Notify all objects that have previously browsed a node that the node 
  327. # has new descendants
  328.  
  329. body namespaceServer::_notifyAddedNode { nodeId } {
  330.     set parentNode $parentNodesArray($nodeId)
  331.     foreach view $registeredViewsList {
  332.     if [info exists browsedNodesArray([list $parentNode $view])] {
  333.         [$xuiAddNotify getComponentByName parentNode] setId $parentNode
  334.         $xuiNodesArray($nodeId) copyClone [$xuiAddNotify getComponentByName addedNode] 
  335.         $view nodeAddedNotify $xuiAddNotify $this
  336.     }
  337.     }
  338. }
  339.  
  340. # namespaceServer::_notifyRemovedNode -- 
  341. #    Notify all objects that have previously browsed a node that the node 
  342. # has being Removed
  343.  
  344. body namespaceServer::_notifyRemovedNode { nodeId } {
  345.     foreach view $registeredViewsList {
  346.     if [info exists browsedNodesArray([list $nodeId $view])] {
  347.         [$xuiRemoveNotify getComponentByName node] setId $nodeId
  348.         $view nodeRemovedNotify $xuiRemoveNotify $this
  349.     }
  350.     }
  351. }
  352.  
  353. # namespaceServer::_notifyModifiedNode --
  354. #    Notify all objects that have previously browsed a node that the node 
  355. # has changed its attributes.
  356.  
  357. body namespaceServer::_notifyModifiedNode { nodeId } {
  358.     set parentNode $parentNodesArray($nodeId)
  359.     foreach view $registeredViewsList {
  360.     if [info exists browsedNodesArray([list $parentNode $view])] {
  361.           $view nodeModifiedNotify $xuiNodesArray($nodeId) $this
  362.     }
  363.     }
  364. }
  365.  
  366. # namespaceServer::registerPlugInInterests --
  367.  
  368. body namespaceServer::registerPlugInInterests { xuiData caller } {
  369. }
  370.  
  371. # namespaceServer::requestXuiDocument --
  372. #    This method is invoked by views to request a certain XML User Interface
  373. # document (property pages, wizard, etc). The namespace will analyze the
  374. # request, see which nodes are interested in contributing to the answer and
  375. # return the specified document
  376.  
  377. body namespaceServer::requestXuiDocument {xuiData caller} {
  378.     set nodeId [[$xuiData getComponentByName node] getId]
  379.     
  380.     # Find out which plugins may be interested (care of not duplicating
  381.     # the owner)
  382.     
  383.     set classes [ $xuiNodesArray($nodeId)  getClasses]
  384.     set plugInsList [$pgDb getPlugInsFromClasses $classes]
  385.     if [expr [lsearch $plugInsList $nodeOwnerArray($nodeId)] == -1 ] {
  386.     lappend plugInsList $nodeOwnerArray($nodeId)
  387.     }
  388.     #$xuiDocumentQuery.data forgetComponents
  389.     $xuiData copyClone $xuiDocumentQuery.data
  390.     
  391.  
  392.     # Create a container for the specific kind of document
  393.     # being requested.
  394.     
  395.     set docType [$xuiData getComponentByName docType]
  396.     switch -glob [$docType getValue] {
  397.     propertyPages {
  398.         set creator [propertyPagesDocumentCreator ::#auto]
  399.     } description {
  400.        set creator [htmlCreator ::#auto]
  401.     } wizard* {
  402.        set creator [wizardDocumentCreator ::#auto]
  403.     } command {
  404.        set creator [genericDocumentCreator ::#auto]
  405.        
  406.        # Right now only the parent interested
  407.        # (so not to confuse other plugIns, but it is likely that
  408.        # in the future somebody will want to intercept calls)
  409.        
  410.        set plugInsList $nodeOwnerArray($nodeId)
  411.     } default {
  412.         error "Unknown propertyPage [$docType getValue]"
  413.     }
  414.     }
  415.     foreach plugIn $plugInsList {
  416.     $creator add [$plugIn requestXuiDocument $xuiDocumentQuery ] $plugIn
  417.     }
  418.     set res [$creator getResult]
  419.     delete object $creator
  420.     #puts "****************** xuiData $xuiData"
  421.     return $res
  422. }
  423.  
  424. # namespaceServer::answerXuiDocument --
  425. #    Namespace receives the submission of an XUI document addressed for a
  426. # certain node. Figures out which nodes want to know about it and sends to
  427. # them.
  428. # TO_DO: May be concurrency problems is firs foreach plugin... loop is stuck
  429. # on transmission and a new filevent arrives? Would xuiDocumentAnswer
  430. # be overwritten?
  431.  
  432. body namespaceServer::answerXuiDocument {xuiData caller} {
  433.  
  434.     set docType [$xuiData getComponentByName docType]
  435.     switch -glob [$docType getValue] {
  436.     propertyPages {
  437.  
  438.     } wizard* {
  439.     } default {
  440.         error "Unknown propertyPage $docType"
  441.     }
  442.     }
  443.  
  444.     
  445.     set nodeId [[$xuiData getComponentByName node] getId]
  446.     set classes [ $xuiNodesArray($nodeId)  getClasses]
  447.     set plugInsList [$pgDb getPlugInsFromClasses $classes]
  448.     if [expr [lsearch $plugInsList $nodeOwnerArray($nodeId)] == -1 ] {
  449.     lappend plugInsList $nodeOwnerArray($nodeId)
  450.     }
  451.     
  452.     #$xuiDocumentAnswer.data forgetComponents
  453.     $xuiData copyClone $xuiDocumentAnswer.data
  454.     #$xuiData clear
  455.     foreach plugIn $plugInsList {
  456.     $plugIn answerXuiDocument $xuiDocumentAnswer 
  457.     }
  458.     return
  459. }
  460.  
  461.  
  462.  
  463.  
  464. class propertyPagesDocumentCreator {
  465.     variable pPages
  466.     constructor {} {
  467.     set pPages [ xuiStructure ::#auto]
  468.     $pPages setXuiClass propertyPages
  469.     $pPages setName propertyPages
  470.     }
  471.     method add {xuiData caller}
  472.     method getResult {} { return $pPages }
  473. }
  474.  
  475.  
  476.  
  477. body propertyPagesDocumentCreator::add { xuiData caller } {
  478.     foreach pPage [$xuiData getComponents] {
  479.     $pPages addComponent $pPage
  480.     }
  481. }
  482.  
  483.  
  484.  
  485. class wizardDocumentCreator {
  486.     variable wizard
  487.     constructor {} {
  488.     set wizard [ xuiStructure ::#auto]
  489.     $wizard setXuiClass propertyPages
  490.     $wizard setName propertyPages
  491.     }
  492.     method add {xuiData caller}
  493.     method getResult {} { return $wizard }
  494. }
  495.  
  496.  
  497.  
  498. body wizardDocumentCreator::add { xuiData caller } {
  499.     foreach wizardPage [$xuiData getComponents] {
  500.     $wizard addComponent $wizardPage
  501.     }
  502. }
  503.  
  504.  
  505.  
  506. class genericDocumentCreator {
  507.     variable generic
  508.     constructor {} {
  509.     set generic [ xuiStructure ::#auto]
  510.     $generic setXuiClass propertyPages
  511.     $generic setName propertyPages
  512.     }
  513.     method add {xuiData caller}
  514.     method getResult {} { return $generic }
  515. }
  516.  
  517.  
  518.  
  519. body genericDocumentCreator::add { xuiData caller } {
  520.     foreach genericPage [$xuiData getComponents] {
  521.     $generic addComponent $genericPage
  522.     }
  523. }
  524.  
  525.  
  526. class htmlCreator {
  527.     variable data {}
  528.     constructor {} {
  529.     }
  530.     method add { text args} {append data $text}
  531.     method getResult {} { return $data}
  532. }
  533.  
  534.  
  535.  
  536.  
  537.