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 | |
16 | package org.qedeq.kernel.bo.module; |
17 | |
18 | import java.util.HashMap; |
19 | import java.util.Iterator; |
20 | import java.util.Map; |
21 | |
22 | import org.qedeq.kernel.bo.common.ModuleReferenceList; |
23 | import org.qedeq.kernel.se.base.module.ChangedRule; |
24 | import org.qedeq.kernel.se.base.module.FunctionDefinition; |
25 | import org.qedeq.kernel.se.base.module.PredicateDefinition; |
26 | import org.qedeq.kernel.se.base.module.Rule; |
27 | import org.qedeq.kernel.se.common.CheckLevel; |
28 | import org.qedeq.kernel.se.common.IllegalModuleDataException; |
29 | import org.qedeq.kernel.se.common.ModuleContext; |
30 | import org.qedeq.kernel.se.common.RuleKey; |
31 | import org.qedeq.kernel.se.dto.module.NodeVo; |
32 | import org.qedeq.kernel.se.visitor.QedeqNumbers; |
33 | |
34 | /** |
35 | * Maps labels of an QEDEQ module to their nodes. Knows all label names. |
36 | * |
37 | * @author Michael Meyling |
38 | */ |
39 | public final class ModuleLabels { |
40 | |
41 | /** External QEDEQ module references. */ |
42 | private ModuleReferenceList references = new KernelModuleReferenceList(); |
43 | |
44 | /** Maps labels to business objects. */ |
45 | private final Map label2Bo = new HashMap(); |
46 | |
47 | /** Maps labels to context of business objects. */ |
48 | private final Map label2Context = new HashMap(); |
49 | |
50 | /** Maps predicate identifiers to {@link PredicateDefinition}s. */ |
51 | private final Map predicateDefinitions = new HashMap(); |
52 | |
53 | /** Maps predicate identifiers to {@link ModuleContext}s. */ |
54 | private final Map predicateContexts = new HashMap(); |
55 | |
56 | /** Maps function identifiers to {@link FunctionDefinition}s. */ |
57 | private final Map functionDefinitions = new HashMap(); |
58 | |
59 | /** Maps function identifiers to {@link ModuleContext}s. */ |
60 | private final Map functionContexts = new HashMap(); |
61 | |
62 | /** Maps rule names to maximum {@link RuleKey}s. (That is rule key with maximum version number). */ |
63 | private final Map ruleMaximum = new HashMap(); |
64 | |
65 | /** Maps rule keys to {@link Rule}s. */ |
66 | private final Map ruleDefinitions = new HashMap(); |
67 | |
68 | /** Maps rule keys to {@link ModuleContext}s. */ |
69 | private final Map ruleContexts = new HashMap(); |
70 | |
71 | /** Maps rule keys to labels. */ |
72 | private final Map ruleLabels = new HashMap(); |
73 | |
74 | /** |
75 | * Constructs a new empty module label list. |
76 | */ |
77 | public ModuleLabels() { |
78 | // nothing to do |
79 | } |
80 | |
81 | /** |
82 | * Set list of external QEDEQ module references. |
83 | * |
84 | * @param references External QEDEQ module references. |
85 | */ |
86 | public void setModuleReferences(final ModuleReferenceList references) { |
87 | this.references = references; |
88 | } |
89 | |
90 | /** |
91 | * Get list of external QEDEQ module references. |
92 | * |
93 | * @return External QEDEQ module references. |
94 | */ |
95 | public ModuleReferenceList getReferences() { |
96 | return this.references; |
97 | } |
98 | |
99 | /** |
100 | * Add node with certain id. All numbers should start with 1. |
101 | * |
102 | * @param node Add this node. |
103 | * @param context The node has this context. |
104 | * @param qedeq Parent module the node is within. |
105 | * @param data Various number counters. |
106 | * @throws IllegalModuleDataException The <code>id</code> already exists (perhaps as a label) |
107 | * or is <code>null</code>. |
108 | */ |
109 | public final void addNode(final ModuleContext context, final NodeVo node, final KernelQedeqBo qedeq, |
110 | final QedeqNumbers data) throws IllegalModuleDataException { |
111 | // don't forget to use the copy constructor because the context could change! |
112 | final ModuleContext con = new ModuleContext(context); |
113 | if (null == node.getId()) { |
114 | throw new IllegalModuleDataException(10001, "An id was not defined.", con, null, |
115 | null); // LATER mime 20071026: organize exception codes |
116 | } |
117 | checkLabelIntern(con, node.getId()); |
118 | label2Context.put(node.getId(), con); |
119 | final KernelNodeBo nodeBo = new KernelNodeBo(node, context, qedeq, data); |
120 | label2Bo.put(node.getId(), nodeBo); |
121 | } |
122 | |
123 | /** |
124 | * Add unique label for module. |
125 | * |
126 | * @param label Add this label. |
127 | * @param context With this context. |
128 | * @throws IllegalModuleDataException The <code>id</code> already exists or is <code>null</code>. |
129 | */ |
130 | public final void addLabel(final ModuleContext context, final String label) |
131 | throws IllegalModuleDataException { |
132 | // don't forget to use the copy constructor because the context could change! |
133 | final ModuleContext con = new ModuleContext(context); |
134 | checkLabelIntern(con, label); |
135 | label2Context.put(label, con); |
136 | } |
137 | |
138 | /** |
139 | * Check that label doesn't exist. |
140 | * |
141 | * @param label Check this label. |
142 | * @param context With this context (already copied). |
143 | * @throws IllegalModuleDataException The <code>id</code> already exists or is |
144 | * <code>null</code>. |
145 | */ |
146 | private final void checkLabelIntern(final ModuleContext context, final String label) |
147 | throws IllegalModuleDataException { |
148 | if (label2Context.containsKey(label)) { |
149 | throw new IllegalModuleDataException(ModuleErrors.LABEL_DEFINED_MORE_THAN_ONCE_CODE, |
150 | ModuleErrors.LABEL_DEFINED_MORE_THAN_ONCE_TEXT + "\"" + label + "\"", |
151 | context, (ModuleContext) label2Context.get(label), null); |
152 | } |
153 | } |
154 | |
155 | /** |
156 | * Get node for given id. |
157 | * |
158 | * @param id Label to search node for. |
159 | * @return Node for given label. Maybe <code>null</code>. |
160 | */ |
161 | public final KernelNodeBo getNode(final String id) { |
162 | return (KernelNodeBo) label2Bo.get(id); |
163 | } |
164 | |
165 | /** |
166 | * Is the given label id a node? Local node labels are not considered. |
167 | * |
168 | * @param id Label to search node for. |
169 | * @return Is this an node of this module? |
170 | */ |
171 | public final boolean isNode(final String id) { |
172 | return label2Bo.get(id) != null; |
173 | } |
174 | |
175 | /** |
176 | * Is the given label id a module? |
177 | * |
178 | * @param id Label to search module reference for. |
179 | * @return Is this an module reference id? |
180 | */ |
181 | public final boolean isModule(final String id) { |
182 | return label2Bo.get(id) == null && label2Context.get(id) != null; |
183 | } |
184 | |
185 | /** |
186 | * Add predicate definition. If such a definition already exists it is overwritten. |
187 | * |
188 | * @param definition Definition to add. |
189 | * @param context Here the definition stands. |
190 | */ |
191 | public void addPredicate(final PredicateDefinition definition, final ModuleContext context) { |
192 | final String identifier = definition.getName() + "_" + definition.getArgumentNumber(); |
193 | getPredicateDefinitions().put(identifier, definition); |
194 | predicateContexts.put(identifier, new ModuleContext(context)); |
195 | } |
196 | |
197 | /** |
198 | * Get predicate definition. |
199 | * |
200 | * @param name Predicate name. |
201 | * @param argumentNumber Number of predicate arguments. |
202 | * @return Definition. Might be <code>null</code>. |
203 | */ |
204 | public PredicateDefinition getPredicate(final String name, final int argumentNumber) { |
205 | return (PredicateDefinition) getPredicateDefinitions().get(name + "_" + argumentNumber); |
206 | } |
207 | |
208 | /** |
209 | * Get predicate context. This is only a copy. |
210 | * |
211 | * @param name Predicate name. |
212 | * @param argumentNumber Number of predicate arguments. |
213 | * @return Module context. Might be <code>null</code>. |
214 | */ |
215 | public ModuleContext getPredicateContext(final String name, final int argumentNumber) { |
216 | final ModuleContext context = (ModuleContext) predicateContexts.get(name + "_" + argumentNumber); |
217 | if (context != null) { |
218 | return new ModuleContext(context); |
219 | } |
220 | return null; |
221 | } |
222 | |
223 | /** |
224 | * Add function definition. If such a definition already exists it is overwritten. |
225 | * |
226 | * @param definition Definition to add. |
227 | * @param context Here the definition stands. |
228 | */ |
229 | public void addFunction(final FunctionDefinition definition, final ModuleContext context) { |
230 | final String identifier = definition.getName() + "_" + definition.getArgumentNumber(); |
231 | getFunctionDefinitions().put(identifier, definition); |
232 | functionContexts.put(identifier, new ModuleContext(context)); |
233 | } |
234 | |
235 | /** |
236 | * Get function definition. |
237 | * |
238 | * @param name Function name. |
239 | * @param argumentNumber Number of function arguments. |
240 | * @return Definition. Might be <code>null</code>. |
241 | */ |
242 | public FunctionDefinition getFunction(final String name, final int argumentNumber) { |
243 | return (FunctionDefinition) getFunctionDefinitions().get(name + "_" + argumentNumber); |
244 | } |
245 | |
246 | /** |
247 | * Get function context. This is only a copy. |
248 | * |
249 | * @param name Function name. |
250 | * @param argumentNumber Number of function arguments. |
251 | * @return Module context. Might be <code>null</code>. |
252 | */ |
253 | public ModuleContext getFunctionContext(final String name, final int argumentNumber) { |
254 | final ModuleContext context = (ModuleContext) functionContexts.get(name + "_" + argumentNumber); |
255 | if (context != null) { |
256 | return new ModuleContext(context); |
257 | } |
258 | return null; |
259 | } |
260 | |
261 | /** |
262 | * Add rule definition. If such a definition already exists it is overwritten. Also sets the |
263 | * key for the maximum rule version. |
264 | * |
265 | * @param label Node label the rule is defined within. |
266 | * @param definition Definition to add. |
267 | * @param context Here the definition stands. |
268 | */ |
269 | public void addRule(final String label, final Rule definition, final ModuleContext context) { |
270 | final RuleKey key = new RuleKey(definition.getName(), definition.getVersion()); |
271 | ruleLabels.put(key, label); |
272 | final RuleKey oldMaximum = (RuleKey) ruleMaximum.get(definition.getName()); |
273 | if (oldMaximum == null || oldMaximum.getVersion() == null || (key.getVersion() != null |
274 | && 0 < key.getVersion().compareTo(oldMaximum.getVersion()))) { |
275 | ruleMaximum.put(definition.getName(), key); |
276 | } |
277 | getRuleDefinitions().put(key, definition); |
278 | ruleContexts.put(key, new ModuleContext(context)); |
279 | } |
280 | |
281 | /** |
282 | * Add rule definition. If such a definition already exists it is overwritten. Also sets the |
283 | * key for the maximum rule version. |
284 | * |
285 | * @param label Node label the rule is defined within. |
286 | * @param definition Here we have the new rule. |
287 | * @param cr New modification to an old rule. |
288 | * @param context Here the definition stands. |
289 | */ |
290 | public void addChangedRule(final String label, final Rule definition, final ChangedRule cr, |
291 | final ModuleContext context) { |
292 | final RuleKey key = new RuleKey(cr.getName(), cr.getVersion()); |
293 | ruleLabels.put(key, label); |
294 | final RuleKey oldMaximum = (RuleKey) ruleMaximum.get(cr.getName()); |
295 | if (oldMaximum == null || oldMaximum.getVersion() == null || (key.getVersion() != null |
296 | && 0 < key.getVersion().compareTo(oldMaximum.getVersion()))) { |
297 | ruleMaximum.put(cr.getName(), key); |
298 | } |
299 | getRuleDefinitions().put(key, definition); |
300 | ruleContexts.put(key, new ModuleContext(context)); |
301 | } |
302 | |
303 | /** |
304 | * Get rule key with maximum rule version. |
305 | * |
306 | * @param ruleName Get maximum rule key for rule with this name. |
307 | * @return Rule key with maximum rule version. Might be <code>null</code>. |
308 | */ |
309 | public RuleKey getRuleKey(final String ruleName) { |
310 | return (RuleKey) ruleMaximum.get(ruleName); |
311 | } |
312 | |
313 | /** |
314 | * Get rule definition. |
315 | * |
316 | * @param key Rule key. |
317 | * @return Definition. Might be <code>null</code>. |
318 | */ |
319 | public Rule getRule(final RuleKey key) { |
320 | return (Rule) getRuleDefinitions().get(key); |
321 | } |
322 | |
323 | /** |
324 | * Get node id of rule key. |
325 | * |
326 | * @param key Rule key. |
327 | * @return Label. Might be <code>null</code>. |
328 | */ |
329 | public String getRuleLabel(final RuleKey key) { |
330 | return (String) ruleLabels.get(key); |
331 | } |
332 | |
333 | /** |
334 | * Get rule context. This is only a copy. |
335 | * |
336 | * @param key Rule key. |
337 | * @return Module context. Might be <code>null</code>. |
338 | */ |
339 | public ModuleContext getRuleContext(final RuleKey key) { |
340 | final ModuleContext context = (ModuleContext) ruleContexts.get(key); |
341 | if (context != null) { |
342 | return new ModuleContext(context); |
343 | } |
344 | return null; |
345 | } |
346 | |
347 | /** |
348 | * Get mapping of predicate definitions. |
349 | * |
350 | * @return Mapping of predicate definitions. |
351 | */ |
352 | public Map getPredicateDefinitions() { |
353 | return this.predicateDefinitions; |
354 | } |
355 | |
356 | /** |
357 | * Get mapping of function definitions. |
358 | * |
359 | * @return Mapping of function definitions. |
360 | */ |
361 | public Map getFunctionDefinitions() { |
362 | return this.functionDefinitions; |
363 | } |
364 | |
365 | /** |
366 | * Get mapping of rule definitions. |
367 | * |
368 | * @return Mapping of rule definitions. Key is {@link RuleKey}, value is {@link Rule}. |
369 | */ |
370 | public Map getRuleDefinitions() { |
371 | return this.ruleDefinitions; |
372 | } |
373 | |
374 | /** |
375 | * Set the state of all nodes to UNCHECKED for being well formed and proved. |
376 | */ |
377 | public void resetNodesToWellFormedUnchecked() { |
378 | final Iterator i = label2Bo.entrySet().iterator(); |
379 | while (i.hasNext()) { |
380 | Object obj = i.next(); |
381 | if (obj instanceof KernelNodeBo) { |
382 | KernelNodeBo bo = (KernelNodeBo) obj; |
383 | bo.setWellFormed(CheckLevel.UNCHECKED); |
384 | bo.setProved(CheckLevel.UNCHECKED); |
385 | } |
386 | } |
387 | } |
388 | |
389 | /** |
390 | * Set the state of all nodes to UNCHECKED for proved. |
391 | */ |
392 | public void resetNodesToProvedUnchecked() { |
393 | final Iterator i = label2Bo.entrySet().iterator(); |
394 | while (i.hasNext()) { |
395 | Object obj = i.next(); |
396 | if (obj instanceof KernelNodeBo) { |
397 | KernelNodeBo bo = (KernelNodeBo) obj; |
398 | bo.setProved(CheckLevel.UNCHECKED); |
399 | } |
400 | } |
401 | } |
402 | |
403 | } |