DefaultKernelQedeqBo.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.io.SourceArea;
022 import org.qedeq.base.trace.Trace;
023 import org.qedeq.base.utility.EqualsUtility;
024 import org.qedeq.base.utility.StringUtility;
025 import org.qedeq.kernel.bo.common.ModuleReferenceList;
026 import org.qedeq.kernel.bo.module.Element2Latex;
027 import org.qedeq.kernel.bo.module.Element2Utf8;
028 import org.qedeq.kernel.bo.module.InternalKernelServices;
029 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
030 import org.qedeq.kernel.bo.module.KernelQedeqBo;
031 import org.qedeq.kernel.bo.module.ModuleConstantsExistenceChecker;
032 import org.qedeq.kernel.bo.module.ModuleLabels;
033 import org.qedeq.kernel.bo.module.QedeqFileDao;
034 import org.qedeq.kernel.se.base.module.LatexList;
035 import org.qedeq.kernel.se.base.module.Qedeq;
036 import org.qedeq.kernel.se.common.DefaultSourceFileExceptionList;
037 import org.qedeq.kernel.se.common.DependencyState;
038 import org.qedeq.kernel.se.common.LoadingState;
039 import org.qedeq.kernel.se.common.LogicalModuleState;
040 import org.qedeq.kernel.se.common.ModuleAddress;
041 import org.qedeq.kernel.se.common.ModuleContext;
042 import org.qedeq.kernel.se.common.ModuleDataException;
043 import org.qedeq.kernel.se.common.Plugin;
044 import org.qedeq.kernel.se.common.SourceFileException;
045 import org.qedeq.kernel.se.common.SourceFileExceptionList;
046 import org.qedeq.kernel.se.dto.module.QedeqVo;
047 
048 
049 /**
050  * Represents a module and its states. This is a kernel intern representation.
051  *
052  @author  Michael Meyling
053  */
054 public class DefaultKernelQedeqBo implements KernelQedeqBo {
055 
056     /** This class. */
057     private static final Class CLASS = DefaultKernelQedeqBo.class;
058 
059     /** Internal kernel services. */
060     private final InternalKernelServices services;
061 
062     /** Address and module specification. */
063     private final ModuleAddress address;
064 
065     /** Loaded QEDEQ module. */
066     private QedeqVo qedeq;
067 
068     /** Required QEDEQ modules. */
069     private KernelModuleReferenceList required;
070 
071     /** Dependent QEDEQ modules. */
072     private KernelModuleReferenceList dependent;
073 
074     /** Predicate and function constant existence checker. */
075     private ModuleConstantsExistenceChecker checker;
076 
077     /** Labels for this module, definitions, etc. */
078     private ModuleLabels labels;
079 
080     /** Can map elements to LaTeX. */
081     private Element2Latex converter;
082 
083     /** Can map elements to UTF-8 text. */
084     private Element2Utf8 textConverter;
085 
086     /** Loader used for loading this object. */
087     private QedeqFileDao loader;
088 
089     /** State change manager. */
090     private final StateManager stateManager;
091 
092     /**
093      * Creates new module properties.
094      *
095      @param   services    Internal kernel services.
096      @param   address     Module address (not <code>null</code>).
097      @throws  NullPointerException    <code>address</code> is null.
098      */
099     public DefaultKernelQedeqBo(final InternalKernelServices services,
100             final ModuleAddress address) {
101         this.services = services;
102         this.address = address;
103         if (address == null) {
104             throw new NullPointerException("ModuleAddress must not be null");
105         }
106         required = new KernelModuleReferenceList();
107         dependent = new KernelModuleReferenceList();
108         stateManager = new StateManager(this);
109     }
110 
111     /**
112      * Set loader used for loading this object.
113      *
114      @param   loader  Responsible loader.
115      */
116     public void setQedeqFileDao(final QedeqFileDao loader) {
117         this.loader = loader;
118     }
119 
120     /**
121      * Get loader used to load this object.
122      *
123      @return  Loader.
124      */
125     public QedeqFileDao getLoader() {
126         return this.loader;
127     }
128 
129     public boolean hasBasicFailures() {
130         return stateManager.hasBasicFailures();
131     }
132 
133     public boolean hasErrors() {
134         return stateManager.hasErrors();
135     }
136 
137     public boolean hasWarnings() {
138         return stateManager.hasWarnings();
139     }
140 
141     public ModuleAddress getModuleAddress() {
142         return address;
143     }
144 
145     /**
146      * Get internal kernel services.
147      *
148      @return  Internal kernel services.
149      */
150     public InternalKernelServices getKernelServices() {
151         return this.services;
152     }
153 
154     /**
155      * Set completeness percentage.
156      *
157      @param   completeness    Completeness of loading into memory.
158      */
159     public void setLoadingCompleteness(final int completeness) {
160         stateManager.setLoadingCompleteness(completeness);
161     }
162 
163     public int getLoadingCompleteness() {
164         return stateManager.getLoadingCompleteness();
165     }
166 
167     /**
168      * Delete QEDEQ module. Invalidates all dependent modules.
169      */
170     public void delete() {
171         stateManager.delete();
172     }
173 
174     /**
175      * Set loading progress module state.
176      *
177      @param   state   Module loading state. Must not be <code>null</code>.
178      @throws  IllegalStateException   State is a failure state or module loaded state.
179      */
180     public void setLoadingProgressState(final LoadingState state) {
181         stateManager.setLoadingProgressState(state);
182     }
183 
184     /**
185      * Set failure module state.
186      *
187      @param   state   Module loading state. Must not be <code>null</code>.
188      @param   e       Exception that occurred during loading. Must not be <code>null</code>.
189      @throws  IllegalArgumentException    <code>state</code> is no failure state
190      */
191     public void setLoadingFailureState(final LoadingState state,
192             final SourceFileExceptionList e) {
193         stateManager.setLoadingFailureState(state, e);
194     }
195 
196     public LoadingState getLoadingState() {
197         return stateManager.getLoadingState();
198     }
199 
200     public boolean isLoaded() {
201         return stateManager.isLoaded();
202     }
203 
204     /**
205      * Set loading state to "loaded". Also puts <code>null</code> to {@link #getLabels()}.
206      *
207      @param   qedeq       This module was loaded. Must not be <code>null</code>.
208      @param   labels      Module labels.
209      @param   converter   Can convert elements into LaTeX. Must not be <code>null</code>.
210      @param   textConverter   Can convert elements into UTF-8 text. Must not be <code>null</code>.
211      @throws  NullPointerException    One argument was <code>null</code>.
212      */
213     public void setLoaded(final QedeqVo qedeq, final ModuleLabels labels,
214             final Element2Latex converter, final Element2Utf8 textConverter) {
215         stateManager.setLoaded(qedeq, labels);
216         this.converter = converter;
217         this.textConverter = textConverter;
218     }
219 
220     public Qedeq getQedeq() {
221         return this.qedeq;
222     }
223 
224     public Element2Latex getElement2Latex() {
225         return this.converter;
226     }
227 
228     public Element2Utf8 getElement2Utf8() {
229         return this.textConverter;
230     }
231 
232     /**
233      * Set dependency progress module state.
234      *
235      @param   state   Module state. Must not be <code>null</code>.
236      @throws  IllegalStateException       Module is not yet loaded.
237      @throws  IllegalArgumentException    <code>state</code> is failure state or loaded required
238      *                                      state.
239      @throws  NullPointerException        <code>state</code> is <code>null</code>.
240      */
241     public void setDependencyProgressState(final DependencyState state) {
242         stateManager.setDependencyProgressState(state);
243     }
244 
245    /**
246     * Set failure module state.
247     *
248     @param   state   Module dependency state. Must not be <code>null</code>.
249     @param   e       Exception that occurred during loading. Must not be <code>null</code>.
250     @throws  IllegalStateException       Module is not yet loaded.
251     @throws  IllegalArgumentException    <code>state</code> is no failure state.
252     @throws  NullPointerException        <code>state</code> is <code>null</code>.
253     */
254     public void setDependencyFailureState(final DependencyState state,
255             final SourceFileExceptionList e) {
256         stateManager.setDependencyFailureState(state, e);
257     }
258 
259     public DependencyState getDependencyState() {
260         return stateManager.getDependencyState();
261     }
262 
263     /**
264      * Set loaded required requirements state.
265      *
266      @param   list        URLs of all referenced modules. Must not be <code>null</code>.
267      @throws  IllegalStateException   Module is not yet loaded.
268      */
269     public void setLoadedRequiredModules(final KernelModuleReferenceList list) {
270         stateManager.setLoadedRequiredModules(list);
271     }
272 
273     public ModuleReferenceList getRequiredModules() {
274         return getKernelRequiredModules();
275     }
276 
277     public KernelModuleReferenceList getKernelRequiredModules() {
278         return required;
279     }
280 
281     public boolean hasLoadedRequiredModules() {
282         return stateManager.hasLoadedRequiredModules();
283     }
284 
285     /**
286      * Get labels and URLs of all directly dependent modules.
287      *
288      @return  URLs of all referenced modules.
289      */
290     public KernelModuleReferenceList getDependentModules() {
291         return dependent;
292     }
293 
294     public void setChecked(final ModuleConstantsExistenceChecker checker) {
295         stateManager.setChecked(checker);
296     }
297 
298     public boolean isChecked() {
299         return stateManager.isChecked();
300     }
301 
302     public void setLogicalProgressState(final LogicalModuleState state) {
303         stateManager.setLogicalProgressState(state);
304     }
305 
306     public void setLogicalFailureState(final LogicalModuleState state,
307             final SourceFileExceptionList e) {
308         stateManager.setLogicalFailureState(state, e);
309     }
310 
311     public LogicalModuleState getLogicalState() {
312         return stateManager.getLogicalState();
313     }
314 
315     public SourceFileExceptionList getErrors() {
316         return stateManager.getErrors();
317     }
318 
319     public SourceFileExceptionList getWarnings() {
320         return stateManager.getWarnings();
321     }
322 
323     public String getStateDescription() {
324         return stateManager.getStateDescription();
325     }
326 
327     public String getName() {
328         if (address == null) {
329             return "null";
330         }
331         return address.getName();
332     }
333 
334     public String getRuleVersion() {
335         if (address == null || qedeq == null
336                 || qedeq.getHeader() == null
337                 || qedeq.getHeader().getSpecification() == null
338                 || qedeq.getHeader().getSpecification().getRuleVersion() == null) {
339             return "";
340         }
341         return qedeq.getHeader().getSpecification().getRuleVersion();
342     }
343 
344     public String getUrl() {
345         if (this.address == null) {
346             return null;
347         }
348         return this.address.getUrl();
349     }
350 
351     /**
352      * Set label references for QEDEQ module.
353      *
354      @param   labels  Label references.
355      */
356     public void setLabels(final ModuleLabels labels) {
357         this.labels = labels;
358     }
359 
360     public ModuleLabels getLabels() {
361         return labels;
362     }
363 
364     /**
365      * Create exception out of {@link ModuleDataException}.
366      *
367      @param   plugin      This plugin generated the error.
368      @param   exception   Take this exception.
369      @return  Newly created instance.
370      */
371     public SourceFileExceptionList createSourceFileExceptionList(final Plugin plugin,
372             final ModuleDataException exception) {
373         SourceArea referenceArea = null;
374         if (exception.getReferenceContext() != null) {
375             referenceArea = createSourceArea(qedeq, exception.getReferenceContext());
376         }
377         final SourceFileException e = new SourceFileException(plugin, exception,
378             createSourceArea(qedeq, exception.getContext()), referenceArea);
379         final DefaultSourceFileExceptionList list = new DefaultSourceFileExceptionList(e);
380         return list;
381     }
382 
383     /**
384      * Create exception out of {@link ModuleDataException}.
385      *
386      @param   plugin      This plugin generated the error.
387      @param   exception   Take this exception.
388      @param   qedeq       Take this QEDEQ source. (This might not be accessible via
389      *                      {@link #getQedeq()}.
390      @return  Newly created instance.
391      */
392     public SourceFileExceptionList createSourceFileExceptionList(final Plugin plugin,
393             final ModuleDataException exception, final Qedeq qedeq) {
394         final SourceFileException e = new SourceFileException(plugin, exception,
395             createSourceArea(qedeq, exception.getContext()), createSourceArea(qedeq,
396                 exception.getReferenceContext()));
397         final DefaultSourceFileExceptionList list = new DefaultSourceFileExceptionList(e);
398         return list;
399     }
400 
401     public SourceFileException createSourceFileException(final Plugin plugin, final ModuleDataException
402             exception) {
403         final SourceArea area = createSourceArea(qedeq, exception.getContext());
404         SourceArea referenceArea = null;
405         if (exception.getReferenceContext() != null) {
406             referenceArea = createSourceArea(qedeq, exception.getReferenceContext());
407         }
408         final SourceFileException e = new SourceFileException(plugin, exception, area, referenceArea);
409         return e;
410     }
411 
412     /**
413      * Create area in source file for QEDEQ module context.
414      * If the system property "qedeq.test.xmlLocationFailures" is set to "true" a runtime
415      * exception is thrown if the context is not found.
416      *
417      @param   qedeq       Look at this QEDEQ module.
418      @param   context     Search for this context.
419      @return  Created file area. Maybe <code>null</code>.
420      */
421     public SourceArea createSourceArea(final Qedeq qedeq, final ModuleContext context) {
422         final String method = "createSourceArea(Qedeq, ModuleContext)";
423         SourceArea area = null;
424         try {
425             area = loader.createSourceArea(qedeq, context);
426         catch (RuntimeException e) {
427             Trace.fatal(CLASS, method, "loader couldn't create context: " + context, e);
428             if (Boolean.TRUE.toString().equalsIgnoreCase(
429                     System.getProperty("qedeq.test.xmlLocationFailures"))) {
430                 throw e;
431             }
432         }
433         if (area == null) {
434             Trace.fatal(CLASS, "createSourceArea""loader coudn't create context: "
435                 + context, new NullPointerException());
436             area = new SourceArea(this.getModuleAddress().getUrl());
437         }
438         return area;
439     }
440 
441     public String[] getSupportedLanguages() {
442         // TODO m31 20070704: there should be a better way to
443         // get all supported languages. Time for a new visitor?
444         if (!isLoaded() || getQedeq() == null || getQedeq().getHeader() == null
445                 || getQedeq().getHeader().getTitle() == null) {
446             return new String[]{};
447         }
448         final LatexList list = getQedeq().getHeader().getTitle();
449         final List result = new ArrayList(list.size());
450         for (int i = 0; i < list.size(); i++) {
451             if (null != list.get(i)) {
452                 result.add(list.get(i).getLanguage());
453             }
454         }
455         return (String[]) result.toArray(new String[]{});
456     }
457 
458     public boolean isSupportedLanguage(final String language) {
459         return StringUtility.isNotIn(language, getSupportedLanguages());
460     }
461 
462     public String getOriginalLanguage() {
463         // FIXME 20110316 m31: rework qedeq.xsd to have a default language
464         final String[] supported = getSupportedLanguages();
465         if (StringUtility.isNotIn("de", supported)) {
466             if (supported.length > 0) {
467                 return supported[0];
468             }
469             return "";
470         }
471         return "de";
472     }
473 
474 
475     /**
476      * Set {@link QedeqVo}. Doesn't do any status handling. Only for internal use.
477      *
478      @param   qedeq   Set this value.
479      */
480     public void setQedeqVo(final QedeqVo qedeq) {
481         this.qedeq = qedeq;
482     }
483 
484     /**
485      * Get {@link StateManager}. Only for internal use.
486      *
487      @return StateManager
488      */
489     protected StateManager getStateManager() {
490         return this.stateManager;
491     }
492 
493     /**
494      * Get the predicate and function existence checker. Is not <code>null</code>
495      * if logic was (not necessarily successfully) checked.
496      *
497      @return  Checker. Checks if a predicate or function constant is defined.
498      */
499     public ModuleConstantsExistenceChecker getExistenceChecker() {
500         return checker;
501     }
502 
503     public void setExistenceChecker(final ModuleConstantsExistenceChecker checker) {
504         this.checker = checker;
505     }
506 
507     public int hashCode() {
508         return (getModuleAddress() == null : getModuleAddress().hashCode());
509     }
510 
511     public boolean equals(final Object obj) {
512         if (obj instanceof DefaultKernelQedeqBo) {
513             return EqualsUtility.equals(((DefaultKernelQedeqBoobj).getModuleAddress(),
514                 this.getModuleAddress());
515         }
516         return false;
517     }
518 
519     public String toString() {
520        return address.getUrl();
521     }
522 
523     public void addPluginErrorsAndWarnings(final Plugin plugin, final SourceFileExceptionList errors,
524             final SourceFileExceptionList warnings) {
525         stateManager.addPluginResults(plugin, errors, warnings);
526     }
527 
528     public void clearAllPluginErrorsAndWarnings() {
529         stateManager.removeAllPluginResults();
530     }
531 
532 }