...
 
Commits (18)
//--------------------------------------------------------------------
// Allgemeine Vorgaben für das Multiprojekt
//--------------------------------------------------------------------
apply plugin: 'java'
buildscript {
......@@ -21,11 +20,8 @@ buildscript {
}
subprojects {
version '2.20.0-SNAPSHOT'
version '2.20.0-SNAPSHOT'
ext {
kernsoftware_version = '[3,4)'
}
}
include':subprojects:de.bsvrz.sys.funclib.bitctrl'
include':subprojects:de.bsvrz.sys.funclib.bitctrl.modell'
include':subprojects:de.bsvrz.sys.funclib.bitctrl.modell.datenkatalog'
include':subprojects:de.bsvrz.sys.funclib.bitctrl.modell.util'
include ':subprojects:de.bsvrz.sys.funclib.bitctrl'
include ':subprojects:de.bsvrz.sys.funclib.bitctrl.modell'
include ':subprojects:de.bsvrz.sys.funclib.bitctrl.modell.datenkatalog'
include ':subprojects:de.bsvrz.sys.funclib.bitctrl.modell.util'
......@@ -3,6 +3,7 @@ Versionsverlauf
## [Noch nicht veröffentlicht]
- Teilweise auf java 8 aktualisiert.
- Beim Einsatz der SWE in Version 2+ müssen folgende potentiell eingesetzte
SWE auch aktualisiert werden:
- de.bsvrz.sys.funclib.bitctrl.dua
......
......@@ -3,7 +3,7 @@
//--------------------------------------------------------------------
/*
plugins {
id "de.bsvrz.gradle.nerzswe" version "0.12.0"
id "de.bsvrz.gradle.nerzswe" version "0.13.0"
id "biz.aQute.bnd.builder" version "4.0.0"
}
*/
......@@ -28,7 +28,7 @@ nerzswe {
//--------------------------------------------------------------------
// Abhängigkeiten
//--------------------------------------------------------------------
String kernsoftware_version = '3.9.7'
dependencies {
//------
// Source:
......@@ -44,4 +44,4 @@ dependencies {
//------
// Test:
testCompile group: 'junit', name: 'junit', version: '4.12'
}
\ No newline at end of file
}
......@@ -34,6 +34,8 @@ import java.io.Serializable;
public abstract class AbstractDavZustand implements Serializable,
Comparable<AbstractDavZustand> {
private static final long serialVersionUID = 8943361554364963349L;
/**
*
*/
......
/*
* BitCtrl-Funktionsbibliothek
* Copyright (C) 2015 BitCtrl Systems GmbH
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact Information:
* BitCtrl Systems GmbH
* Weißenfelser Straße 67
* 04229 Leipzig
* Phone: +49 341-490670
* mailto: info@bitctrl.de
*/
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import java.util.Arrays;
import java.util.List;
/**
* Abstrakte Implementierung eines Handlers zur Ausf&uuml;hrung von Operationen.
* Die Klasse implementiert einige Funktionen der Schnittstelle Handler um die
* Implementierung konkreter Handler-Klassen zu erleichtern.
*
* @author BitCtrl Systems GmbH, Peuker, Schumann
*/
public abstract class AbstractHandler implements Handler {
/**
* Liefert den n-ten Operanden aus einer Liste von Operanden.<br>
* Wenn die Liste weniger Operanden enth&auml;lt, wird {@code null}
* geliefert.
*
* @param operanden
* Die Liste der Operanden
* @param index
* Der Index des gesuchten Operanden
* @return Den Operand oder {@code null}
*/
public static Object getOperand(final List<? extends Object> operanden,
final int index) {
Object ergebnis = null;
if ((operanden != null) && (operanden.size() > index)) {
ergebnis = operanden.get(index);
}
return ergebnis;
}
@Override
public Object perform(final Operator operator, final Object... operanden) {
return perform(operator, Arrays.asList(operanden));
}
@Override
public HandlerValidation validiereHandler(final Operator operator,
final Object... operanden) {
return validiereHandler(operator, Arrays.asList(operanden));
}
}
......@@ -26,71 +26,45 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* Basisklasse aller Symbole des Interpeters.
*
* @author BitCtrl Systems GmbH, Uwe Peuker, Schumann
*/
public interface Ausdruck {
public interface Ausdruck<T> {
/**
* Behelfsklasse, um ein paar n&uuml;tzliche statische Methoden im Interface
* unterzubringen.
* Bestimmt Rekursiv die Menge der Termsymbole im Ausdruck, die
* Variablen darstellen.
*
* @author BitCtrl Systems GmbH, Schumann
* @param ausdruck
* Ein beliebiger Ausdruck
* @return Menge der Variablennamen
*/
final class Info {
/**
* Bestimmt Rekursiv die Menge der Termsymbole im Ausdruck, die
* Variablen darstellen.
*
* @param ausdruck
* Ein beliebiger Ausdruck
* @return Menge der Variablennamen
*/
public static Set<String> getVariablen(final Ausdruck ausdruck) {
Set<String> variablen;
variablen = new HashSet<>();
if (ausdruck instanceof Variable) {
// Wir sind an einem Termsymbol angekommen, was Variable ist
variablen.add(((Variable) ausdruck).getName());
} else if (ausdruck.getNachfolger() != null) {
// Ausdruck ist kein Terminalsymbol
for (final Ausdruck a : ausdruck.getNachfolger()) {
// Rekursion
variablen.addAll(getVariablen(a));
}
static Set<String> getVariablen(final Ausdruck<?> ausdruck) {
Set<String> variablen = new HashSet<>();
if (ausdruck instanceof Variable) {
variablen.add(((Variable) ausdruck).getName());
} else {
for (final Ausdruck<?> a : ausdruck.getNachfolger()) {
variablen.addAll(getVariablen(a));
}
return variablen;
}
/**
* Konstruktor.
*/
private Info() {
// privater Standardkonstruktor, wird nie verwendet
}
return variablen;
}
/**
* Gibt eine Liste der verschachtelten Ausdr&uuml;cke zur&uuml;ck.
* <p>
* <em>Hinweis:</em> Terminalsymbole liefern keine leere Liste sondern
* {@code null} zur&uuml;ck. Eine leere Liste ist demnach ein Hinweis auf
* einen unvollst&auml;ndigen Syntaxbaum.
*
* @return Liste der Ausdr&uuml;cke <em>direkt</em> unter diesen Ausdruck.
* Die Methode arbeiten im Gegensatz zu {@link #interpret(Kontext)}
* nicht rekursiv.
*/
List<Ausdruck> getNachfolger();
default List<? extends Ausdruck<?>> getNachfolger() {
return Collections.emptyList();
}
/**
* Interpretiert den Ausdruck im gegebenen Kontext.
......@@ -99,6 +73,6 @@ public interface Ausdruck {
* Kontext, indem der Ausdruck ausgewertet wird
* @return Wert des interpretierten Ausdrucks
*/
Object interpret(Kontext kontext);
T interpret(Kontext kontext);
}
......@@ -26,18 +26,38 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import java.util.List;
import java.util.*;
/**
* Schnittstelle f&uuml;r alle Klassen die Operationen des Interpreters
* implementieren. Statt jeder Operation eine eigene Klasse zu geben, werden mit
* Hilfe des Musters <em>Besucher</em> alle Operationen in einer Klasse
* geb&uuml;ndelt. Neue Operationen k&ouml;nnen durch implementieren dieser
* Schnittstelle definiert werden. Siehe auch {@link AbstractHandler}
* Schnittstelle definiert werden. Siehe auch {@link Handler}
*
* @author BitCtrl Systems GmbH, Schumann
*/
public interface Handler {
public abstract class Handler {
/**
* Liefert den n-ten Operanden aus einer Liste von Operanden.<br>
* Wenn die Liste weniger Operanden enth&auml;lt, wird {@code null}
* geliefert.
*
* @param operanden
* Die Liste der Operanden
* @param index
* Der Index des gesuchten Operanden
* @return Den Operand oder {@code null}
*/
public static Object getOperand(List<?> operanden, int index) {
Object ergebnis = null;
if ((operanden != null) && (operanden.size() > index)) {
ergebnis = operanden.get(index);
}
return ergebnis;
}
/**
* Gibt die Liste der Operatoren zur&uuml;ck, die der Handler verarbeiten
......@@ -45,7 +65,7 @@ public interface Handler {
*
* @return Liste von Operatoren
*/
Operator[] getHandledOperators();
public abstract Operator[] getHandledOperators();
/**
* F&uuml;hrt eine Operation mit der Liste der Operanden aus. Die Liste der
......@@ -57,7 +77,7 @@ public interface Handler {
* Liste der Operanden
* @return Wert der Operation, abh&auml;ngig von Operator und Operanden
*/
Object perform(Operator operator, List<Object> operanden);
public abstract Object perform(Operator operator, List<?> operanden);
/**
* F&uuml;hrt eine Operation mit dem Operanden aus.
......@@ -68,7 +88,9 @@ public interface Handler {
* Operandenliste
* @return Wert der Operation, abh&auml;ngig von Operator und Operand
*/
Object perform(Operator operator, Object... operanden);
public Object perform(Operator operator, Object... operanden) {
return perform(operator, Arrays.asList(operanden));
}
/**
* Pr&uuml;ft ob der Handler die angegebene Operation auf Liste der
......@@ -80,8 +102,7 @@ public interface Handler {
* Liste von Operanden
* @return das Ergebnis der &Uuml;berpr&uuml;fung
*/
HandlerValidation validiereHandler(Operator operator,
List<? extends Object> operanden);
protected abstract HandlerValidation validiereHandler(Operator operator, List<?> operanden);
/**
* Pr&uuml;ft ob der Handler die angegebene Operation auf dem Operanden
......@@ -93,6 +114,8 @@ public interface Handler {
* Operandenliste
* @return das Ergebnis der &Uuml;berpr&uuml;fung
*/
HandlerValidation validiereHandler(Operator operator, Object... operanden);
protected HandlerValidation validiereHandler(Operator operator, Object... operanden) {
return validiereHandler(operator, Arrays.asList(operanden));
}
}
......@@ -26,8 +26,7 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import java.util.HashMap;
import java.util.Set;
import java.util.*;
import com.bitctrl.i18n.Messages;
......@@ -128,20 +127,20 @@ public class Kontext {
/**
* Liefert den Wert einer Variable und pr&uuml;ft gleichzeitig deren Typ.
*
* @param <T> Der Typ der Variable im Kontext.
* @param name
* Name der Variablen
* der Name der Variablen.
* @param typ
* Typ bzw. Klasse, den die Variable haben soll
* @return Wert der Variable
* der Typ, den die Variable haben soll.
* @return den Wert der Variable.
* @throws InterpreterException
* Wenn der Variablenname oder der Typ {@code null} ist, der
* Variablenname nur aus Whitespaces betsteht oder der Typ der
* Variable nicht korrekt ist
* Variable nicht korrekt ist.
*/
public Object get(final String name, final Class<?>... typ) {
public <T> T get(final String name, final Class<? extends T>... typ) {
if (typ == null) {
throw new InterpreterException(
Messages.get(InterpreterMessages.BadTypNull));
throw new InterpreterException(Messages.get(InterpreterMessages.BadTypNull));
}
final Object wert = get(name);
......@@ -153,11 +152,10 @@ public class Kontext {
}
}
if (!ok) {
throw new SymbolUndefiniertException(Messages.get(
InterpreterMessages.NoVariableWithNameAndTyp, name, typ));
throw new SymbolUndefiniertException(Messages.get(InterpreterMessages.NoVariableWithNameAndTyp, name, Arrays.asList(typ)));
}
return wert;
return (T) wert;
}
/**
......
......@@ -33,13 +33,8 @@ package de.bsvrz.sys.funclib.bitctrl.interpreter;
*
* @author BitCtrl Systems GmbH, Uwe Peuker
*/
public interface Literal extends Ausdruck {
public interface Literal<T> extends Ausdruck<T> {
/**
* Gibt den Wert des Literals zur&uuml;ck.
*
* @return Der Wert
*/
Object getWert();
// tagging interface
}
......@@ -26,10 +26,7 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.*;
/**
* Ein Nicht-Terminal-Symbol des Interpreters, sprich ein Operatorsymbol bzw
......@@ -37,7 +34,7 @@ import java.util.List;
*
* @author BitCtrl Systems GmbH, Schumann
*/
public class OperationsSymbol implements Ausdruck {
public class Operation<T, O> implements Ausdruck<T> {
/**
* Der Operator dieser Operation.
......@@ -47,7 +44,7 @@ public class OperationsSymbol implements Ausdruck {
/**
* Die Liste der Operanden.
*/
private final List<Ausdruck> operanden;
private final List<Ausdruck<O>> operanden;
/**
* Konstruiert ein Symbol mit den gegebenen Operator und Operanden.
......@@ -59,17 +56,9 @@ public class OperationsSymbol implements Ausdruck {
* @throws NullPointerException
* Wenn ein Funktionsparameter {@code null} ist
*/
public OperationsSymbol(final Operator operator,
final Ausdruck... operanden) {
if (operator == null || operanden == null) {
throw new NullPointerException();
}
this.operator = operator;
this.operanden = new ArrayList<>();
if (operanden.length > 0) {
this.operanden.addAll(Arrays.asList(operanden));
}
public Operation(final Operator operator,
final Ausdruck<O>... operanden) {
this(operator, Arrays.asList(operanden));
}
/**
......@@ -82,9 +71,10 @@ public class OperationsSymbol implements Ausdruck {
* @throws NullPointerException
* Wenn ein Funktionsparameter {@code null} ist
*/
public OperationsSymbol(final Operator operator,
final List<? extends Ausdruck> operanden) {
this(operator, operanden.toArray(new Ausdruck[0]));
public Operation(final Operator operator,
final List<? extends Ausdruck<O>> operanden) {
this.operator = Objects.requireNonNull(operator, "operator");
this.operanden = new ArrayList<>(Objects.requireNonNull(operanden, "operanden"));
}
/**
......@@ -97,8 +87,8 @@ public class OperationsSymbol implements Ausdruck {
* @throws NullPointerException
* Wenn ein Funktionsparameter {@code null} ist
*/
public OperationsSymbol(final String operatorSymbol,
final Ausdruck... operanden) {
public Operation(final String operatorSymbol,
final Ausdruck<O>... operanden) {
this(Operator.getOperator(operatorSymbol), operanden);
}
......@@ -112,14 +102,14 @@ public class OperationsSymbol implements Ausdruck {
* @throws NullPointerException
* Wenn ein Funktionsparameter {@code null} ist
*/
public OperationsSymbol(final String operatorSymbol,
final List<? extends Ausdruck> operanden) {
this(operatorSymbol, operanden.toArray(new Ausdruck[0]));
public Operation(final String operatorSymbol,
final List<? extends Ausdruck<O>> operanden) {
this(Operator.getOperator(operatorSymbol), operanden);
}
@Override
public List<Ausdruck> getNachfolger() {
return new ArrayList<>(operanden);
public List<? extends Ausdruck<O>> getNachfolger() {
return Collections.unmodifiableList(operanden);
}
/**
......@@ -127,7 +117,7 @@ public class OperationsSymbol implements Ausdruck {
*
* @return Die Liste der Operanden
*/
public List<? extends Ausdruck> getOperanden() {
public List<? extends Ausdruck<O>> getOperanden() {
return operanden;
}
......@@ -143,11 +133,11 @@ public class OperationsSymbol implements Ausdruck {
}
@Override
public Object interpret(final Kontext kontext) {
public T interpret(final Kontext kontext) {
assert operator != null;
final List<Object> values = new ArrayList<>();
for (final Ausdruck a : operanden) {
final List<O> values = new ArrayList<>();
for (final Ausdruck<O> a : operanden) {
if (a != null) {
values.add(a.interpret(kontext));
} else {
......@@ -155,7 +145,7 @@ public class OperationsSymbol implements Ausdruck {
}
}
return operator.execute(values);
return (T) operator.execute(values);
}
@Override
......@@ -169,7 +159,7 @@ public class OperationsSymbol implements Ausdruck {
result += operator + " " + operanden.get(0);
} else {
// Es gibt mehr als einen Operanden
final Iterator<Ausdruck> i = operanden.iterator();
final Iterator<Ausdruck<O>> i = operanden.iterator();
Ausdruck a = i.next();
result += a.toString(); // erster Operand
......
......@@ -179,7 +179,7 @@ public final class Operator {
* Menge von Operanden
* @return Ergebnis der Operation
*/
public Object execute(final List<Object> werte) {
public Object execute(final List<?> werte) {
if (handler.size() == 0) {
throw new InterpreterException(Messages.get(
InterpreterMessages.HandlerNotFound, getSymbol()));
......@@ -216,7 +216,7 @@ public final class Operator {
* Die Operanden
* @return Den Text
*/
private String getAufrufString(final List<Object> werte) {
private String getAufrufString(final List<?> werte) {
final StringBuffer meldung = new StringBuffer("(");
for (final Object wert : werte) {
if (meldung.length() > 1) {
......
......@@ -33,7 +33,9 @@ package de.bsvrz.sys.funclib.bitctrl.interpreter;
*
* @author BitCtrl Systems GmbH, Uwe Peuker
*/
public interface Variable extends Ausdruck {
public interface Variable<T> extends Ausdruck<T> {
// TODO Variable könnte eine Klasse sein, die aus dem Kontext ein Literal mit Typ liest.
/**
* liefert den Name der Variable, die der Ausdruck definiert.
......@@ -41,4 +43,5 @@ public interface Variable extends Ausdruck {
* @return den Name
*/
String getName();
}
......@@ -26,11 +26,11 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter.logik;
import java.util.List;
import java.util.*;
import com.bitctrl.i18n.Messages;
import de.bsvrz.sys.funclib.bitctrl.interpreter.AbstractHandler;
import de.bsvrz.sys.funclib.bitctrl.interpreter.Handler;
import de.bsvrz.sys.funclib.bitctrl.interpreter.HandlerValidation;
import de.bsvrz.sys.funclib.bitctrl.interpreter.InterpreterException;
import de.bsvrz.sys.funclib.bitctrl.interpreter.InterpreterMessages;
......@@ -42,15 +42,15 @@ import de.bsvrz.sys.funclib.bitctrl.interpreter.Operator;
*
* @author BitCtrl Systems GmbH, Schumann
*/
public class LogikHandler extends AbstractHandler {
public class LogikHandler extends Handler {
/** Konjunktion bzw. logisches "und" */
/** Logisches "und" */
public static final Operator UND = Operator.getOperator("und");
/** Disjunktion bzw. logisches "oder" */
/** Logisches "oder" */
public static final Operator ODER = Operator.getOperator("oder");
/** Negation bzw. logisches "nicht" */
/** Logisches "nicht" */
public static final Operator NICHT = Operator.getOperator("nicht");
/** Logische Implikation. */
......@@ -67,229 +67,80 @@ public class LogikHandler extends AbstractHandler {
}
@Override
public Object perform(final Operator operator, final List<Object> operanden) {
if (operator == null
|| !validiereHandler(operator, operanden).isValid()) {
throw new InterpreterException(
Messages.get(InterpreterMessages.HandlerNotFound));
public Object perform(Operator operator, List<?> operanden) {
if (operator == null || !validiereHandler(operator, operanden).isValid()) {
throw new InterpreterException(Messages.get(InterpreterMessages.HandlerNotFound));
}
LogischerWert result = null;
if (operator == UND) {
result = minimum(operanden.toArray());
return und(operanden.toArray(new LogischerWert[0]));
} else if (operator == ODER) {
result = maximum(operanden.toArray());
return oder(operanden.toArray(new LogischerWert[0]));
} else if (operator == NICHT) {
result = komplement(operanden.get(0));
return nicht((LogischerWert) operanden.get(0));
} else if (operator == IMPLIKATION) {
result = implikation(operanden.toArray());
return implikation((LogischerWert) operanden.get(0), (LogischerWert) operanden.get(1));
}
return result;
throw new IllegalStateException("[unreachable code] unbekannter Operator: " + operator);
}
@Override
public HandlerValidation validiereHandler(final Operator operator,
final List<? extends Object> operanden) {
assert operanden != null : "Liste der Operanden darf nicht null sein.";
boolean anzahlOk = false;
boolean typOk = true;
// Anzahl der Operanden und Operation prüfen
switch (operanden.size()) {
case 0:
anzahlOk = false;
break;
case 1:
if (NICHT.equals(operator)) {
anzahlOk = true;
}
break;
case 2:
if (IMPLIKATION.equals(operator)) {
anzahlOk = true;
}
break;
default:
}
public HandlerValidation validiereHandler(Operator operator, List<?> operanden) {
boolean anzahlOk = validiereAnzahl(operator, operanden);
boolean typOk = validiereTyp(operanden);
return new HandlerValidation(anzahlOk, typOk);
}
private static boolean validiereAnzahl(Operator operator, List<?> operanden) {
if (UND.equals(operator) || ODER.equals(operator)) {
if (operanden.size() >= 2) {
anzahlOk = true;
}
}
// Alle Operanden müssen ein logischer Wert sein
for (final Object obj : operanden) {
if (obj instanceof LogischerWert) {
final LogischerWert lw = (LogischerWert) obj;
if (!lw.isBoolWert()) {
typOk = false;
break;
}
} else {
typOk = false;
break;
}
return operanden.size() >= 2;
} else if (NICHT.equals(operator)) {
return operanden.size() == 1;
} else if (IMPLIKATION.equals(operator)) {
return operanden.size() == 2;
} else {
return false;
}
return new HandlerValidation(anzahlOk, typOk);
}
/**
* Bestimmt das Ergebnis der Implikation: nicht a oder b.
*
* @param operanden
* Operandenliste mit genau zwei Operanden: a und b
* @return Logischer Wert mit berechneter Zugeh&ouml;rigkeit oder booleschen
* Wert, wenn alle Operanden boolesche Werte haben
*/
protected LogischerWert implikation(final Object[] operanden) {
assert operanden != null : "Argument operanden darf nicht null sein.";
assert operanden.length == 2 : "Anzahl der Operanden muss gleich 2 sein.";
assert operanden[0] instanceof LogischerWert : "Operanden müssen logische Werte sein.";
assert operanden[1] instanceof LogischerWert : "Operanden müssen logische Werte sein.";
final LogischerWert na = komplement(operanden[0]);
final LogischerWert[] ab = { na, (LogischerWert) operanden[1] };
return maximum(ab);
private static boolean validiereTyp(List<?> operanden) {
return operanden.stream()
.map(o -> o instanceof LogischerWert)
.reduce(Boolean::logicalAnd)
.orElse(false);
}
/**
* Berechnet das Komplement: 1 - a. Entspricht dem logischen "nicht".
*
* @param operand
* Operand
* @return Logischer Wert mit berechneter Zugeh&ouml;rigkeit oder booleschen
* Wert, wenn alle Operanden boolesche Werte haben
*/
protected LogischerWert komplement(final Object operand) {
assert operand != null : "Argument operand darf nicht null sein.";
assert operand instanceof LogischerWert : "Operand muss ein logische Werte sein.";
final LogischerWert wert = (LogischerWert) operand;
if (wert.isBoolWert()) {
return new LogischerWert(!wert.getBoolWert());
}
if (wert.getZugehoerigkeit() == null) {
return new LogischerWert(null);
}
final Double d = Math.abs(1.0 - wert.getZugehoerigkeit());
return new LogischerWert(d.floatValue());
protected LogischerWert und(LogischerWert... operanden) {
return und(Arrays.asList(operanden));
}
/**
* Bestimmt das Maximum: max(a, b, ...). Entspricht dem logischen "oder".
*
* @param operanden
* Operandenliste mit mindestens einem Operanden
* @return Logischer Wert mit berechneter Zugeh&ouml;rigkeit oder booleschen
* Wert, wenn alle Operanden boolesche Werte haben
*/
protected LogischerWert maximum(final Object[] operanden) {
assert operanden != null : "Argument operanden darf nicht null sein.";
assert operanden.length > 0 : "Anzahl der Operanden muss größer 0 sein.";
Float wert = null;
boolean boolWert = true;
for (final Object obj : operanden) {
assert obj instanceof LogischerWert : "Operanden müssen logische Werte sein.";
LogischerWert operand;
operand = (LogischerWert) obj;
if (!operand.isBoolWert()) {
boolWert = false;
if (operand.getZugehoerigkeit() == null) {
// Einer der Operanden ist null => Ergebnis = null
return new LogischerWert(null);
}
}
if (wert == null) {
// Erster Operand
wert = operand.getZugehoerigkeit();
} else {
if (operand.getZugehoerigkeit() > wert) {
wert = operand.getZugehoerigkeit();
}
}
}
if (boolWert) {
// XXX assert eventuell entfernen
assert (wert != null) && (wert == 1 || wert == 0);
if (wert != null && wert == 1) {
return new LogischerWert(true);
}
return new LogischerWert(false);
}
return new LogischerWert(wert);
protected LogischerWert und(Collection<LogischerWert> operanden) {
return operanden.stream()
.map(LogischerWert::get)
.reduce(Boolean::logicalAnd)
.map(LogischerWert::of)
.get();
}
/**
* Bestimmt das Minimum: min(a, b, ...). Entspricht dem logischen "und".
*
* @param operanden
* Operandenliste mit mindestens einem Operanden
* @return Logischer Wert mit berechneter Zugeh&ouml;rigkeit oder booleschen
* Wert, wenn alle Operanden boolesche Werte haben
*/
protected LogischerWert minimum(final Object[] operanden) {
assert operanden != null : "Argument operanden darf nicht null sein.";
assert operanden.length > 0 : "Anzahl der Operanden muss größer 0 sein.";
Float wert = null;
boolean boolWert = true;
for (final Object obj : operanden) {
assert obj instanceof LogischerWert : "Operanden müssen logische Werte sein.";
LogischerWert operand;
operand = (LogischerWert) obj;
if (!operand.isBoolWert()) {
boolWert = false;
if (operand.getZugehoerigkeit() == null) {
// Einer der Operanden ist null => Ergebnis = null
return new LogischerWert(null);
}
}
if (wert == null) {
// Erster Operand
wert = operand.getZugehoerigkeit();
} else {
if (operand.getZugehoerigkeit() == null) {
wert = null;
break;
}
if (operand.getZugehoerigkeit() < wert) {
wert = operand.getZugehoerigkeit();
}
}
}
if (boolWert) {
// XXX assert eventuell anders verwenden
assert wert != null && (wert == 1 || wert == 0);
protected LogischerWert oder(LogischerWert... operanden) {
return oder(Arrays.asList(operanden));
}
if (wert != null && wert == 1) {
return new LogischerWert(true);
}
protected LogischerWert oder(Collection<LogischerWert> operanden) {
return operanden.stream()
.map(LogischerWert::get)
.reduce(Boolean::logicalOr)
.map(LogischerWert::of)
.get();
}
return new LogischerWert(false);
}
protected LogischerWert nicht(LogischerWert a) {
return LogischerWert.of(!a.get());
}
return new LogischerWert(wert);
protected LogischerWert implikation(LogischerWert a, LogischerWert b) {
return oder(nicht(a), b);
}
}
......@@ -33,11 +33,11 @@ import de.bsvrz.sys.funclib.bitctrl.interpreter.Kontext;
import de.bsvrz.sys.funclib.bitctrl.interpreter.Variable;
/**
* Ein boolesches Terminalsymbol (Variable).
* Eine Variable die einen logischen Wert enthält.
*
* @author BitCtrl Systems GmbH, Schumann
*/
public class LogischesSymbol implements Variable {
public class LogischeVariable implements Variable<LogischerWert> {
/**
* Der Name der Variable im Kontext.
......@@ -50,19 +50,11 @@ public class LogischesSymbol implements Variable {
* @param name
* Name der Variable im Kontext
*/
public LogischesSymbol(final String name) {
public LogischeVariable(String name) {
Kontext.pruefeName(name);
this.name = name;
}
/**
* Gibt immer {@code null} zur&uuml;ck, da dies ein Terminalsymbol ist.
*/
@Override
public List<Ausdruck> getNachfolger() {
return null;
}
/**
* Nennt den Namen des Terminalsymbols.
*
......@@ -70,13 +62,11 @@ public class LogischesSymbol implements Variable {
*/
@Override
public String getName() {
assert name != null && name != ""; //$NON-NLS-1$
return name;
}
@Override
public Object interpret(final Kontext kontext) {
public LogischerWert interpret(Kontext kontext) {
if (kontext.enthaelt(getName())) {
return kontext.get(getName(), LogischerWert.class);
}
......
......@@ -31,213 +31,50 @@ import com.bitctrl.i18n.Messages;
import de.bsvrz.sys.funclib.bitctrl.interpreter.InterpreterException;
import de.bsvrz.sys.funclib.bitctrl.interpreter.InterpreterMessages;
import java.util.*;
/**
* Der Wert eines LogischenAsudrucks, der f&uuml;r Boolesche Logik und
* Fuzzy-Logik verwendbar ist. Boolsche Logik wird intern durch die
* Zugeh&ouml;rigkeitswerte "1" und "0" repr&auml;sentiert.
* Wertobjekt für einen booleschen Wert.
*
* @author BitCtrl Systems GmbH, Peuker
* @author BitCtrl Systems GmbH, Schumann
* @author BitCtrl Systems GmbH, Uwe Peuker
* @author BitCtrl Systems GmbH, Falko Schumann
*/
public class LogischerWert {
public final class LogischerWert {
/**
* Eine globale Instanz f&uuml;r den boolschen Wert <i>true</i>.
*/
public static final LogischerWert WAHR = new LogischerWert(true);
/**
* Eine globale Instanz f&uuml;r den boolschen Wert <i>false</i>.
*/
public static final LogischerWert FALSCH = new LogischerWert(false);
/**
* liefert die statische Instanz eines logischen Wertes f&uuml;r die
* Boolschen Werte WAHR und FALSCH.
*
* @param wert
* der boolsche Wert.
* @return die Instanz.
*/
public static final LogischerWert valueOf(final boolean wert) {
if (wert) {
return WAHR;
}
return FALSCH;
public static final LogischerWert of(final boolean wert) {
return wert ? WAHR : FALSCH;
}
/**
* Die Zugeh&ouml;rigkeit.
*/
private Float zugehoerigkeit;
/**
* Gibt an, ob der Wert gerade ein logischer oder ein
* Zugeh&ouml;rigkeitswert ist.
*/
private boolean boolWert;
private final boolean wert;
/**
* Der Konstruktor erzeugt einen logischen Wert mit der Zugeh&ouml;rigkeit
* "1" f&uuml;r <i>true</i> bzw "0" f&uuml;r <i>false</i>.
*
* @param wert
* Der boolsche Wert, den der logische Wert repr&auml;sentieren
* soll
*/
public LogischerWert(final boolean wert) {
set(wert);
private LogischerWert(boolean wert){
this.wert = wert;
}
/**
* Der Konstruktor erzeugt einen logischen Wert mit der &uuml;bergebenen
* Zugeh&ouml;rigkeit.
*
* @param wert
* Der Zugeh&ouml;rigkeitswert
*/
public LogischerWert(final Float wert) {
set(wert);
public boolean get() {
return wert;
}
@Override
public int hashCode() {
throw new UnsupportedOperationException();
}
/**
* Zwei logische Werte sind gleich, wenn sie beide den selben Typ (logischer
* Wert oder Zugeh&ouml;rigkeit) und Wert besitzen.
*/
@Override
public boolean equals(final Object obj) {
if (obj instanceof LogischerWert) {
final LogischerWert lw = (LogischerWert) obj;
Float f1, f2;
f1 = zugehoerigkeit;
f2 = lw.zugehoerigkeit;
if (!(boolWert ^ lw.boolWert) && f1.equals(f2)) {
return true;
}
}
return false;
}
/**
* Gibt den aktuellen Wert zur&uuml;ck.
*
* @return Wert vom Typ {@code Float} oder {@code Boolean}
*/
public Object get() {
if (!boolWert) {
return zugehoerigkeit;
}
assert zugehoerigkeit == 0 || zugehoerigkeit == 1;
if (getZugehoerigkeit() == 1) {
return true;
}
return false;
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LogischerWert that = (LogischerWert) o;
return wert == that.wert;
}
/**
* Liefert einen booleschen Wert entsprechend der Zugeh&ouml;rigkeit des
* logischen Wertes. Die Zugeh&ouml;rigkeit "1" entspricht dem booleschen
* Wert <i>true</i>, die Zugeh&ouml;rigkeit "0" entspricht dem booleschen
* Wert <i>false</i>. Hat die Zugeh&ouml;rigkeit einen anderen Wert wird
* eine <b>InterpreterException</b> geworfen.
*
* @return Den Wert
*/
public boolean getBoolWert() {
if (!boolWert) {
throw new InterpreterException(
Messages.get(InterpreterMessages.NoBooleanValue));
}
assert zugehoerigkeit == 0 || zugehoerigkeit == 1;
if (getZugehoerigkeit() == 1) {
return true;
}
return false;
}
/**
* Liefert den Zugeh&ouml;rigkeitswert, der durch den logischen Wert
* repr&auml;sentiert wird.
*
* @return Wert
*/
public Float getZugehoerigkeit() {
return zugehoerigkeit;
}
/**
* Pr&uuml;ft ob der logische Wert ein boolescher Wert ist.
*
* @return {@code true}, wenn der Wert ein boolescher Wert ist, sonst
* {@code false}
*/
public boolean isBoolWert() {
return boolWert;
}
/**
* Setzt den Wert auf den angegebenen booleschen Wert.
*
* @param wert
* boolescher Wert
*/
public void set(final boolean wert) {
if (wert) {
set(1f);
} else {
set(0f);
}
boolWert = true;
}
/**
* Setzt den Wert auf die angegebene Zugeh&ouml;rigkeit.
*
* @param z
* Zugeh&ouml;rigkeit.
*/
public void set(final Float z) {
if (z != null && (z < 0 || z > 1)) {
throw new InterpreterException(Messages.get(
InterpreterMessages.BadMembership, z));
}
zugehoerigkeit = z;
boolWert = false;
@Override
public int hashCode() {
return Objects.hash(wert);
}
/**
* Wenn der logische Wert ein boolescher Wert ist, wird "wahr" oder "falsch"
* zur&uuml;ckgegeben, sonst der Zahlenwert der Zugeh&ouml;rigkeit.
*/
@Override
public String toString() {
String result;
if (boolWert) {
if (getBoolWert()) {
result = "wahr";
} else {
result = "falsch";
}
} else {
result = String.valueOf(getZugehoerigkeit());
}
return result;
return wert ? "wahr" : "falsch";
}
}
......@@ -33,11 +33,11 @@ import de.bsvrz.sys.funclib.bitctrl.interpreter.Kontext;
import de.bsvrz.sys.funclib.bitctrl.interpreter.Literal;
/**
* Ein boolesches Terminalsymbol (Literal).
* Ein Literal das einen logischen Wert enthält.
*
* @author BitCtrl Systems GmbH, Falko Schumann
*/
public class LogischesLiteral implements Literal {
public class LogischesLiteral implements Literal<LogischerWert> {
/**
* Repr&auml;sentiert den logischen Wert des Literals.
......@@ -51,17 +51,7 @@ public class LogischesLiteral implements Literal {
* Wert
*/
public LogischesLiteral(final boolean wert) {
this.wert = new LogischerWert(wert);
}
/**
* Konstruiert ein Terminalsymbol mit dem angegebenen Wert.
*
* @param wert
* Wert
*/
public LogischesLiteral(final Float wert) {
this.wert = new LogischerWert(wert);
this.wert = LogischerWert.of(wert);
}
/**
......@@ -71,39 +61,17 @@ public class LogischesLiteral implements Literal {
* Wert
*/
public LogischesLiteral(final LogischerWert wert) {
if (wert.isBoolWert()) {
this.wert = new LogischerWert(wert.getBoolWert());
} else {
this.wert = new LogischerWert(wert.getZugehoerigkeit());
}
}
/**
* Gibt immer {@code null} zur&uuml;ck, da dies ein Terminalsymbol ist.
*/
@Override
public List<Ausdruck> getNachfolger() {
return null;
}
/**
* Nennt den Wert des Terminalsymbols.
*
* @return Wert des Literal
*/
@Override
public LogischerWert getWert() {
return wert;
this.wert = wert;
}
@Override
public Object interpret(final Kontext kontext) {
public LogischerWert interpret(final Kontext kontext) {
return wert;
}
@Override
public String toString() {
return getWert().toString();
return wert.toString();
}
}
......@@ -25,19 +25,33 @@
*/
package de.bsvrz.sys.funclib.bitctrl.interpreter;
import de.bsvrz.sys.funclib.bitctrl.interpreter.logik.LogikHandler;
import de.bsvrz.sys.funclib.bitctrl.interpreter.logik.LogischerWert;
import de.bsvrz.sys.funclib.bitctrl.interpreter.logik.*;
import org.junit.*;
import static de.bsvrz.sys.funclib.bitctrl.interpreter.logik.LogikHandler.*;
import static org.junit.Assert.*;
public final class TestInterpreter {
private TestInterpreter() {
// es gibt keine Instanzen der Klasse
}
@BeforeClass
public static void registerHandler() {
Operator.registerHandler(new LogikHandler());
}
@Test
public void test() {
Ausdruck<?> ausdruck = new Operation<>(UND,
new LogischesLiteral(true),
new Operation<>(ODER,
new LogischesLiteral(true),
new LogischesLiteral(false)
)
);
Kontext kontext = new Kontext();
public static void main(final String[] args) {
final Handler h = new LogikHandler();
LogischerWert wert = (LogischerWert) ausdruck.interpret(kontext);
h.validiereHandler(Operator.getOperator("nicht"), LogischerWert.WAHR);
}
assertTrue(wert.get());
}
}