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.logic.model; |
17 | |
18 | import org.qedeq.base.trace.Trace; |
19 | import org.qedeq.base.utility.StringUtility; |
20 | |
21 | /** |
22 | * One predicate for our model. |
23 | * |
24 | * @author Michael Meyling |
25 | */ |
26 | public abstract class Predicate { |
27 | |
28 | /** This class. */ |
29 | private static final Class CLASS = Predicate.class; |
30 | |
31 | /** Minimum number of arguments this predicate has. */ |
32 | private final int minimum; |
33 | |
34 | /** Maximum number of arguments this predicate has. */ |
35 | private final int maximum; |
36 | |
37 | /** Display text. */ |
38 | private final String display; |
39 | |
40 | /** Description for this predicate. */ |
41 | private final String description; |
42 | |
43 | /** |
44 | * Constructor. |
45 | * |
46 | * @param minimum Minimum number of arguments this predicate has. |
47 | * @param maximum Maximum number of arguments this predicate has. |
48 | * @param display Show this to represent the predicate within outputs. |
49 | * @param description Description for this predicate. |
50 | */ |
51 | public Predicate(final int minimum, final int maximum, final String display, |
52 | final String description) { |
53 | this.minimum = minimum; |
54 | this.maximum = maximum; |
55 | this.display = display; |
56 | this.description = description; |
57 | } |
58 | |
59 | /** |
60 | * Construct negation of other predicate. |
61 | * |
62 | * @param predicate Negate this predicate. |
63 | * @return Negation of predicate. |
64 | */ |
65 | public static Predicate not(final Predicate predicate) { |
66 | return new Predicate(predicate.getMinimumArgumentNumber(), |
67 | predicate.getMaximumArgumentNumber(), "!" + predicate.toString(), |
68 | "!" + predicate.getDescription()) { |
69 | public boolean calculate(final Entity[] entities) { |
70 | final String method = "not.calculate(Entity[])"; |
71 | if (Trace.isDebugEnabled(CLASS)) { |
72 | Trace.param(CLASS, method, "toString", toString()); |
73 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
74 | } |
75 | final boolean result = !predicate.calculate(entities); |
76 | Trace.param(CLASS, method, "result ", result); |
77 | return result; |
78 | } |
79 | }; |
80 | } |
81 | |
82 | /** |
83 | * Construct conjunction of two predicates. |
84 | * |
85 | * @param op1 First predicate. |
86 | * @param op2 Second predicate. |
87 | * @return Conjunction of two predicates. |
88 | */ |
89 | public static Predicate and(final Predicate op1, final Predicate op2) { |
90 | if (op1.getMinimumArgumentNumber() > op2.getMaximumArgumentNumber() |
91 | || op1.getMaximumArgumentNumber() < op2.getMinimumArgumentNumber()) { |
92 | throw new IllegalArgumentException("Predicates can not be combined " + op1 + " and " |
93 | + op2); |
94 | } |
95 | return new Predicate(Math.max(op1.getMinimumArgumentNumber(), |
96 | op2.getMinimumArgumentNumber()), Math.min(op1.getMaximumArgumentNumber(), |
97 | op2.getMaximumArgumentNumber()), op1.toString() + " and " + op2.toString(), |
98 | op1.getDescription() + " and " + op2.getDescription()) { |
99 | public boolean calculate(final Entity[] entities) { |
100 | final String method = "and.calculate(Entity[])"; |
101 | if (Trace.isDebugEnabled(CLASS)) { |
102 | Trace.param(CLASS, method, "toString", toString()); |
103 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
104 | } |
105 | boolean result = op1.calculate(entities) && op2.calculate(entities); |
106 | Trace.param(CLASS, method, "result ", result); |
107 | return result; |
108 | } |
109 | }; |
110 | } |
111 | |
112 | /** |
113 | * Construct disjunction of two predicates. |
114 | * |
115 | * @param op1 First predicate. |
116 | * @param op2 Second predicate. |
117 | * @return Disjunction of two predicates. |
118 | */ |
119 | public static Predicate or(final Predicate op1, final Predicate op2) { |
120 | if (op1.getMinimumArgumentNumber() > op2.getMaximumArgumentNumber() |
121 | || op1.getMaximumArgumentNumber() < op2.getMinimumArgumentNumber()) { |
122 | throw new IllegalArgumentException("Predicates can not be combined " + op1 + " and " |
123 | + op2); |
124 | } |
125 | return new Predicate(Math.max(op1.getMinimumArgumentNumber(), |
126 | op2.getMinimumArgumentNumber()), Math.min(op1.getMaximumArgumentNumber(), |
127 | op2.getMaximumArgumentNumber()), op1.toString() + " or " + op2.toString(), |
128 | op1.getDescription() + " or " + op2.getDescription()) { |
129 | public boolean calculate(final Entity[] entities) { |
130 | final String method = "or.calculate(Entity[])"; |
131 | if (Trace.isDebugEnabled(CLASS)) { |
132 | Trace.param(CLASS, method, "toString", toString()); |
133 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
134 | } |
135 | if (Trace.isDebugEnabled(CLASS)) { |
136 | Trace.param(CLASS, method, "toString", toString()); |
137 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
138 | } |
139 | boolean result = op1.calculate(entities) || op2.calculate(entities); |
140 | Trace.param(CLASS, method, "result ", result); |
141 | return result; |
142 | } |
143 | }; |
144 | } |
145 | |
146 | /** |
147 | * Construct identifying predicate. |
148 | * |
149 | * @param entity Check if all entities are equal to this. |
150 | * @return Predicate to check for this entity. |
151 | */ |
152 | public static Predicate isEntity(final Entity entity) { |
153 | return new Predicate(1, 99, "=" + entity, "= " + entity.getDescription()) { |
154 | public boolean calculate(final Entity[] entities) { |
155 | final String method = "isEntity.calculate(Entity[])"; |
156 | if (Trace.isDebugEnabled(CLASS)) { |
157 | Trace.param(CLASS, method, "toString", toString()); |
158 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
159 | } |
160 | if (Trace.isDebugEnabled(CLASS)) { |
161 | Trace.param(CLASS, method, "toString", toString()); |
162 | Trace.param(CLASS, method, "entities", StringUtility.toString(entities)); |
163 | } |
164 | boolean result = true; |
165 | for (int i = 0; i < entities.length; i++) { |
166 | result &= entity.getValue() == entities[i].getValue(); |
167 | } |
168 | Trace.param(CLASS, method, "result ", result); |
169 | return result; |
170 | } |
171 | }; |
172 | } |
173 | |
174 | /** |
175 | * Get minimum number of arguments this predicate has. |
176 | * |
177 | * @return Minimum number of arguments for this predicate. |
178 | */ |
179 | public int getMinimumArgumentNumber() { |
180 | return minimum; |
181 | } |
182 | |
183 | /** |
184 | * Get maximum number of arguments this predicate has. |
185 | * |
186 | * @return Maximum umber of arguments for this predicate. |
187 | */ |
188 | public int getMaximumArgumentNumber() { |
189 | return maximum; |
190 | } |
191 | |
192 | /** |
193 | * Get display text. |
194 | * |
195 | * @return Representation of this predicate for textual output. |
196 | */ |
197 | public String toString() { |
198 | return display; |
199 | } |
200 | |
201 | /** |
202 | * Get description. |
203 | * |
204 | * @return Description of this predicate. |
205 | */ |
206 | public String getDescription() { |
207 | return description; |
208 | } |
209 | |
210 | /** |
211 | * Calculate truth value. |
212 | * |
213 | * @param entities Calculate predicate for this entities. |
214 | * @return Truth value. |
215 | */ |
216 | public abstract boolean calculate(Entity[] entities); |
217 | |
218 | } |