LoadRequiredModulesExecutor.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.dependency;
017 
018 import java.util.HashMap;
019 import java.util.Map;
020 
021 import org.qedeq.base.io.Parameters;
022 import org.qedeq.base.trace.Trace;
023 import org.qedeq.base.utility.StringUtility;
024 import org.qedeq.kernel.bo.log.QedeqLog;
025 import org.qedeq.kernel.bo.module.ControlVisitor;
026 import org.qedeq.kernel.bo.module.InternalServiceProcess;
027 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
028 import org.qedeq.kernel.bo.module.KernelQedeqBo;
029 import org.qedeq.kernel.bo.module.PluginExecutor;
030 import org.qedeq.kernel.se.common.ModuleDataException;
031 import org.qedeq.kernel.se.common.Plugin;
032 import org.qedeq.kernel.se.common.SourceFileException;
033 import org.qedeq.kernel.se.common.SourceFileExceptionList;
034 import org.qedeq.kernel.se.state.DependencyState;
035 
036 
037 /**
038  * Load all required QEDEQ modules.
039  *
040  @author  Michael Meyling
041  */
042 public final class LoadRequiredModulesExecutor extends ControlVisitor implements PluginExecutor {
043 
044     /** This class. */
045     private static final Class CLASS = LoadRequiredModulesExecutor.class;
046 
047     /**
048      * Constructor.
049      *
050      @param   plugin      Plugin we work for.
051      @param   prop        Internal QedeqBo.
052      @param   parameters  Currently ignored.
053      */
054     LoadRequiredModulesExecutor(final Plugin plugin, final KernelQedeqBo prop,
055             final Parameters parameters) {
056         super(plugin, prop);
057     }
058 
059     public Object executePlugin(final InternalServiceProcess process, final Object data) {
060         final String method = "executePlugin";
061         if (getQedeqBo().hasLoadedRequiredModules()) {
062             return Boolean.TRUE; // everything is OK
063         }
064         QedeqLog.getInstance().logRequest(
065             "Loading required modules", getQedeqBo().getUrl());
066         // all QedeqBos currently in state "loading required modules"
067         Map loadingRequiredInProgress = (Mapdata;
068         if (loadingRequiredInProgress == null) {
069             loadingRequiredInProgress = new HashMap();
070         }
071         Boolean all = (BooleangetServices().executePlugin(LoadAllRequiredModulesPlugin.class.getName(),
072                getQedeqBo(), null, process);
073         if (!all.booleanValue()) {
074             final String msg = "Loading required modules failed";
075             QedeqLog.getInstance().logFailureReply(msg, getQedeqBo().getUrl(),
076                 "Not all required modules could not even be loaded.");
077             getQedeqBo().setDependencyFailureState(
078                 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getQedeqBo().getErrors());
079             return Boolean.FALSE;
080         }
081         if (loadingRequiredInProgress.containsKey(getQedeqBo())) { // already checked?
082             throw new IllegalStateException("Programming error: must not be marked!");
083         }
084         getQedeqBo().setDependencyProgressState(getPlugin(), DependencyState.STATE_LOADING_REQUIRED_MODULES);
085 
086         loadingRequiredInProgress.put(getQedeqBo(), getQedeqBo());
087 
088         final KernelModuleReferenceList required = (KernelModuleReferenceListgetQedeqBo().getRequiredModules();
089 
090         final SourceFileExceptionList sfl = new SourceFileExceptionList();
091         Trace.trace(CLASS, this, method, "loading required modules of " + getQedeqBo().getUrl());
092         for (int i = 0; i < required.size(); i++) {
093             final KernelQedeqBo current = required.getKernelQedeqBo(i);
094             if (loadingRequiredInProgress.containsKey(current)) {
095                 ModuleDataException me = new LoadRequiredModuleException(
096                     DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
097                     DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + "\""
098                     + required.getLabel(i"\"",
099                     required.getModuleContext(i));
100                 sfl.add(createError(me));
101                 continue;
102             }
103             getQedeqBo().getKernelServices().executePlugin(LoadRequiredModulesPlugin.class.getName(),
104                 current, loadingRequiredInProgress, process);
105             if (!current.hasLoadedRequiredModules()) {
106                 // LATER 20110119 m31: we take only the first error, is that ok?
107                 String text = DependencyErrors.IMPORT_OF_MODULE_FAILED_TEXT + "\""
108                     + required.getLabel(i"\"";
109                 if (current.getErrors().size() 0) {
110                     // FIXME 20130324 m31: what if this changed directly after .size() call?
111                     text += ", " + current.getErrors().get(0).getMessage();
112                 }
113                 ModuleDataException me = new LoadRequiredModuleException(
114                     DependencyErrors.IMPORT_OF_MODULE_FAILED_CODE,
115                     text, required.getModuleContext(i));
116                 sfl.add(createError(me));
117                 continue;
118             }
119         }
120 
121         loadingRequiredInProgress.remove(getQedeqBo());
122 
123         if (getQedeqBo().getDependencyState().areAllRequiredLoaded()) {
124             return Boolean.TRUE; // everything is OK, someone elses thread might have corrected errors!
125         }
126         getQedeqBo().getLabels().setModuleReferences(required)// FIXME why here?
127         if (!getQedeqBo().hasBasicFailures() && sfl.size() == 0) {
128             getQedeqBo().setLoadedRequiredModules();
129             QedeqLog.getInstance().logSuccessfulReply(
130                 "Loading required modules successful", getQedeqBo().getUrl());
131             return Boolean.TRUE;
132         }
133         if (sfl.size() != 0) {
134             getQedeqBo().setDependencyFailureState(
135                 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
136         else {
137             getQedeqBo().setDependencyFailureState(
138                 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getQedeqBo().getErrors());
139         }
140         final String msg = "Loading required modules failed";
141         QedeqLog.getInstance().logFailureReply(msg, getQedeqBo().getUrl(),
142              StringUtility.replace(getQedeqBo().getErrors().getMessage()"\n""\n\t"));
143         return  Boolean.FALSE;
144     }
145 
146     // FIXME
147     public double getExecutionPercentage() {
148         return 1;
149     }
150 
151     public boolean getInterrupted() {
152         return false;
153     }
154 
155     public String getLocationDescription() {
156         return "running";
157     }
158 
159 
160     /**
161      * Prepare exception for error collection.
162      *
163      @param   me  Basis exception.
164      @return  Error.
165      */
166     private SourceFileException createError(final ModuleDataException me) {
167         return getQedeqBo().createSourceFileException(getPlugin(), me);
168     }
169 
170 }