| 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.ArrayList; |
| 19 | import java.util.HashMap; |
| 20 | import java.util.List; |
| 21 | import java.util.Map; |
| 22 | |
| 23 | import org.qedeq.base.trace.Trace; |
| 24 | import org.qedeq.base.utility.EqualsUtility; |
| 25 | import org.qedeq.kernel.bo.common.ModuleReferenceList; |
| 26 | import org.qedeq.kernel.bo.common.QedeqBo; |
| 27 | import org.qedeq.kernel.se.common.IllegalModuleDataException; |
| 28 | import org.qedeq.kernel.se.common.ModuleContext; |
| 29 | |
| 30 | |
| 31 | /** |
| 32 | * Represents a reference list of modules. Every entry has a symbolic name for one referenced QEDEQ |
| 33 | * module. This module label acts as a prefix for all references to that module. The module label |
| 34 | * must be an unique String. |
| 35 | * |
| 36 | * @author Michael Meyling |
| 37 | */ |
| 38 | public class KernelModuleReferenceList implements ModuleReferenceList { |
| 39 | |
| 40 | /** This class. */ |
| 41 | private static final Class CLASS = KernelModuleReferenceList.class; |
| 42 | |
| 43 | /** Contains all labels. */ |
| 44 | private final List labels; |
| 45 | |
| 46 | /** Contains all module props. */ |
| 47 | private final List props; |
| 48 | |
| 49 | /** Contains all module import contexts. */ |
| 50 | private final List contexts; |
| 51 | |
| 52 | /** Maps labels to context. */ |
| 53 | private final Map label2Context; |
| 54 | |
| 55 | /** |
| 56 | * Constructs an empty list of module references. |
| 57 | */ |
| 58 | public KernelModuleReferenceList() { |
| 59 | labels = new ArrayList(); |
| 60 | props = new ArrayList(); |
| 61 | contexts = new ArrayList(); |
| 62 | label2Context = new HashMap(); |
| 63 | } |
| 64 | |
| 65 | /** |
| 66 | * Add module reference to list. |
| 67 | * |
| 68 | * @param context Within this context. |
| 69 | * @param label Referenced module gets this label. Must not be <code>null</code> or empty. |
| 70 | * @param prop Referenced module has this properties. Must not be <code>null</code>. |
| 71 | * @throws IllegalModuleDataException The <code>label</code> is empty or <code>null</code>. |
| 72 | */ |
| 73 | public void add(final ModuleContext context, final String label, final QedeqBo prop) |
| 74 | throws IllegalModuleDataException { |
| 75 | if (label == null || label.length() <= 0) { |
| 76 | throw new IllegalModuleDataException(10003, "An label was not defined.", |
| 77 | new ModuleContext(context), null, |
| 78 | null); // LATER mime 20071026: organize exception codes |
| 79 | } |
| 80 | final ModuleContext con = new ModuleContext(context); |
| 81 | labels.add(label); |
| 82 | label2Context.put(label, con); |
| 83 | contexts.add(con); |
| 84 | Trace.param(CLASS, "add(ModuleContext, String, QedeqBo)", "context", con); |
| 85 | props.add(prop); |
| 86 | } |
| 87 | |
| 88 | /** |
| 89 | * Add module reference to list. |
| 90 | * |
| 91 | * @param context Within this context. |
| 92 | * @param label Referenced module gets this label. Must not be <code>null</code> or empty. |
| 93 | * @param prop Referenced module has this properties. Must not be <code>null</code>. |
| 94 | * @throws IllegalModuleDataException The <code>id</code> already exists or is |
| 95 | * <code>null</code>. Also if <code>label</code> is empty or <code>null</code>. |
| 96 | */ |
| 97 | public void addLabelUnique(final ModuleContext context, final String label, |
| 98 | final QedeqBo prop) throws IllegalModuleDataException { |
| 99 | if (labels.contains(label)) { |
| 100 | // LATER mime 20071026: organize exception codes |
| 101 | throw new IllegalModuleDataException(10004, "Label \"" + label |
| 102 | + "\" defined more than once.", new ModuleContext(context), // use copy constructor! |
| 103 | (ModuleContext) label2Context.get(label), null); |
| 104 | } |
| 105 | add(new ModuleContext(context), label, prop); |
| 106 | } |
| 107 | |
| 108 | public int size() { |
| 109 | return labels.size(); |
| 110 | } |
| 111 | |
| 112 | public String getLabel(final int index) { |
| 113 | return (String) labels.get(index); |
| 114 | } |
| 115 | |
| 116 | public QedeqBo getQedeqBo(final int index) { |
| 117 | return (QedeqBo) props.get(index); |
| 118 | } |
| 119 | |
| 120 | /** |
| 121 | * Get {@link QedeqBo} of referenced module. |
| 122 | * |
| 123 | * @param index Entry index. |
| 124 | * @return Module properties for that module. |
| 125 | */ |
| 126 | public KernelQedeqBo getKernelQedeqBo(final int index) { |
| 127 | return (KernelQedeqBo) props.get(index); |
| 128 | } |
| 129 | |
| 130 | public ModuleContext getModuleContext(final int index) { |
| 131 | return (ModuleContext) contexts.get(index); |
| 132 | } |
| 133 | |
| 134 | public QedeqBo getQedeqBo(final String label) { |
| 135 | final int index = labels.indexOf(label); |
| 136 | if (index < 0) { |
| 137 | return null; |
| 138 | } |
| 139 | return (QedeqBo) props.get(index); |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Get KernelQedeqBo of referenced module via label. Might be <code>null</code>. |
| 144 | * |
| 145 | * @param label Label for referenced module or <code>null</code> if not found. |
| 146 | * @return QEQDEQ BO. |
| 147 | */ |
| 148 | public KernelQedeqBo getKernelQedeqBo(final String label) { |
| 149 | final int index = labels.indexOf(label); |
| 150 | if (index < 0) { |
| 151 | return null; |
| 152 | } |
| 153 | return (KernelQedeqBo) props.get(index); |
| 154 | } |
| 155 | |
| 156 | /** |
| 157 | * Is the given QEDEQ BO already in this list? |
| 158 | * |
| 159 | * @param bo QEDEQ BO. |
| 160 | * @return Already in list? |
| 161 | */ |
| 162 | public boolean contains(final KernelQedeqBo bo) { |
| 163 | return props.contains(bo); |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * Delete a given QEDEQ BO already from list. |
| 168 | * |
| 169 | * @param bo QEDEQ BO. |
| 170 | */ |
| 171 | public void remove(final KernelQedeqBo bo) { |
| 172 | int index; |
| 173 | while (0 <= (index = props.indexOf(bo))) { |
| 174 | final String label = (String) labels.get(index); |
| 175 | label2Context.remove(label); |
| 176 | props.remove(index); |
| 177 | labels.remove(index); |
| 178 | contexts.remove(index); |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | public boolean equals(final Object obj) { |
| 183 | if (!(obj instanceof KernelModuleReferenceList)) { |
| 184 | return false; |
| 185 | } |
| 186 | final ModuleReferenceList otherList = (ModuleReferenceList) obj; |
| 187 | if (size() != otherList.size()) { |
| 188 | return false; |
| 189 | } |
| 190 | for (int i = 0; i < size(); i++) { |
| 191 | if (!EqualsUtility.equals(getLabel(i), otherList.getLabel(i)) |
| 192 | || !EqualsUtility.equals(getQedeqBo(i), |
| 193 | otherList.getQedeqBo(i))) { |
| 194 | return false; |
| 195 | } |
| 196 | } |
| 197 | return true; |
| 198 | } |
| 199 | |
| 200 | /** |
| 201 | * Empty reference list. |
| 202 | */ |
| 203 | public void clear() { |
| 204 | labels.clear(); |
| 205 | props.clear(); |
| 206 | contexts.clear(); |
| 207 | label2Context.clear(); |
| 208 | } |
| 209 | |
| 210 | /** |
| 211 | * Copy all list entry references of <code>list</code> to this instance. |
| 212 | * |
| 213 | * @param list Copy from here. |
| 214 | */ |
| 215 | public void set(final KernelModuleReferenceList list) { |
| 216 | clear(); |
| 217 | this.labels.addAll(list.labels); |
| 218 | this.props.addAll(list.props); |
| 219 | this.contexts.addAll(list.contexts); |
| 220 | this.label2Context.putAll(list.label2Context); |
| 221 | } |
| 222 | |
| 223 | public int hashCode() { |
| 224 | int hash = 0; |
| 225 | for (int i = 0; i < size(); i++) { |
| 226 | hash = hash ^ (i + 1); |
| 227 | if (getLabel(i) != null) { |
| 228 | hash = hash ^ getLabel(i).hashCode(); |
| 229 | hash = hash ^ getQedeqBo(i).hashCode(); |
| 230 | } |
| 231 | } |
| 232 | return hash; |
| 233 | } |
| 234 | |
| 235 | public String toString() { |
| 236 | final StringBuffer buffer = new StringBuffer("module reference list:\n"); |
| 237 | for (int i = 0; i < size(); i++) { |
| 238 | if (i != 0) { |
| 239 | buffer.append("\n"); |
| 240 | } |
| 241 | buffer.append((i + 1) + ":\t"); |
| 242 | buffer.append(getLabel(i)).append(": ").append(getQedeqBo(i)).append("\n"); |
| 243 | } |
| 244 | return buffer.toString(); |
| 245 | } |
| 246 | |
| 247 | } |