KernelQedeqBoStorage.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.HashMap;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Map;
023 
024 import org.qedeq.base.trace.Trace;
025 import org.qedeq.kernel.bo.common.QedeqBo;
026 import org.qedeq.kernel.bo.module.InternalKernelServices;
027 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
028 import org.qedeq.kernel.bo.module.KernelQedeqBo;
029 import org.qedeq.kernel.se.common.ModuleAddress;
030 import org.qedeq.kernel.se.state.LoadingState;
031 
032 /**
033  * Holds all known QEDEQ modules.
034  */
035 class KernelQedeqBoStorage {
036 
037     /** This class. */
038     private static final Class CLASS = KernelQedeqBoStorage.class;
039 
040     /** QEDEQ Modules; key: ModuleAddress, value: KernelQedeqBo. */
041     private final Map bos = new HashMap();
042 
043 
044     /**
045      * Get {@link QedeqBo} for an module address. If it is unknown it will be created.
046      *
047      @param   services    Internal kernel services.
048      @param   address     Module address.
049      @return  QedeqBo for module.
050      */
051     synchronized DefaultKernelQedeqBo getKernelQedeqBo(final InternalKernelServices services,
052             final ModuleAddress address) {
053         if (bos.containsKey(address)) {
054             return (DefaultKernelQedeqBobos.get(address);
055         }
056         final DefaultKernelQedeqBo prop = new DefaultKernelQedeqBo(services, address);
057         bos.put(address, prop);
058         return prop;
059     }
060 
061     /**
062      * Remove all modules from memory.
063      */
064     synchronized void removeAllModules() {
065         final String method = "removeAllModules()";
066         Trace.begin(CLASS, this, method);
067         try {
068             for (final Iterator iterator
069                     = bos.entrySet().iterator();
070                     iterator.hasNext()) {
071                 Map.Entry entry = (Map.Entryiterator.next();
072                 final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBoentry.getValue();
073                 prop.delete();
074             }
075             bos.clear();
076         catch (RuntimeException e) {
077             Trace.trace(CLASS, this, method, e);
078         finally {
079             Trace.end(CLASS, this, method);
080         }
081     }
082 
083     /**
084      * Validate module dependencies and throw Error if they are not correct.
085      */
086     synchronized void validateDependencies() {
087         final String method = "validateDependencies";
088         boolean error = false;
089         Trace.begin(CLASS, this, method);
090         for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext()) {
091             Map.Entry entry = (Map.Entryiterator.next();
092             final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBoentry.getValue();
093             Trace.param(CLASS, this, method, "prop", prop);
094             if (!prop.hasLoadedRequiredModules()) {
095                 continue;
096             }
097 
098             // prop must be in dependent list for all required modules
099             final KernelModuleReferenceList refs = prop.getKernelRequiredModules();
100             for (int i = 0; i < refs.size(); i++) {
101                 final DefaultKernelQedeqBo ref = (DefaultKernelQedeqBorefs.getKernelQedeqBo(i);
102                 final KernelModuleReferenceList dependents = ref.getDependentModules();
103                 if (!dependents.contains(prop)) {
104                     Trace.fatal(CLASS, this, method, ref.getUrl() " missing dependent module: "
105                         + prop.getUrl()null);
106                     error = true;
107                 }
108             }
109 
110             // for all dependent modules, prop must be in required list
111             final KernelModuleReferenceList dependents = prop.getDependentModules();
112             for (int i = 0; i < dependents.size(); i++) {
113                 final DefaultKernelQedeqBo dependent
114                     (DefaultKernelQedeqBodependents.getKernelQedeqBo(i);
115                 final KernelModuleReferenceList refs2 = dependent.getDependentModules();
116                 if (!refs2.contains(prop)) {
117                     Trace.fatal(CLASS, this, method, dependent.getUrl()
118                         " missing required module: " + prop.getUrl()null);
119                     error = true;
120                 }
121             }
122         }
123         Trace.end(CLASS, this, method);
124 
125         // if the dependencies are not ok we throw an error!
126         if (error) {
127             Error e = new Error("QEDEQ dependencies and status are flawed! This is a major error!");
128             Trace.fatal(CLASS, this, method, "Shutdown because of major validation error", e);
129             throw e;
130         }
131     }
132 
133     /**
134      * Remove a QEDEQ module from memory.
135      *
136      @param   prop    Defines the module.
137      */
138     synchronized void removeModule(final KernelQedeqBo prop) {
139         final String method = "removeModule(KernelQedeqBo)";
140         Trace.begin(CLASS, this, method);
141         try {
142             Trace.trace(CLASS, this, method, "removing " +  prop.getUrl());
143             bos.remove(prop.getModuleAddress());
144         catch (RuntimeException e) {
145             Trace.fatal(CLASS, this, method, "unexpected runtime exception", e);
146             throw e;
147         finally {
148             Trace.end(CLASS, this, method);
149         }
150     }
151 
152     /**
153      * Get list of all successfully loaded modules.
154      *
155      @return  list of all successfully loaded modules.
156      */
157     synchronized ModuleAddress[] getAllLoadedModules() {
158         final String method = "getAllModules()";
159         Trace.begin(CLASS, this, method);
160         try {
161             final List list = new ArrayList();
162             for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext()) {
163                 Map.Entry entry = (Map.Entryiterator.next();
164                 final QedeqBo prop = (QedeqBoentry.getValue();
165                 if (prop.getLoadingState().getCode() >= LoadingState.STATE_LOADED.getCode()) {
166                     list.add(prop.getModuleAddress());
167                 }
168             }
169             return (ModuleAddress[]) list.toArray(new ModuleAddress[list.size()]);
170         finally {
171             Trace.end(CLASS, this, method);
172         }
173     }
174 
175     /**
176      * Get number of QEDEQ modules in STATE_LOADED.
177      *
178      @return  Number of loaded modules.
179      */
180     synchronized int getNumberOfLoadedModules() {
181         return getAllLoadedModules().length;
182     }
183 
184 }