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