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