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