00001 # Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00002 # 00003 # This file is free software; as a special exception the author gives 00004 # unlimited permission to copy and/or distribute it, with or without 00005 # modifications, as long as this notice is preserved. 00006 # 00007 # This program is distributed in the hope that it will be useful, but 00008 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 00009 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00010 00011 ## ---------------------------------------------------------------------------- 00012 ## YadaGrammar - bundled information about a CDG grammar 00013 ## \ingroup YadaConfiguration 00014 ## 00015 ## \author Michael Daum 00016 ## 00017 ## $Id: YadaGrammar.tcl,v 1.24 2004/10/15 17:24:37 micha Exp $ 00018 ## ---------------------------------------------------------------------------- 00019 class YadaGrammar { 00020 inherit YadaConfigItem 00021 00022 # variables ---------------------------------------------------------------- 00023 00024 ## list of all files making up the grammar 00025 public variable files {} 00026 00027 ## list of selected wordgraph ids 00028 private variable _selection "" 00029 00030 ## array mapping wordgraph ids to YadaWordgraph s 00031 private variable _wordgraphs; ## \type TclArray 00032 00033 ## flag indicating whether the grammars _wordgraphs are up to date. If not 00034 ## we reconstruct this array in scan() or rescan(). 00035 private variable _isUpToDate 0 00036 00037 ## array mapping selection attribute to wordgraph-id 00038 private variable _selected 00039 00040 # methods ------------------------------------------------------------------ 00041 00042 constructor {args} {}; ## \type TclList 00043 destructor {} 00044 00045 public method deleteWordgraphs {} 00046 public method getWordgraphs {} 00047 public method getWordgraph {wgName}; ## \type TclString 00048 public method setWordgraph {wordgraph}; ## \type YadaWordgraph 00049 public method setSelection {args}; ## \type TclList 00050 public method getSelection {} 00051 public method scan {} 00052 public method rescan {} 00053 public method clone {args}; ## \type TclList 00054 public method toDOM {} 00055 public method fromDOM {rootNode}; ## \type domNode 00056 public method isUpToDate {} 00057 public method persistenceFileInSync {} 00058 public method getPersistanceFileName {}; ## overriding virtual method 00059 00060 }; 00061 00062 ## ---------------------------------------------------------------------------- 00063 ## constructor 00064 ## ---------------------------------------------------------------------------- 00065 body YadaGrammar::constructor {args} { 00066 global env 00067 00068 eval configure $args 00069 } 00070 00071 ## ---------------------------------------------------------------------------- 00072 ## destructor 00073 ## ---------------------------------------------------------------------------- 00074 body YadaGrammar::destructor {} { 00075 deleteWordgraphs 00076 } 00077 00078 00079 ## ---------------------------------------------------------------------------- 00080 ## Serializes Object into a DOM-XML-Node 00081 ## @return root DOM node representing the Grammar-Object (root tag <yada>) 00082 ## ---------------------------------------------------------------------------- 00083 body YadaGrammar::toDOM {} { 00084 set document [dom createDocument "yada"] 00085 set root [$document documentElement] 00086 00087 dom createNodeCmd elementNode grammar 00088 dom createNodeCmd elementNode file 00089 00090 $root appendFromScript { 00091 grammar -name $name { 00092 foreach f $files { 00093 file -name $f 00094 } 00095 } 00096 } 00097 00098 set nodeConfigDoc [$root selectNodes "/yada/grammar"] 00099 00100 foreach wordgraphID $_selection { 00101 set wordgraph $_wordgraphs($wordgraphID) 00102 $wordgraph configure -isSelected 1 00103 $nodeConfigDoc appendChild [$wordgraph toDOM] 00104 00105 } 00106 foreach wordgraph [getWordgraphs] { 00107 if {[info exists _selected([$wordgraph cget -name])]==0 || $_selected([$wordgraph cget -name])==0 } { 00108 $wordgraph configure -isSelected 0 00109 $nodeConfigDoc appendChild [$wordgraph toDOM] 00110 } 00111 } 00112 return $root 00113 } 00114 00115 00116 ## ---------------------------------------------------------------------------- 00117 ## Initialize Object with DOM node (that has saved the object state) 00118 ## @param rootNode root DOM-Node (Tag <yada>) 00119 ## ---------------------------------------------------------------------------- 00120 body YadaGrammar::fromDOM {rootNode} { 00121 set xpath "/yada/grammar" 00122 set nodeGrammar [$rootNode selectNodes $xpath] 00123 set name [$nodeGrammar getAttribute name] 00124 00125 set nodeFiles [$rootNode selectNodes ${xpath}/file] 00126 set files {} 00127 foreach nodeFile $nodeFiles { 00128 lappend files [$nodeFile getAttribute "name"] 00129 } 00130 00131 00132 00133 set newSelection "" 00134 deleteWordgraphs 00135 set nodeWordgraphs [$rootNode selectNodes ${xpath}/yadaWordgraph] 00136 foreach nodeWordgraph $nodeWordgraphs { 00137 set newWordgraph [YadaWordgraph ::#auto] 00138 $newWordgraph fromDOM $nodeWordgraph 00139 set _wordgraphs([$newWordgraph cget -name]) $newWordgraph 00140 if {[$newWordgraph cget -isSelected]} { 00141 lappend newSelection [$newWordgraph cget -name] 00142 } 00143 } 00144 eval setSelection $newSelection 00145 00146 } 00147 00148 ## ---------------------------------------------------------------------------- 00149 ## deleteWordgraphs 00150 ## ---------------------------------------------------------------------------- 00151 body YadaGrammar::deleteWordgraphs {} { 00152 foreach wgName [array names _wordgraphs] { 00153 itcl::delete object $_wordgraphs($wgName) 00154 unset _wordgraphs($wgName) 00155 } 00156 setModified 00157 } 00158 00159 ## ---------------------------------------------------------------------------- 00160 ## getWordgraphs 00161 ## ---------------------------------------------------------------------------- 00162 body YadaGrammar::getWordgraphs {} { 00163 set result "" 00164 foreach wgName [lsort -dictionary [array names _wordgraphs]] { 00165 lappend result $_wordgraphs($wgName) 00166 } 00167 00168 return "$result" 00169 } 00170 00171 ## ---------------------------------------------------------------------------- 00172 ## getWordgraph 00173 ## ---------------------------------------------------------------------------- 00174 body YadaGrammar::getWordgraph {wgName} { 00175 if {[info exists _wordgraphs($wgName)]} { 00176 return $_wordgraphs($wgName) 00177 } else { 00178 return "" 00179 } 00180 } 00181 00182 ## ---------------------------------------------------------------------------- 00183 ## setWordgraph 00184 ## registers a YadaWordgraph object 00185 ## ---------------------------------------------------------------------------- 00186 body YadaGrammar::setWordgraph {wordgraph} { 00187 set wgName [$wordgraph cget -name] 00188 if {[info exists _wordgraphs($wgName)]} { 00189 itcl::delete object $_wordgraphs($wgName) 00190 } 00191 set _wordgraphs($wgName) $wordgraph 00192 } 00193 00194 ## ---------------------------------------------------------------------------- 00195 ## scan 00196 ## ---------------------------------------------------------------------------- 00197 body YadaGrammar::scan {} { 00198 if {!$_isUpToDate} { 00199 rescan 00200 } 00201 } 00202 00203 ## ---------------------------------------------------------------------------- 00204 ## rescan 00205 ## ---------------------------------------------------------------------------- 00206 body YadaGrammar::rescan {} { 00207 global env 00208 00209 .main printStatus "... rescanning grammar '$name'" 00210 00211 setModified 00212 00213 # remove all contained wordgraphs from the grammar 00214 deleteWordgraphs 00215 00216 00217 # build a temporary xml log file 00218 set xmlFile [::file join $env(YADA_TMP) _yada[pid].xml.gz] 00219 00220 00221 # build a cdg process which is to be asked about wordgraphs and annotations 00222 set machine [.main getMachine "localhost"] 00223 00224 set process [CdgProcess ::#auto \ 00225 -printCommand "" \ 00226 -xmlFile $xmlFile \ 00227 -initFile none] 00228 00229 # start a cdgp process 00230 set thisPid [$process start] 00231 if {$thisPid <= 0} { 00232 .main printStatus "" 00233 printMessage "ERROR: cannot start cdgp process $env(YADA_CDGP)" 00234 return 00235 } 00236 00237 # load the grammar files 00238 foreach file $files { 00239 if {[regexp {.*\.gz} $file]} { 00240 $process tell "set preprocessor /usr/bin/zcat" 00241 $process tell "set prepsuffix .gz" 00242 } elseif {[regexp {.*\.m4} $file]} { 00243 $process tell "set preprocessor /usr/bin/m4 -s -P" 00244 $process tell "set prepsuffix .m4" 00245 } 00246 $process tell "load $file" 00247 } 00248 00249 # give us the wordgraphs 00250 $process tell "wordgraph\nannotation\nquit\n" 00251 .main printStatus "... started cdgp process" 00252 $process wait 00253 00254 #itcl::delete object $process 00255 00256 # get the document data 00257 .main printStatus "... opening source file '$xmlFile'" 00258 set fp [open "|zcat $xmlFile" r] 00259 .main printStatus "... reading source file '$xmlFile'" 00260 set data [read $fp] 00261 close $fp 00262 00263 ### for debugging 00264 #file delete $xmlFile 00265 00266 # parse it 00267 .main printStatus "... parsing source file '$xmlFile'" 00268 set document [dom parse $data] 00269 00270 set node [$document documentElement] 00271 if {$node == ""} { 00272 printMessage "ERROR: no cdgp logfile while recaning grammar." error 00273 } 00274 00275 # parse all lattice nodes 00276 foreach latticeNode [$node getElementsByTagName "lattice"] { 00277 00278 # build a new yada wordgraph 00279 set yadaWordgraph [YadaWordgraph ::#auto] 00280 $yadaWordgraph readXmlNode $latticeNode 00281 00282 # assert it into the grammar 00283 .main printStatus "... adding wordgraph '[$yadaWordgraph cget -name]'" 00284 setWordgraph $yadaWordgraph 00285 } 00286 00287 # parse all annotations 00288 foreach annoNode [$node getElementsByTagName "annotation"] { 00289 set latticeId [$annoNode getAttribute "lattice"] 00290 set annoId [$annoNode getAttribute "id"] 00291 set yadaWordgraph [getWordgraph $latticeId] 00292 if {$yadaWordgraph == ""} { 00293 .main printStatus "WARNING: no wordgraph '$latticeId' for annotation '$annoId'" 00294 } else { 00295 .main printStatus "... adding annotation '$annoId' to wordgraph '$latticeId'" 00296 $yadaWordgraph readXmlAnno $annoNode 00297 } 00298 } 00299 00300 # delete it 00301 $document delete 00302 set document "" 00303 set _isUpToDate 1 00304 .main printStatus "done rescanning" 00305 00306 # reestablish the selection 00307 eval setSelection $_selection 00308 } 00309 00310 ## ---------------------------------------------------------------------------- 00311 ## setSelection 00312 ## ---------------------------------------------------------------------------- 00313 body YadaGrammar::setSelection {args} { 00314 00315 foreach wordgraphID $_selection { 00316 set _selected($wordgraphID) 0 00317 } 00318 foreach wordgraphID $args { 00319 set _selected($wordgraphID) 1 00320 } 00321 00322 set _selection $args 00323 setModified 00324 } 00325 00326 ## ---------------------------------------------------------------------------- 00327 ## getSelection 00328 ## ---------------------------------------------------------------------------- 00329 body YadaGrammar::getSelection {} { 00330 return "$_selection" 00331 } 00332 00333 ## ---------------------------------------------------------------------------- 00334 ## clone 00335 ## ---------------------------------------------------------------------------- 00336 body YadaGrammar::clone {args} { 00337 00338 # build a new grammar 00339 set newGrammar [YadaGrammar ::#auto -name $name -files $files] 00340 00341 # clone all wordgraphs 00342 foreach wgName [array names _wordgraphs] { 00343 set newWordgraph [$_wordgraphs($wgName) clone] 00344 $newGrammar setWordgraph $newWordgraph 00345 } 00346 00347 # clone the selection 00348 eval $newGrammar setSelection $_selection 00349 00350 eval $newGrammar configure $args 00351 00352 return $newGrammar 00353 } 00354 00355 ## ---------------------------------------------------------------------------- 00356 ## files callback 00357 ## ---------------------------------------------------------------------------- 00358 configbody YadaGrammar::files { 00359 00360 if {$files == "<none>"} { 00361 return 00362 } 00363 00364 set thisFiles $files 00365 set files "" 00366 foreach file $thisFiles { 00367 catch {lappend files [glob $file]} 00368 } 00369 setModified 00370 } 00371 00372 ## ---------------------------------------------------------------------------- 00373 ## Returns the value of private member variable _isUpToDate 00374 ## ---------------------------------------------------------------------------- 00375 body YadaGrammar::isUpToDate {} { 00376 return $_isUpToDate 00377 } 00378 00379 00380 00381 ## ---------------------------------------------------------------------------- 00382 ## Predicate returning 1, if grammar file has been changed since the 00383 ## last saving, otherwise 0 00384 ## If no persistant state file exists, 1 is returned 00385 ## ---------------------------------------------------------------------------- 00386 body YadaGrammar::persistenceFileInSync {} { 00387 set zippedFileName [getPersistanceFileName].gz 00388 00389 if { ![hasSavedState]} { 00390 return 1 00391 } 00392 00393 ::file stat $zippedFileName persistantStateFileAttribs 00394 set ctime1 $persistantStateFileAttribs(ctime) 00395 00396 foreach grammarFile $files { 00397 ::file stat $grammarFile grammarFileAttribs 00398 set ctime2 $grammarFileAttribs(ctime) 00399 if { [expr {$ctime2 > $ctime1}] } { 00400 return 1 00401 } 00402 } 00403 00404 return 0 00405 } 00406 00407 ## ---------------------------------------------------------------------------- 00408 ## Getting unique file name from registry 00409 ## ---------------------------------------------------------------------------- 00410 body YadaGrammar::getPersistanceFileName {} { 00411 return [.main getPersistanceFileNameForGrammar $name] 00412 } 00413