EMMA Coverage Report (generated Fri Feb 14 08:28:31 UTC 2014)
[all classes][org.qedeq.kernel.bo.service.dependency]

COVERAGE SUMMARY FOR SOURCE FILE [LoadRequiredModulesExecutor.java]

nameclass, %method, %block, %line, %
LoadRequiredModulesExecutor.java100% (1/1)80%  (8/10)91%  (473/522)89%  (95.9/108)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LoadRequiredModulesExecutor100% (1/1)80%  (8/10)91%  (473/522)89%  (95.9/108)
getLocationDescription (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getVisitPercentage (): double 0%   (0/1)0%   (0/3)0%   (0/1)
executePlugin (InternalModuleServiceCall, Object): Object 100% (1/1)73%  (106/146)71%  (22/31)
<static initializer> 100% (1/1)90%  (9/10)90%  (0.9/1)
circlesInRequiredModules (InternalModuleServiceCall, KernelQedeqBo, SourceFil... 100% (1/1)98%  (127/129)96%  (25/26)
LoadRequiredModulesExecutor (ModuleService, KernelQedeqBo, Parameters): void 100% (1/1)100% (5/5)100% (2/2)
createError (ModuleDataException): SourceFileException 100% (1/1)100% (7/7)100% (1/1)
getInterrupted (): boolean 100% (1/1)100% (2/2)100% (1/1)
loadAllRequiredModules (InternalModuleServiceCall, KernelQedeqBo, boolean): b... 100% (1/1)100% (121/121)100% (21/21)
noCirclesInRequiredModules (InternalModuleServiceCall, KernelQedeqBo, Stack, ... 100% (1/1)100% (96/96)100% (23/23)

1/* This file is part of the project "Hilbert II" - http://www.qedeq.org
2 *
3 * Copyright 2000-2014,  Michael Meyling <mime@qedeq.org>.
4 *
5 * "Hilbert II" is free software; you can redistribute
6 * it and/or modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15 
16package org.qedeq.kernel.bo.service.dependency;
17 
18import java.util.Stack;
19 
20import org.qedeq.base.io.Parameters;
21import org.qedeq.base.trace.Trace;
22import org.qedeq.base.utility.StringUtility;
23import org.qedeq.kernel.bo.common.ModuleReferenceList;
24import org.qedeq.kernel.bo.log.QedeqLog;
25import org.qedeq.kernel.bo.module.InternalModuleServiceCall;
26import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
27import org.qedeq.kernel.bo.module.KernelQedeqBo;
28import org.qedeq.kernel.bo.service.basis.ControlVisitor;
29import org.qedeq.kernel.bo.service.basis.ModuleServicePluginExecutor;
30import org.qedeq.kernel.se.common.ModuleDataException;
31import org.qedeq.kernel.se.common.ModuleService;
32import org.qedeq.kernel.se.common.SourceFileException;
33import org.qedeq.kernel.se.common.SourceFileExceptionList;
34import org.qedeq.kernel.se.state.DependencyState;
35import org.qedeq.kernel.se.visitor.InterruptException;
36 
37 
38/**
39 * Load all required QEDEQ modules.
40 *
41 * @author  Michael Meyling
42 */
43public final class LoadRequiredModulesExecutor extends ControlVisitor implements ModuleServicePluginExecutor {
44 
45    /** This class. */
46    private static final Class CLASS = LoadRequiredModulesExecutor.class;
47 
48    /** Percentage between 0 and 100. */
49    private double percentage;
50 
51    /**
52     * Constructor.
53     *
54     * @param   plugin      Plugin we work for.
55     * @param   prop        Internal QedeqBo.
56     * @param   parameters  Currently ignored.
57     */
58    LoadRequiredModulesExecutor(final ModuleService plugin, final KernelQedeqBo prop,
59            final Parameters parameters) {
60        super(plugin, prop);
61    }
62 
63    public Object executePlugin(final InternalModuleServiceCall call, final Object data) throws InterruptException {
64        percentage = 0;
65        final String method = "executePlugin";
66        if (getKernelQedeqBo().hasLoadedRequiredModules()) {
67            percentage = 100;
68            return Boolean.TRUE; // everything is OK
69        }
70        QedeqLog.getInstance().logRequest(
71            "Loading required modules", getKernelQedeqBo().getUrl());
72        // all QedeqBos currently in state "loading required modules"
73 
74        if (!loadAllRequiredModules(call, getKernelQedeqBo(), true)) {
75            final String msg = "Loading required modules failed";
76            QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
77                "Not all required modules could not even be loaded.");
78            return Boolean.FALSE;
79        }
80        percentage = 100;
81        Trace.trace(CLASS, this, method, "loading required modules of " + getKernelQedeqBo().getUrl());
82        getKernelQedeqBo().setDependencyProgressState(DependencyState.STATE_LOADING_REQUIRED_MODULES);
83 
84 
85        final SourceFileExceptionList sfl = new SourceFileExceptionList();
86        if (circlesInRequiredModules(call, getKernelQedeqBo(), sfl)) {
87            final String msg = "Loading required modules failed";
88            QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
89                "There were circular dependencies.");
90            return Boolean.FALSE;
91        }
92 
93        if (getKernelQedeqBo().getDependencyState().areAllRequiredLoaded()) {
94            return Boolean.TRUE; // everything is OK, someone else's thread might have corrected errors!
95        }
96 
97        getKernelQedeqBo().getLabels().setModuleReferences(getKernelQedeqBo().getRequiredModules()); // FIXME why here?
98        if (!getKernelQedeqBo().hasBasicFailures() && sfl.size() == 0) {
99            getKernelQedeqBo().setLoadedRequiredModules();
100            QedeqLog.getInstance().logSuccessfulReply(
101                "Loading required modules successful", getKernelQedeqBo().getUrl());
102            return Boolean.TRUE;
103        }
104        if (sfl.size() != 0) {
105            getKernelQedeqBo().setDependencyFailureState(
106                DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
107        } else {
108            getKernelQedeqBo().setDependencyFailureState(
109                DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getKernelQedeqBo().getErrors());
110        }
111        final String msg = "Loading required modules failed";
112        QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
113             StringUtility.replace(getKernelQedeqBo().getErrors().getMessage(), "\n", "\n\t"));
114        return  Boolean.FALSE;
115    }
116 
117    private boolean circlesInRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
118            final SourceFileExceptionList sfl) {
119        if (bo.hasLoadedRequiredModules()) {
120            return false;
121        }
122        Stack loadingRequiredInProgress = new Stack();
123        Stack labels = new Stack();
124//        System.out.println("->checking " + bo.getName());
125        loadingRequiredInProgress.push(bo);
126        final KernelModuleReferenceList required = bo.getKernelRequiredModules();
127        final StringBuffer error = new StringBuffer();
128        for (int i = 0; i < required.size(); i++) {
129            final KernelQedeqBo current = required.getKernelQedeqBo(i);
130//            System.out.println("-->testing " + current.getName());
131            labels.push(required.getLabel(i));
132            if (loadingRequiredInProgress.contains(current)) {
133//                for (int j = 0; j < loadingRequiredInProgress.size(); j++) {
134//                    System.out.print("-> " + labels.get(j).toString());
135//                }
136                ModuleDataException me = new LoadRequiredModuleException(
137                    DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
138                    DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + "\""
139                    + required.getLabel(i) + "\"",
140                    required.getModuleContext(i));
141                sfl.add(createError(me));
142//                me.printStackTrace(System.out);
143                labels.pop();
144                continue;
145            }
146 
147//            System.out.println("->removing " + bo.getName());
148//            loadingRequiredInProgress.remove(bo);
149            error.setLength(0);
150            if (!noCirclesInRequiredModules(call, required.getKernelQedeqBo(i), loadingRequiredInProgress, labels,
151                    error)) {
152                // LATER 20110119 m31: we take only the first error, is that ok?
153                String text = DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + error.toString();
154                ModuleDataException me = new LoadRequiredModuleException(
155                    DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
156                    text, required.getModuleContext(i));
157                sfl.add(createError(me));
158            }
159            labels.pop();
160        }
161//        System.out.println("->removing " + bo.getName());
162        loadingRequiredInProgress.pop();
163        if (sfl.size() > 0) {
164            bo.setDependencyFailureState(DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
165            return true;
166        }
167        return false;
168    }
169 
170    private boolean noCirclesInRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
171            final Stack loadingRequiredInProgress, final Stack labels, final StringBuffer error) {
172        if (!bo.hasLoadedImports()) {
173            return false;
174        }
175//        System.out.println("->checking " + bo.getName());
176        loadingRequiredInProgress.push(bo);
177        final KernelModuleReferenceList required = bo.getKernelRequiredModules();
178        boolean result = true;
179        for (int i = 0; i < required.size(); i++) {
180            final KernelQedeqBo current = required.getKernelQedeqBo(i);
181//            System.out.println("-->testing " + current.getName() + " (" + required.getLabel(i) + ")");
182            labels.push(required.getLabel(i));
183            if (loadingRequiredInProgress.contains(current)) {
184                for (int j = 0; j < loadingRequiredInProgress.size(); j++) {
185                    if (j > 0) {
186                        error.append(" -> ");
187                    }
188                    error.append("\"" + labels.get(j).toString() + "\"");
189                }
190                result = false;
191//                System.out.println("## " + error);
192                labels.pop();
193                break;
194            }
195 
196            if (!noCirclesInRequiredModules(call, required.getKernelQedeqBo(i), loadingRequiredInProgress, labels,
197                    error)) {
198                result = false;
199//                System.out.println("## " + error);
200                labels.pop();
201                break;
202            }
203            labels.pop();
204        }
205//        System.out.println("->removing " + bo.getName());
206        loadingRequiredInProgress.pop();
207        return result;
208    }
209 
210    private boolean loadAllRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
211            final boolean first) throws InterruptException {
212        if (bo.hasLoadedImports()) {
213            return true;
214        }
215        getServices().executePlugin(call.getInternalServiceProcess(),
216            LoadDirectlyRequiredModulesPlugin.class.getName(), bo, null);
217        if (!bo.hasLoadedImports()) {
218            return false;
219        }
220        final ModuleReferenceList imports = bo.getRequiredModules();
221        final SourceFileExceptionList sfl = new SourceFileExceptionList();
222        boolean result = true;
223        for (int i = 0; i < imports.size(); i++) {
224            if (!imports.getQedeqBo(i).hasLoadedImports()) {
225                if (!loadAllRequiredModules(call, (KernelQedeqBo) imports.getQedeqBo(i), false)) {
226                    result = false;
227                    if (first) {
228                        // LATER 20110119 m31: we take only the first error, is that ok?
229                        String text = DependencyErrors.IMPORT_OF_MODULE_FAILED_TEXT + "\""
230                            + imports.getLabel(i) + "\"";
231                        if (imports.getQedeqBo(i).getErrors().size() > 0) {
232                            text += ", " + imports.getQedeqBo(i).getErrors().get(0).getMessage();
233                        }
234                        ModuleDataException me = new LoadRequiredModuleException(
235                            DependencyErrors.IMPORT_OF_MODULE_FAILED_CODE,
236                            text, imports.getModuleContext(i));
237                        sfl.add(createError(me));
238                    }
239                }
240            }
241        }
242        if (sfl.size() > 0) {
243            bo.setDependencyFailureState(DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
244        }
245        return result;
246    }
247 
248    public double getVisitPercentage() {
249        return percentage;
250    }
251 
252    public boolean getInterrupted() {
253        return false;
254    }
255 
256    public String getLocationDescription() {
257        return super.getLocationDescription();
258    }
259 
260 
261    /**
262     * Prepare exception for error collection.
263     *
264     * @param   me  Basis exception.
265     * @return  Error.
266     */
267    private SourceFileException createError(final ModuleDataException me) {
268        return getKernelQedeqBo().createSourceFileException(getService(), me);
269    }
270 
271}

[all classes][org.qedeq.kernel.bo.service.dependency]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov