StateManager.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2011,  Michael Meyling <mime@qedeq.org>.
004  *
005  * "Hilbert II" is free software; you can redistribute
006  * it and/or modify it under the terms of the GNU General Public
007  * License as published by the Free Software Foundation; either
008  * version 2 of the License, or (at your option) any later version.
009  *
010  * This program is distributed in the hope that it will be useful,
011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013  * GNU General Public License for more details.
014  */
015 
016 package org.qedeq.kernel.bo.service;
017 
018 import java.util.ArrayList;
019 import java.util.List;
020 
021 import org.qedeq.base.trace.Trace;
022 import org.qedeq.base.utility.StringUtility;
023 import org.qedeq.kernel.bo.log.ModuleEventLog;
024 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
025 import org.qedeq.kernel.bo.module.ModuleConstantsExistenceChecker;
026 import org.qedeq.kernel.bo.module.ModuleLabels;
027 import org.qedeq.kernel.se.common.DefaultSourceFileExceptionList;
028 import org.qedeq.kernel.se.common.DependencyState;
029 import org.qedeq.kernel.se.common.LoadingState;
030 import org.qedeq.kernel.se.common.LogicalModuleState;
031 import org.qedeq.kernel.se.common.ModuleDataException;
032 import org.qedeq.kernel.se.common.Plugin;
033 import org.qedeq.kernel.se.common.SourceFileExceptionList;
034 import org.qedeq.kernel.se.dto.module.QedeqVo;
035 
036 
037 /**
038  * Changes the states of {@link org.qedeq.kernel.bo.service.DefaultKernelQedeqBo}s.
039  * All state changing is done here.
040  *
041  @author  Michael Meyling
042  */
043 public class StateManager {
044 
045     /** This class. */
046     private static final Class CLASS = StateManager.class;
047 
048     /** Main BO to care about. */
049     private final DefaultKernelQedeqBo bo;
050 
051     /** Completeness during loading from web. */
052     private int loadingCompleteness;
053 
054     /** Describes QEDEQ module loading state. */
055     private LoadingState loadingState;
056 
057     /** Describes QEDEQ module dependency state. */
058     private DependencyState dependencyState;
059 
060     /** Describes QEDEQ module logical state. */
061     private LogicalModuleState logicalState;
062 
063     /** Holds QEDEQ module plugin results. */
064     private PluginResultManager pluginResults;
065 
066     /** Failure exceptions for basic operations. */
067     private SourceFileExceptionList errors;
068 
069 
070     StateManager(final DefaultKernelQedeqBo bo) {
071         this.bo = bo;
072         loadingState = LoadingState.STATE_UNDEFINED;
073         loadingCompleteness = 0;
074         dependencyState = DependencyState.STATE_UNDEFINED;
075         logicalState = LogicalModuleState.STATE_UNCHECKED;
076         pluginResults = new PluginResultManager();
077     }
078 
079     /**
080      * Delete QEDEQ module. Invalidates all dependent modules.
081      */
082     public void delete() {
083         checkIfDeleted();
084         invalidateOtherDependentModulesToLoaded();
085         setLoadingState(LoadingState.STATE_DELETED);
086         bo.setQedeqVo(null);
087         bo.getKernelRequiredModules().clear();
088         bo.getDependentModules().clear();
089         bo.setLabels(null);
090         setDependencyState(DependencyState.STATE_UNDEFINED);
091         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
092         setErrors(null);
093         ModuleEventLog.getInstance().removeModule(bo);
094     }
095 
096     /**
097      * Is the module in a failure state? That is the case if loading of module or imported modules
098      * failed or the logical check failed. Possible plugin failures don't matter.
099      *
100      @return  Failure during loading or logical check occurred.
101      */
102     public boolean hasBasicFailures() {
103         return loadingState.isFailure() || dependencyState.isFailure() || logicalState.isFailure();
104     }
105 
106     /**
107      * Has the module any errors? This includes loading, importing, logical and plugin errors.
108      *
109      @return  Errors occurred.
110      */
111     public boolean hasErrors() {
112         return hasBasicFailures() || (getErrors() != null && getErrors().size() 0);
113     }
114 
115     /**
116      * Has the module any warnings? This includes loading, importing, logical and plugin warnings.
117      *
118      @return  Warnings occurred.
119      */
120     public boolean hasWarnings() {
121         return (getWarnings() != null && getWarnings().size() 0);
122     }
123 
124     /**
125      * Set completeness percentage.
126      *
127      @param   completeness    Completeness of loading into memory.
128      */
129     public void setLoadingCompleteness(final int completeness) {
130         this.loadingCompleteness = completeness;
131     }
132 
133     /**
134      * Get loading completeness percentage.
135      *
136      @return  Completeness as percent number.
137      */
138     public int getLoadingCompleteness() {
139         return this.loadingCompleteness;
140     }
141 
142     /**
143      * Get loading state.
144      *
145      @return  Loading state.
146      */
147     public LoadingState getLoadingState() {
148         return this.loadingState;
149     }
150 
151     /**
152      * Is the module loaded?
153      *
154      @return  Is the module loaded?
155      */
156     public boolean isLoaded() {
157         return loadingState == LoadingState.STATE_LOADED;
158     }
159 
160     /**
161      * Set loading progress module state.
162      *
163      @param   state   Module loading state. Must not be <code>null</code>.
164      @throws  IllegalStateException   State is a failure state or module loaded state.
165      */
166     public void setLoadingProgressState(final LoadingState state) {
167         checkIfDeleted();
168         if (state == LoadingState.STATE_LOADED) {
169             throw new IllegalArgumentException(
170                 "this state could only be set by calling method setLoaded");
171         }
172         if (state != LoadingState.STATE_DELETED  && state.isFailure()) {
173             throw new IllegalArgumentException(
174                 "this is a failure state, call setLoadingFailureState for " + state);
175         }
176         // if module has no loading state we give him one before creating an event
177         if (getLoadingState() == LoadingState.STATE_UNDEFINED) {
178             setLoadingState(state);
179             ModuleEventLog.getInstance().addModule(bo);
180         }
181         if (state == LoadingState.STATE_LOADING_FROM_BUFFER) {
182             invalidateOtherDependentModulesToLoaded();
183         }
184         if (state == LoadingState.STATE_DELETED) {
185             throw new IllegalArgumentException(
186                 "call delete for " + state);
187         }
188         setLoadingState(state);
189         bo.setQedeqVo(null);
190         bo.getKernelRequiredModules().clear();
191         bo.getDependentModules().clear();
192         bo.setLabels(null);
193         setDependencyState(DependencyState.STATE_UNDEFINED);
194         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
195         setErrors(null);
196         ModuleEventLog.getInstance().stateChanged(bo);
197     }
198 
199     /**
200      * Set failure module state.
201      *
202      @param   state   Module loading state. Must not be <code>null</code>.
203      @param   e       Exception that occurred during loading. Must not be <code>null</code>.
204      @throws  IllegalArgumentException    <code>state</code> is no failure state
205      */
206     public void setLoadingFailureState(final LoadingState state,
207             final SourceFileExceptionList e) {
208         if (e == null) {
209             throw new NullPointerException("Exception must not be null");
210         }
211         checkIfDeleted();
212         if (!state.isFailure()) {
213             throw new IllegalArgumentException(
214                 "this is no failure state, call setLoadingProgressState");
215         }
216         // if module has no loading state we give him one before creating an event
217         if (getLoadingState() == LoadingState.STATE_UNDEFINED) {
218             setLoadingState(state);
219             ModuleEventLog.getInstance().addModule(bo);
220         }
221         invalidateOtherDependentModulesToLoaded();
222         bo.setQedeqVo(null);
223         bo.getKernelRequiredModules().clear();
224         bo.getDependentModules().clear();
225         bo.setLabels(null);
226         setLoadingState(state);
227         setDependencyState(DependencyState.STATE_UNDEFINED);
228         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
229         setErrors(e);
230         ModuleEventLog.getInstance().stateChanged(bo);
231     }
232 
233     /**
234      * Set loading state to "loaded". Also puts <code>null</code> to
235      {@link DefaultKernelQedeqBo#getLabels()}.
236      *
237      @param   qedeq   This module was loaded. Must not be <code>null</code>.
238      @param   labels  Module labels.
239      @throws  NullPointerException    One argument was <code>null</code>.
240      */
241     public void setLoaded(final QedeqVo qedeq, final ModuleLabels labels) {
242         checkIfDeleted();
243         if (qedeq == null) {
244             throw new NullPointerException("Qedeq is null");
245         }
246         invalidateOtherDependentModulesToLoaded();
247         setLoadingState(LoadingState.STATE_LOADED);
248         bo.setQedeqVo(qedeq);
249         bo.getKernelRequiredModules().clear();
250         bo.getDependentModules().clear();
251         bo.setLabels(labels);
252         setDependencyState(DependencyState.STATE_UNDEFINED);
253         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
254         setErrors(null);
255         ModuleEventLog.getInstance().stateChanged(bo);
256     }
257 
258     /**
259      * Set dependency progress module state.
260      *
261      @param   state   Module state. Must not be <code>null</code>.
262      @throws  IllegalStateException       Module is not yet loaded.
263      @throws  IllegalArgumentException    <code>state</code> is failure state or loaded required
264      *                                      state.
265      @throws  NullPointerException        <code>state</code> is <code>null</code>.
266      */
267     public void setDependencyProgressState(final DependencyState state) {
268         checkIfDeleted();
269         if (!isLoaded() && state != DependencyState.STATE_UNDEFINED) {
270             throw new IllegalStateException("module is not yet loaded");
271         }
272         if (state.isFailure()) {
273             throw new IllegalArgumentException(
274                 "this is a failure state, call setDependencyFailureState");
275         }
276         if (state == DependencyState.STATE_LOADED_REQUIRED_MODULES) {
277             throw new IllegalArgumentException(
278                 "this state could only be set by calling method setLoadedRequiredModules");
279         }
280         if (state == DependencyState.STATE_LOADING_REQUIRED_MODULES) {
281             invalidateOtherDependentModulesToLoaded();
282         }
283         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
284         setDependencyState(state);
285         bo.getKernelRequiredModules().clear();
286         setErrors(null);
287         ModuleEventLog.getInstance().stateChanged(bo);
288     }
289 
290    /**
291     * Set failure module state.
292     *
293     @param   state   Module dependency state. Must not be <code>null</code>.
294     @param   e       Exception that occurred during loading. Must not be <code>null</code>.
295     @throws  IllegalStateException       Module is not yet loaded.
296     @throws  IllegalArgumentException    <code>state</code> is no failure state.
297     @throws  NullPointerException        <code>state</code> is <code>null</code>.
298     */
299     public void setDependencyFailureState(final DependencyState state,
300             final SourceFileExceptionList e) {
301         if (e == null) {
302             throw new NullPointerException("Exception must not be null");
303         }
304         checkIfDeleted();
305         if (!isLoaded()) {
306             throw new IllegalStateException("module is not yet loaded");
307         }
308         if (!state.isFailure()) {
309             throw new IllegalArgumentException(
310                 "this is no failure state, call setLoadingProgressState");
311         }
312         invalidateOtherDependentModulesToLoadedRequired();
313         setDependencyState(state);
314         setErrors(e);
315         ModuleEventLog.getInstance().stateChanged(bo);
316     }
317 
318     /**
319      * Get dependency state.
320      *
321      @return  Dependency state.
322      */
323     public DependencyState getDependencyState() {
324         return this.dependencyState;
325     }
326 
327     /**
328      * Reset all (recursive) dependent modules (if any) to state loaded.
329      */
330     private void invalidateOtherDependentModulesToLoaded() {
331         final String method = "invalidateOtherDependModulesToLoaded";
332         Trace.begin(CLASS, this, method);
333         Trace.param(CLASS, this, method, "bo", bo);
334         if (hasLoadedRequiredModules()) {
335             final KernelModuleReferenceList dependent = bo.getDependentModules();
336             Trace.trace(CLASS, this, method, "begin list of dependent modules");
337             // remember dependent modules
338             final List list = new ArrayList();
339             for (int i = 0; i < dependent.size(); i++) {
340                 Trace.param(CLASS, this, method, "" + i, dependent.getKernelQedeqBo(i));
341                 list.add(dependent.getKernelQedeqBo(i));
342             }
343             Trace.trace(CLASS, this, method, "end list of dependent modules");
344             for (int i = 0; i < list.size(); i++) {
345                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBolist.get(i);
346                 // work on it, if still in list of dependent modules
347                 if (dependent.contains(ref)) {
348                     ref.getStateManager().invalidateDependentModulesToLoaded();
349                 }
350             }
351             list.clear();
352             dependent.clear();
353 
354             final KernelModuleReferenceList required = bo.getKernelRequiredModules();
355             for (int i = 0; i < required.size(); i++) {
356                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBorequired.getKernelQedeqBo(i);
357                 Trace.param(CLASS, this, method, "remove dependence from", ref);
358                 ref.getDependentModules().remove(bo);
359             }
360             required.clear();
361         }
362         Trace.end(CLASS, this, method);
363     }
364 
365     /**
366      * Reset this and all (recursive) dependent modules (if any) to state loaded.
367      */
368     private void invalidateDependentModulesToLoaded() {
369         final String method = "invalidateDependentModulesToLoaded";
370         Trace.begin(CLASS, this, method);
371         Trace.param(CLASS, this, method, "bo", bo);
372         if (hasLoadedRequiredModules()) {
373             final KernelModuleReferenceList dependent = bo.getDependentModules();
374             Trace.trace(CLASS, this, method, "begin list of dependent modules");
375             // remember dependent modules
376             final List list = new ArrayList();
377             for (int i = 0; i < dependent.size(); i++) {
378                 Trace.param(CLASS, this, method, "" + i, dependent.getKernelQedeqBo(i));
379                 list.add(dependent.getKernelQedeqBo(i));
380             }
381             Trace.trace(CLASS, this, method, "end list of dependent modules");
382             for (int i = 0; i < list.size(); i++) {
383                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBolist.get(i);
384                 // work on it, if still in list of dependent modules
385                 if (dependent.contains(ref)) {
386                     ref.getStateManager().invalidateDependentModulesToLoaded();
387                 }
388             }
389             list.clear();
390             dependent.clear();
391 
392             final KernelModuleReferenceList required = bo.getKernelRequiredModules();
393             for (int i = 0; i < required.size(); i++) {
394                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBorequired.getKernelQedeqBo(i);
395                 Trace.param(CLASS, this, method, "remove dependence from", ref);
396                 ref.getDependentModules().remove(bo);
397             }
398             required.clear();
399 
400             invalidateThisModule();
401             setLoadingState(LoadingState.STATE_LOADED);
402             ModuleEventLog.getInstance().stateChanged(bo);
403         }
404         Trace.end(CLASS, this, method);
405     }
406 
407     /**
408      * Reset all (recursive) dependent modules (if any) to state loaded required.
409      */
410     private void invalidateOtherDependentModulesToLoadedRequired() {
411         if (isChecked()) {
412             final KernelModuleReferenceList dependent = bo.getDependentModules();
413             for (int i = 0; i < dependent.size(); i++) {
414                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBodependent.getKernelQedeqBo(i);
415                 ref.getStateManager().invalidateDependentModulesToLoadedRequired();
416             }
417         }
418     }
419 
420     /**
421      * Reset this and all (recursive) dependent modules (if any) to state loaded required.
422      */
423     private void invalidateDependentModulesToLoadedRequired() {
424         if (isChecked()) {
425             final KernelModuleReferenceList dependent = bo.getDependentModules();
426             for (int i = 0; i < dependent.size(); i++) {
427                 DefaultKernelQedeqBo ref = (DefaultKernelQedeqBodependent.getKernelQedeqBo(i);
428                 ref.getStateManager().invalidateDependentModulesToLoadedRequired();
429             }
430             invalidateThisModule();
431             setDependencyState(DependencyState.STATE_LOADED_REQUIRED_MODULES);
432             ModuleEventLog.getInstance().stateChanged(bo);
433         }
434     }
435 
436     private void invalidateThisModule() {
437         setLoadingState(LoadingState.STATE_LOADED);
438         setDependencyState(DependencyState.STATE_UNDEFINED);
439         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
440         setErrors(null);
441     }
442 
443     /**
444      * Are all required modules loaded?
445      *
446      @return  All required modules are loaded?
447      */
448     public boolean hasLoadedRequiredModules() {
449         return isLoaded() && dependencyState == DependencyState.STATE_LOADED_REQUIRED_MODULES;
450     }
451 
452     /**
453      * Set loaded required requirements state.
454      *
455      @param   required  URLs of all referenced modules. Must not be <code>null</code>.
456      @throws  IllegalStateException   Module is not yet loaded.
457      */
458     public void setLoadedRequiredModules(final KernelModuleReferenceList required) {
459         checkIfDeleted();
460         if (!isLoaded()) {
461             throw new IllegalStateException(
462                 "Required modules can only be set if module is loaded."
463                 "\"\nCurrently the status for the module"
464                 "\"" + bo.getName() "\" is \"" + bo.getLoadingState() "\"");
465         }
466         invalidateDependentModulesToLoadedRequired();
467 
468         for (int i = 0; i < required.size(); i++) {
469             DefaultKernelQedeqBo current = (DefaultKernelQedeqBorequired.getKernelQedeqBo(i);
470             try {
471                 current.getDependentModules().add(required.getModuleContext(i),
472                     required.getLabel(i), bo);
473             catch (ModuleDataException me) {  // should never happen
474                 throw new RuntimeException(me);
475             }
476         }
477 
478         setDependencyState(DependencyState.STATE_LOADED_REQUIRED_MODULES);
479         setLogicalState(LogicalModuleState.STATE_UNCHECKED);
480         setErrors(null);
481         bo.getKernelRequiredModules().set(required);
482         ModuleEventLog.getInstance().stateChanged(bo);
483     }
484 
485     /**
486      * Set logic checked state. Also set the predicate and function existence checker.
487      *
488      @param   checker Checks if a predicate or function constant is defined.
489      */
490     public void setChecked(final ModuleConstantsExistenceChecker checker) {
491         checkIfDeleted();
492         if (!hasLoadedRequiredModules()) {
493             throw new IllegalStateException(
494                 "Checked can only be set if all required modules are loaded."
495                 "\"\nCurrently the status for the module"
496                 "\"" + bo.getName() "\" is \"" + bo.getLoadingState() "\"");
497         }
498         setLogicalState(LogicalModuleState.STATE_CHECKED);
499         bo.setExistenceChecker(checker);
500         ModuleEventLog.getInstance().stateChanged(bo);
501     }
502 
503    /**
504     * Set loading progress module state. Must not be <code>null</code>.
505     *
506     @param   state   module state
507     */
508     public void setLogicalProgressState(final LogicalModuleState state) {
509         if (getDependencyState().getCode()
510                 < DependencyState.STATE_LOADED_REQUIRED_MODULES.getCode()
511                 && state != LogicalModuleState.STATE_UNCHECKED) {
512             throw new IllegalArgumentException(
513                 "this state could only be set if all required modules are loaded ");
514         }
515         if (state.isFailure()) {
516             throw new IllegalArgumentException(
517                 "this is a failure state, call setLogicalFailureState");
518         }
519         if (state == LogicalModuleState.STATE_CHECKED) {
520             throw new IllegalArgumentException(
521                 "set with setChecked(ExistenceChecker)");
522         }
523         invalidateOtherDependentModulesToLoadedRequired();
524         setLogicalState(state);
525         setErrors(null);
526         ModuleEventLog.getInstance().stateChanged(bo);
527     }
528 
529     /**
530      * Set failure module state.
531      *
532      @param   state   module state
533      @param   e       Exception that occurred during loading.
534      @throws  IllegalArgumentException    <code>state</code> is no failure state
535      */
536     public void setLogicalFailureState(final LogicalModuleState state,
537             final SourceFileExceptionList e) {
538         if ((!isLoaded() || !hasLoadedRequiredModules())
539                 && state != LogicalModuleState.STATE_UNCHECKED) {
540             throw new IllegalArgumentException(
541                 "this state could only be set if all required modules are loaded ");
542         }
543         if (!state.isFailure()) {
544             throw new IllegalArgumentException(
545                 "this is no failure state, call setLogicalProgressState");
546         }
547         invalidateDependentModulesToLoadedRequired();
548         setLogicalState(state);
549         setErrors(e);
550         ModuleEventLog.getInstance().stateChanged(bo);
551     }
552 
553     /**
554      * Checks if the current instance is already deleted.
555      *
556      @throws  IllegalStateException   Module is already deleted.
557      */
558     private void checkIfDeleted() {
559         if (getLoadingState() == LoadingState.STATE_DELETED) {
560             throw new IllegalStateException("module is already deleted: " + bo.getUrl());
561         }
562     }
563 
564     /**
565      * Was the module successfully checked for logical errors?
566      *
567      @return  Successfully checked for logical errors?
568      */
569     public boolean isChecked() {
570         return isLoaded() && hasLoadedRequiredModules()
571             && logicalState == LogicalModuleState.STATE_CHECKED;
572     }
573 
574     /**
575      * Get the logical state.
576      *
577      @return  Logical state.
578      */
579     public LogicalModuleState getLogicalState() {
580         return this.logicalState;
581     }
582 
583     /**
584      * Get a description of the current state the module is in.
585      *
586      @return  Textual representation of module state.
587      */
588     public String getStateDescription() {
589         String result = "";
590         if (loadingState == LoadingState.STATE_LOADING_FROM_WEB) {
591             result = loadingState.getText() " (" + loadingCompleteness + "%)";
592         else if (!isLoaded()) {
593             result = loadingState.getText();
594         else if (!hasLoadedRequiredModules()) {
595             if (dependencyState == DependencyState.STATE_UNDEFINED) {
596                 result = loadingState.getText();
597             }
598             result = dependencyState.getText();
599         else if (!isChecked()) {
600             if (logicalState == LogicalModuleState.STATE_UNCHECKED) {
601                 result = dependencyState.getText();
602             }
603             result = logicalState.getText();
604         else {
605             result =  logicalState.getText();
606         }
607         final String pluginState = pluginResults.getPluginStateDescription();
608         if (pluginState.length() 0) {
609             result += "; " + pluginState;
610         }
611         return result;
612     }
613 
614     /**
615      * Set {@link LoadingState}. Doesn't do any status handling. Only for internal use.
616      *
617      @param   state   Set this loading state.
618      */
619     protected void setLoadingState(final LoadingState state) {
620         this.loadingState = state;
621     }
622 
623     /**
624      * Set {@link DependencyState}. Doesn't do any status handling. Only for internal use.
625      *
626      @param   state   Set this dependency state.
627      */
628     protected void setDependencyState(final DependencyState state) {
629         this.dependencyState = state;
630     }
631 
632     /**
633      * Set {@link LogicalModuleState}. Doesn't do any status handling. Only for internal use.
634      *
635      @param   state   Set this logical state.
636      */
637     protected void setLogicalState(final LogicalModuleState state) {
638         this.logicalState = state;
639     }
640 
641     /**
642      * Get all errors.
643      *
644      @return  Errors. Is a newly created list.
645      */
646     public SourceFileExceptionList getErrors() {
647         final DefaultSourceFileExceptionList result = new DefaultSourceFileExceptionList(errors);
648         result.add(pluginResults.getAllErrors());
649         return result;
650     }
651 
652     /**
653      * Get all warnings.
654      *
655      @return  Warnings. Is a newly created list.
656      */
657     public SourceFileExceptionList getWarnings() {
658         final DefaultSourceFileExceptionList result = new DefaultSourceFileExceptionList();
659         result.add(pluginResults.getAllWarnings());
660         return result;
661     }
662 
663     /**
664      * Set {@link SourceFileExceptionList}. Doesn't do any status handling. Only for internal use.
665      *
666      @param   errors   Set this error list.
667      */
668     protected void setErrors(final SourceFileExceptionList errors) {
669         this.errors = errors;
670         // TODO mime 20100625: "if errors==null" this should be a new function "clearErrors" or other
671         if (errors == null) {
672             pluginResults = new PluginResultManager();
673         }
674     }
675 
676     /**
677      * Add the plugin execution errors and warnings.
678      *
679      @param   plugin      Plugin that was executed.
680      @param   errors      Resulting errors.
681      @param   warnings    Resulting warnings.
682      */
683     public void addPluginResults(final Plugin plugin, final SourceFileExceptionList errors,
684             final SourceFileExceptionList warnings) {
685         pluginResults.addResult(plugin, errors, warnings);
686         ModuleEventLog.getInstance().stateChanged(bo);
687     }
688 
689     /**
690      * Remove all plugin errors and warnings.
691      */
692     public void removeAllPluginResults() {
693         pluginResults.removeAllResults();
694         ModuleEventLog.getInstance().stateChanged(bo);
695     }
696 
697     /**
698      * Print the dependence tree to <code>System.out</code>.
699      */
700     public void printDependencyTree() {
701         printDependencyTree(0);
702         System.out.println();
703     }
704 
705     private void printDependencyTree(final int tab) {
706         System.out.println(StringUtility.getSpaces(tab+ bo.getName());
707         final int newTab = tab + bo.getName().length();
708         final KernelModuleReferenceList dependent = bo.getDependentModules();
709         for (int i = 0; i < dependent.size(); i++) {
710             DefaultKernelQedeqBo ref = (DefaultKernelQedeqBodependent.getKernelQedeqBo(i);
711             ref.getStateManager().printDependencyTree(newTab);
712         }
713     }
714 
715 }