Predicate.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.logic.model;
017 
018 import org.qedeq.base.trace.Trace;
019 import org.qedeq.base.utility.StringUtility;
020 
021 /**
022  * One predicate for our model.
023  *
024  @author  Michael Meyling
025  */
026 public abstract class Predicate {
027 
028     /** This class. */
029     private static final Class CLASS = Predicate.class;
030 
031     /** Minimum number of arguments this predicate has. */
032     private final int minimum;
033 
034     /** Maximum number of arguments this predicate has. */
035     private final int maximum;
036 
037     /** Display text. */
038     private final String display;
039 
040     /** Description for this predicate. */
041     private final String description;
042 
043     /**
044      * Constructor.
045      *
046      @param   minimum         Minimum number of arguments this predicate has.
047      @param   maximum         Maximum number of arguments this predicate has.
048      @param   display         Show this to represent the predicate within outputs.
049      @param   description     Description for this predicate.
050      */
051     public Predicate(final int minimum, final int maximum, final String display,
052             final String description) {
053         this.minimum = minimum;
054         this.maximum = maximum;
055         this.display = display;
056         this.description = description;
057     }
058 
059     /**
060      * Construct negation of other predicate.
061      *
062      @param   predicate   Negate this predicate.
063      @return  Negation of predicate.
064      */
065     public static Predicate not(final Predicate predicate) {
066         return new Predicate(predicate.getMinimumArgumentNumber(),
067             predicate.getMaximumArgumentNumber()"!" + predicate.toString(),
068             "!" + predicate.getDescription()) {
069                 public boolean calculate(final Entity[] entities) {
070                     final String method = "not.calculate(Entity[])";
071                     if (Trace.isDebugEnabled(CLASS)) {
072                         Trace.param(CLASS, method, "toString", toString());
073                         Trace.param(CLASS, method, "entities", StringUtility.toString(entities));
074                     }
075                     final boolean result = !predicate.calculate(entities);
076                     Trace.param(CLASS, method, "result  ", result);
077                     return result;
078                 }
079         };
080     }
081 
082     /**
083      * Construct conjunction of two predicates.
084      *
085      @param   op1     First predicate.
086      @param   op2     Second predicate.
087      @return  Conjunction of two predicates.
088      */
089     public static Predicate and(final Predicate op1, final Predicate op2) {
090         if (op1.getMinimumArgumentNumber() > op2.getMaximumArgumentNumber()
091                 || op1.getMaximumArgumentNumber() < op2.getMinimumArgumentNumber()) {
092             throw new IllegalArgumentException("Predicates can not be combined " + op1 + " and "
093                 + op2);
094         }
095         return new Predicate(Math.max(op1.getMinimumArgumentNumber(),
096                 op2.getMinimumArgumentNumber()), Math.min(op1.getMaximumArgumentNumber(),
097                 op2.getMaximumArgumentNumber()), op1.toString() " and " + op2.toString(),
098                 op1.getDescription() " and " + op2.getDescription()) {
099             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(199"=" + 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 }