Skip to content
Commits on Source (9)
......@@ -9,19 +9,23 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.bitctrl.util.monitor.IMonitor;
import com.bitctrl.util.monitor.SubMonitor;
import de.bsvrz.dav.daf.main.config.DataModel;
import de.bsvrz.dav.daf.main.config.SystemObject;
import de.bsvrz.sys.funclib.bitctrl.modell.ObjektFactory;
import de.bsvrz.sys.funclib.bitctrl.modell.SystemObjekt;
import de.bsvrz.sys.funclib.bitctrl.modell.tmkexlmstglobal.attribute.AttRdsTMCRichtung;
import de.bsvrz.sys.funclib.bitctrl.modell.tmtmcglobal.attribute.AttTmcRichtung;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.konfigurationsdaten.KdAeusseresStrassenSegment;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.konfigurationsdaten.KdGesamtStrasse;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.konfigurationsdaten.KdStrasse.Daten;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.konfigurationsdaten.KdStrassenSegment;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.objekte.AeusseresStrassenSegment;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.objekte.GesamtStrasse;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.objekte.InneresStrassenSegment;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.objekte.Netz;
import de.bsvrz.sys.funclib.bitctrl.modell.tmverkehrglobal.objekte.NetzBestandTeil;
......@@ -51,9 +55,7 @@ public class NetzCache extends AbstractCache {
private Map<Strasse, List<StrassenSegment>> s2ss;
private Map<StrassenSegment, Strasse> ss2s;
// StraßenSegment <-> StraßenTeilSegment
// private Map<StrassenSegment, List<StrassenTeilSegment>> ss2sts;
// private Map<StrassenTeilSegment, List<StrassenSegment>> sts2ss;
private Set<GesamtStrasse> gesamtstrassen;
/**
* Map, welche zu einem Straßennamen die dazugehörige Straße speichert.
......@@ -66,45 +68,38 @@ public class NetzCache extends AbstractCache {
private HashMap<Strasse, String> strassenNummernMap;
/**
* Map, welche den Namen des Von-Knotens zu einer Straße in positiver
* Richtung speichert. Bei negativer Richtung ist dann der Von-Knoten der
* Nach-Knoten.
* Map, welche den Namen des Von-Knotens zu einer Straße in positiver Richtung
* speichert. Bei negativer Richtung ist dann der Von-Knoten der Nach-Knoten.
*/
private Map<Strasse, String> vonStrassenKnotenMap;
/**
* Map, welche den Namen des Nach-Knotens zu einer Straße in positiver
* Richtung speichert. Bei negativer Richtung ist dann der Nach-Knoten der
* Von-Knoten.
* Map, welche den Namen des Nach-Knotens zu einer Straße in positiver Richtung
* speichert. Bei negativer Richtung ist dann der Nach-Knoten der Von-Knoten.
*/
private Map<Strasse, String> nachStrassenKnotenMap;
/**
* Initialisert den Netzcache, in dem alle notwendige Daten aus der
* Konfiguration gelesen und zwischengespeichert werden. Insbesondere werden
* notwendige Rückwärtreferenzen aufgelöst, die in der Konfiguration so
* nicht gesichert werden.
* notwendige Rückwärtreferenzen aufgelöst, die in der Konfiguration so nicht
* gesichert werden.
*
* Nach Aufruf der Methode ist der Cache <strong>nicht</strong>
* initialisert. Stattdessen wird ein Job angestoßen der diese Aufgabe
* übernimmt.
* Nach Aufruf der Methode ist der Cache <strong>nicht</strong> initialisert.
* Stattdessen wird ein Job angestoßen der diese Aufgabe übernimmt.
*
* @param moc
* der Cache, von welchem dieser Cache abhängig ist
* @param verbindungsCache
* der verwendete Verbindungscache
* @param moc der Cache, von welchem dieser Cache abhängig ist
* @param verbindungsCache der verwendete Verbindungscache
*
* @see AbstractCache#isInitialisiert()
* @see #addPropertyChangeListener(PropertyChangeListener)
* @see #PROP_STATE
*/
public NetzCache(final ModellObjektCache moc,
final AbstractDavVerbindungsCache verbindungsCache) {
public NetzCache(final ModellObjektCache moc, final AbstractDavVerbindungsCache verbindungsCache) {
super(moc, verbindungsCache);
}
protected void preInit(final ModellObjektCache moc,
final AbstractDavVerbindungsCache verbindungsCache) {
protected void preInit(final ModellObjektCache moc, final AbstractDavVerbindungsCache verbindungsCache) {
this.moc = moc;
this.verbindungsCache = verbindungsCache;
}
......@@ -122,6 +117,7 @@ public class NetzCache extends AbstractCache {
s2ss = new HashMap<>();
ss2s = new HashMap<>();
gesamtstrassen = new HashSet<>();
// ss2sts = new HashMap<StrassenSegment, List<StrassenTeilSegment>>();
// sts2ss = new HashMap<StrassenTeilSegment, List<StrassenSegment>>();
......@@ -145,15 +141,12 @@ public class NetzCache extends AbstractCache {
// (2) Lade Konfigurationsdaten "AeussereStrassenSegment"
subMonitor.subTask("Lade StrassenSegment-Daten der Netzbestandteile");
final DataModel dataModel = verbindungsCache.getObjektFactory().getDav()
.getDataModel();
final DataModel dataModel = verbindungsCache.getObjektFactory().getDav().getDataModel();
if (isBenutzeBlockAbruf()) {
dataModel.getConfigurationData(aessSO,
dataModel.getAttributeGroup(KdStrassenSegment.PID));
dataModel.getConfigurationData(aessSO, dataModel.getAttributeGroup(KdStrassenSegment.PID));
} else {
for (final SystemObject so : aessSO) {
so.getConfigurationData(
dataModel.getAttributeGroup(KdStrassenSegment.PID));
so.getConfigurationData(dataModel.getAttributeGroup(KdStrassenSegment.PID));
}
}
subMonitor.worked(250);
......@@ -163,15 +156,12 @@ public class NetzCache extends AbstractCache {
}
// (3) Lade Daten
subMonitor.subTask(
"Lade AeussereStrassenSegment-Daten der Netzbestandteile");
subMonitor.subTask("Lade AeussereStrassenSegment-Daten der Netzbestandteile");
if (isBenutzeBlockAbruf()) {
dataModel.getConfigurationData(aessSO, dataModel
.getAttributeGroup(KdAeusseresStrassenSegment.PID));
dataModel.getConfigurationData(aessSO, dataModel.getAttributeGroup(KdAeusseresStrassenSegment.PID));
} else {
for (final SystemObject so : aessSO) {
so.getConfigurationData(dataModel
.getAttributeGroup(KdAeusseresStrassenSegment.PID));
so.getConfigurationData(dataModel.getAttributeGroup(KdAeusseresStrassenSegment.PID));
}
}
......@@ -190,11 +180,8 @@ public class NetzCache extends AbstractCache {
int i = 1;
for (final AeusseresStrassenSegment segment : aess) {
subMonitor2
.subTask(new StringBuffer("Analysiere Netzbestandteil ")
.append(i).append(" von ")
.append(anzahlSegmente).append(": ")
.append(segment.getName()).toString());
subMonitor2.subTask(new StringBuffer("Analysiere Netzbestandteil ").append(i).append(" von ")
.append(anzahlSegmente).append(": ").append(segment.getName()).toString());
cacheAeusseresStrassenSegment(segment);
subMonitor2.worked(1);
......@@ -206,41 +193,56 @@ public class NetzCache extends AbstractCache {
}
}
final ObjektFactory objektFactory = verbindungsCache.getObjektFactory();
@SuppressWarnings("unchecked")
final List<GesamtStrasse> alleGesamtStrassen = (List<GesamtStrasse>) objektFactory
.bestimmeModellobjekte(GesamtStrasse.PID);
objektFactory.getDaten(alleGesamtStrassen, KdGesamtStrasse.class);
final Set<Strasse> alleStrassenDesNetzes = s2ss.keySet();
for (final GesamtStrasse g : alleGesamtStrassen) {
final KdGesamtStrasse.Daten datum = g.getKdGesamtStrasse().getDatum();
if (datum != null) {
boolean enthalten = datum.getStrasseFR1().stream().anyMatch(s -> alleStrassenDesNetzes.contains(s));
if (!enthalten) {
enthalten = datum.getStrasseFR2().stream().anyMatch(s -> alleStrassenDesNetzes.contains(s));
}
if (enthalten) {
gesamtstrassen.add(g);
}
}
}
// TODO Straßensegmente der Straßen sortieren
// TODO Straßenteilsegmente der Straßensegmente sortieren
Debug.getLogger()
.info("Benötigte Zeit zum Initialisieren des BitCtrl Netz-Caches: "
Debug.getLogger().info("Benötigte Zeit zum Initialisieren des BitCtrl Netz-Caches: "
+ (System.currentTimeMillis() - start) + " ms");
return true;
}
/**
* Ermittelt rekursiv sämtliche äußeren Straßensegmente eines Netzes sowie
* deren Teilnetze.
* Ermittelt rekursiv sämtliche äußeren Straßensegmente eines Netzes sowie deren
* Teilnetze.
*
* @param netz
* das Netz
* @param besuchteNetze
* die bereits besuchte Netze, verhindert Endlosschleifen
* @param netz das Netz
* @param besuchteNetze die bereits besuchte Netze, verhindert Endlosschleifen
*/
private void ermittelAeussereStrassenSegmente(final Netz netz,
final ArrayList<Netz> besuchteNetze) {
private void ermittelAeussereStrassenSegmente(final Netz netz, final ArrayList<Netz> besuchteNetze) {
if (besuchteNetze.contains(netz)) {
return;
}
besuchteNetze.add(netz);
for (final NetzBestandTeil netzBestandTeil : netz
.getNetzBestandTeile()) {
if (netzBestandTeil instanceof AeusseresStrassenSegment
&& !aess.contains(netzBestandTeil)) {
for (final NetzBestandTeil netzBestandTeil : netz.getNetzBestandTeile()) {
if (netzBestandTeil instanceof AeusseresStrassenSegment && !aess.contains(netzBestandTeil)) {
aess.add((AeusseresStrassenSegment) netzBestandTeil);
} else if (netzBestandTeil instanceof Netz) {
ermittelAeussereStrassenSegmente((Netz) netzBestandTeil,
besuchteNetze);
ermittelAeussereStrassenSegmente((Netz) netzBestandTeil, besuchteNetze);
}
}
}
......@@ -248,16 +250,13 @@ public class NetzCache extends AbstractCache {
/**
* Cacht die Daten des Start- und Endknoten eines äußeren Straßensegments.
*
* @param segment
* das äußere Straßensegment
* @param segment das äußere Straßensegment
*/
protected void cacheAeusseresStrassenSegment(
final AeusseresStrassenSegment segment) {
protected void cacheAeusseresStrassenSegment(final AeusseresStrassenSegment segment) {
// cacheStrassenTeilSegmente(aess);
cacheStrasse(segment);
StrassenKnoten sk = segment.getKdAeusseresStrassenSegment().getDatum()
.getVonKnoten();
StrassenKnoten sk = segment.getKdAeusseresStrassenSegment().getDatum().getVonKnoten();
if (sk != null) {
cacheInneresStrasseSegment(sk);
}
......@@ -269,12 +268,10 @@ public class NetzCache extends AbstractCache {
}
/**
* Erzeugt die Referenzen StraßenKnoten &lt;-&gt; InneresStraßenSegment.
* Cacht auch die Straße und die Straßenteilsegmente der inneren
* Straßensegmente.
* Erzeugt die Referenzen StraßenKnoten &lt;-&gt; InneresStraßenSegment. Cacht
* auch die Straße und die Straßenteilsegmente der inneren Straßensegmente.
*
* @param sk
* der zu cachende Straßenknoten
* @param sk der zu cachende Straßenknoten
*/
protected void cacheInneresStrasseSegment(final StrassenKnoten sk) {
if (sk2iss.containsKey(sk)) {
......@@ -283,8 +280,7 @@ public class NetzCache extends AbstractCache {
}
final Set<InneresStrassenSegment> mengeISS = new HashSet<>();
for (final InneresStrassenSegment iss : sk
.getInnereStrassenSegmente()) {
for (final InneresStrassenSegment iss : sk.getInnereStrassenSegmente()) {
iss2sk.put(iss, sk);
mengeISS.add(iss);
......@@ -297,8 +293,7 @@ public class NetzCache extends AbstractCache {
/**
* Erzeugt die Referenzen StraßenSegment &lt;-&gt; Straßen.
*
* @param ss
* das Straßensegment
* @param ss das Straßensegment
*/
protected void cacheStrasse(final StrassenSegment ss) {
if (ss2s.containsKey(ss)) {
......@@ -322,8 +317,7 @@ public class NetzCache extends AbstractCache {
s2ss.get(s).add(ss);
// Parse den Straßennamen und fülle die entsprechenden Maps
if (s.getKdStrasse() == null
|| s.getKdStrasse().getDatum() == null) {
if (s.getKdStrasse() == null || s.getKdStrasse().getDatum() == null) {
return;
}
final Daten datum = s.getKdStrasse().getDatum();
......@@ -331,54 +325,24 @@ public class NetzCache extends AbstractCache {
if (strassenNamenMap.get(name) == null) {
strassenNamenMap.put(name, s);
}
final String nummer = datum.getTyp().toString().substring(0, 1)
+ datum.getNummer().getValue();
final String nummer = datum.getTyp().toString().substring(0, 1) + datum.getNummer().getValue();
if (strassenNummernMap.get(s) == null) {
strassenNummernMap.put(s, nummer);
}
if (name.contains(" von ") && name.contains(" nach ")) {
if (vonStrassenKnotenMap.get(s) == null) {
final String vonStrassenKnoten = name.substring(
name.indexOf(" von ") + 5, name.indexOf(" nach "));
final String vonStrassenKnoten = name.substring(name.indexOf(" von ") + 5, name.indexOf(" nach "));
vonStrassenKnotenMap.put(s, vonStrassenKnoten);
}
if (nachStrassenKnotenMap.get(s) == null) {
final String nachStrassenKnoten = name
.substring(name.indexOf(" nach ") + 6);
final String nachStrassenKnoten = name.substring(name.indexOf(" nach ") + 6);
nachStrassenKnotenMap.put(s, nachStrassenKnoten);
}
}
}
}
/**
* Erzeugt die Referenzen StraßenSegment <-> StraßenTeilSegment.
*
* @param ss
* das zu cachende Straßensegment
*/
// protected void cacheStrassenTeilSegmente(final StrassenSegment ss) {
// if (ss2sts.containsKey(ss)) {
// // Straßensegment wurde bereits gecacht
// return;
// }
//
// final List<Linie> linien = ss.getKdBestehtAusLinienObjekten()
// .getDatum().getLinienReferenz();
// final List<StrassenTeilSegment> listSTS = new
// ArrayList<StrassenTeilSegment>();
// for (final Linie linie : linien) {
// final StrassenTeilSegment sts = (StrassenTeilSegment) linie;
// listSTS.add(sts);
//
// if (!sts2ss.containsKey(sts)) {
// sts2ss.put(sts, new ArrayList<StrassenSegment>());
// }
// sts2ss.get(sts).add(ss);
// }
// ss2sts.put(ss, listSTS);
// }
/**
* Gibt das Netz zurück, welches diesem Netzcache zugrunde liegt.
*
......@@ -388,6 +352,35 @@ public class NetzCache extends AbstractCache {
return verkehrsModellNetz;
}
/**
* Gibt die {@link GesamtStrasse}s im Netz zurück.
*
* @return die vorhandenen {@link GesamtStrasse}n.
*/
public Set<GesamtStrasse> getGesamtStrassen() {
ensureInit();
return Collections.unmodifiableSet(gesamtstrassen);
}
/**
* Liefert die {@link Strasse}n einer {@link GesamtStrasse} in der gefragten
* Richtung. Es werden nur {@link Strasse}n ermittelt, die auch im Netz sind.
*
*/
public Set<Strasse> getStrassen(final GesamtStrasse gesamtStraße, final AttTmcRichtung richtung) {
final Set<Strasse> strassen = getStrassen();
final KdGesamtStrasse.Daten datum = gesamtStraße.getKdGesamtStrasse().getDatum();
if (datum != null) {
if (AttTmcRichtung.ZUSTAND_1_POSITIV.equals(richtung)) {
return datum.getStrasseFR1().stream().filter(s -> strassen.contains(s)).collect(Collectors.toSet());
} else if (AttTmcRichtung.ZUSTAND_1N_NEGATIV.equals(richtung)) {
return datum.getStrasseFR2().stream().filter(s -> strassen.contains(s)).collect(Collectors.toSet());
}
}
return Collections.unmodifiableSet(Collections.emptySet());
}
/**
* Gibt die Straßen im Netz zurück.
*
......@@ -418,16 +411,6 @@ public class NetzCache extends AbstractCache {
return Collections.unmodifiableSet(ss2s.keySet());
}
/**
* Gibt die Straßenteilsegmente im Netz zurück.
*
* @return die Straßenteilsegmente im Netz.
*/
// public Set<StrassenTeilSegment> getStrassenTeilSegmente() {
// ensureInit();
// return Collections.unmodifiableSet(sts2ss.keySet());
// }
/**
* Gibt die Menge aller Strassenknoten zurück, die sich im Netz befinden.
*
......@@ -439,11 +422,9 @@ public class NetzCache extends AbstractCache {
}
/**
* Gibt zu einem inneren Straßensegment den dazugehörigen Straßenknoten
* zurück.
* Gibt zu einem inneren Straßensegment den dazugehörigen Straßenknoten zurück.
*
* @param iss
* ein inneres Straßensegment.
* @param iss ein inneres Straßensegment.
* @return der dazugehörige Straßenknoten oder <code>null</code>, wenn das
* innere Straßensegment unbekannt ist.
*/
......@@ -455,13 +436,11 @@ public class NetzCache extends AbstractCache {
/**
* Gibt die inneren Straßensegmente eines Straßenknotens zurück.
*
* @param sk
* ein Straßenknoten.
* @param sk ein Straßenknoten.
* @return die inneren Straßensegmente oder eine leere Liste, wenn der
* Straßenknoten keine Straßensegmente hat oder unbekannt ist.
*/
public Set<InneresStrassenSegment> getInneresStrassenSegmente(
final StrassenKnoten sk) {
public Set<InneresStrassenSegment> getInneresStrassenSegmente(final StrassenKnoten sk) {
ensureInit();
return sk2iss.get(sk);
}
......@@ -469,20 +448,22 @@ public class NetzCache extends AbstractCache {
/**
* Gibt die Straßensegmente einer Straße zurück.
*
* @param strasse
* eine Straße.
* @param strasse eine Straße.
* @return die Straßensegmente der Strasse.
*/
public List<StrassenSegment> getStrassenSegmente(final Strasse strasse) {
ensureInit();
return Collections.unmodifiableList(s2ss.get(strasse));
final List<StrassenSegment> list = s2ss.get(strasse);
if (list != null) {
return Collections.unmodifiableList(list);
}
return Collections.unmodifiableList(Collections.emptyList());
}
/**
* Gibt die Straße zu einem Straßensegment zurück.
*
* @param ss
* ein Straßensegment.
* @param ss ein Straßensegment.
* @return die Straße auf dem das Straßensegment liegt.
*/
public Strasse getStrasse(final StrassenSegment ss) {
......@@ -490,39 +471,10 @@ public class NetzCache extends AbstractCache {
return ss2s.get(ss);
}
/**
* Gibt zu einem Straßenteilsegment das Straßensegment (inneres oder
* äußeres) zurück.
*
* @param sts
* ein Straßenteilsegment.
* @return das dazugehörige innere oder äußere Straßensegment.
*/
// public List<StrassenSegment> getStrassenSegment(
// final StrassenTeilSegment sts) {
// ensureInit();
// return Collections.unmodifiableList(sts2ss.get(sts));
// }
/**
* Gibt zu einem Straßensegment (inneres oder äußeres) die dazugehörigen
* Straßenteilsegmente zurück.
*
* @param ss
* ein inneres oder äußeres Straßensegment.
* @return die dazugehörigen Straßenteilsegmente.
*/
// public List<StrassenTeilSegment> getStrassenTeilSegmente(
// final StrassenSegment ss) {
// ensureInit();
// return Collections.unmodifiableList(ss2sts.get(ss));
// }
/**
* Liefert die zu einem gegebenen Straßennamen gehörige Straße zurück.
*
* @param strassenName
* der Straßenname, darf nicht <code>null</code> sein
* @param strassenName der Straßenname, darf nicht <code>null</code> sein
*
* @return die zu einem gegebenen Straßennamen gehörige Straße, kann
* <code>null</code> sein
......@@ -536,8 +488,7 @@ public class NetzCache extends AbstractCache {
/**
* Liefert die Straßennummer einer gegebenen Straße zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
*
* @return die Straßennummer einer gegebenen Straße
*/
......@@ -549,33 +500,28 @@ public class NetzCache extends AbstractCache {
/**
* Liefert den Straßennamen zu einer gegebenen Straßennummer und Richtung
* zurück. Sollte kein Straßenname für die gegebene Straßennummer
* existieren, wird die Straßennummer zurückgegeben.
* zurück. Sollte kein Straßenname für die gegebene Straßennummer existieren,
* wird die Straßennummer zurückgegeben.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Richtung, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Richtung, darf nicht <code>null</code> sein
*
* @return Straßennamen zu einer gegebenen Straßennummer und Richtungr,
* niemals <code>null</code>
* @return Straßennamen zu einer gegebenen Straßennummer und Richtungr, niemals
* <code>null</code>
*/
public String getStrassenName(final Strasse strasse,
final AttRdsTMCRichtung richtung) {
public String getStrassenName(final Strasse strasse, final AttRdsTMCRichtung richtung) {
ensureInit();
assert strasse != null;
assert richtung != null;
if (richtung.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV
.getValue()) {
if (richtung.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV.getValue()) {
return strasse.getName();
}
final String nummer = getStrassenNummer(strasse);
final String von = getVonStrassenKnoten(strasse, richtung);
final String nach = getNachStrassenKnoten(strasse, richtung);
if (nummer != null && !"".equals(nummer) && von != null
&& !"".equals(von) && nach != null && !"".equals(nach)) {
return new StringBuffer(nummer).append(" von ").append(von)
.append(" nach ").append(nach).toString();
if (nummer != null && !"".equals(nummer) && von != null && !"".equals(von) && nach != null
&& !"".equals(nach)) {
return new StringBuffer(nummer).append(" von ").append(von).append(" nach ").append(nach).toString();
}
return strasse.getName();
}
......@@ -583,48 +529,38 @@ public class NetzCache extends AbstractCache {
/**
* Liefert den Straßennamen zu einer gegebenen Straße und Richtung zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Richtung, darf auch <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Richtung, darf auch <code>null</code> sein
*
* @return Straßennamen zu einer gegebenen Straßennummer und Richtung,
* niemals <code>null</code>
* @return Straßennamen zu einer gegebenen Straßennummer und Richtung, niemals
* <code>null</code>
*/
public String getStrassenName(final Strasse strasse,
final AttTmcRichtung richtung) {
public String getStrassenName(final Strasse strasse, final AttTmcRichtung richtung) {
ensureInit();
assert strasse != null;
if (AttTmcRichtung.ZUSTAND_1N_NEGATIV.equals(richtung)) {
return getStrassenName(strasse,
AttRdsTMCRichtung.ZUSTAND_1_NEGATIV);
return getStrassenName(strasse, AttRdsTMCRichtung.ZUSTAND_1_NEGATIV);
}
if (AttTmcRichtung.ZUSTAND_1_POSITIV.equals(richtung)) {
return getStrassenName(strasse,
AttRdsTMCRichtung.ZUSTAND_0_POSITIV);
return getStrassenName(strasse, AttRdsTMCRichtung.ZUSTAND_0_POSITIV);
}
return strasse.getName();
}
/**
* Liefert den Namen des Von-Straßenknotens zu einer gegebenen Straße
* zurück.
* Liefert den Namen des Von-Straßenknotens zu einer gegebenen Straße zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Straßenrichtung, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Straßenrichtung, darf nicht <code>null</code> sein
*
* @return Von-Straßenknoten zu einer gegebenen Straßennummer, kann
* <code>null</code> sein
*/
public String getVonStrassenKnoten(final Strasse strasse,
final AttRdsTMCRichtung richtung) {
public String getVonStrassenKnoten(final Strasse strasse, final AttRdsTMCRichtung richtung) {
ensureInit();
assert strasse != null;
assert richtung != null;
final String vonStrassenKnoten = (richtung
.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV.getValue())
final String vonStrassenKnoten = (richtung.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV.getValue())
? vonStrassenKnotenMap.get(strasse)
: nachStrassenKnotenMap.get(strasse);
if (vonStrassenKnoten != null && !"".equals(vonStrassenKnoten)) {
......@@ -634,44 +570,34 @@ public class NetzCache extends AbstractCache {
}
/**
* Liefert den Namen des Von-Straßenknotens zu einer gegebenen Straße
* zurück.
* Liefert den Namen des Von-Straßenknotens zu einer gegebenen Straße zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Straßenrichtung, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Straßenrichtung, darf nicht <code>null</code> sein
*
* @return Von-Straßenknoten zu einer gegebenen Straßennummer, kann
* <code>null</code> sein
*/
public String getVonStrassenKnoten(final Strasse strasse,
final AttTmcRichtung richtung) {
public String getVonStrassenKnoten(final Strasse strasse, final AttTmcRichtung richtung) {
return getVonStrassenKnoten(strasse,
richtung == AttTmcRichtung.ZUSTAND_1_POSITIV
? AttRdsTMCRichtung.ZUSTAND_0_POSITIV
richtung == AttTmcRichtung.ZUSTAND_1_POSITIV ? AttRdsTMCRichtung.ZUSTAND_0_POSITIV
: AttRdsTMCRichtung.ZUSTAND_1_NEGATIV);
}
/**
* Liefert den Namen des Nach-Straßenknotens zu einer gegebenen Straße
* zurück.
* Liefert den Namen des Nach-Straßenknotens zu einer gegebenen Straße zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Straßenrichtung, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Straßenrichtung, darf nicht <code>null</code> sein
*
* @return Nach-Straßenknoten zu einer gegebenen Straßennummer, kann
* <code>null</code> sein
*/
public String getNachStrassenKnoten(final Strasse strasse,
final AttRdsTMCRichtung richtung) {
public String getNachStrassenKnoten(final Strasse strasse, final AttRdsTMCRichtung richtung) {
ensureInit();
assert strasse != null;
assert richtung != null;
final String nachStrassenKnoten = (richtung
.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV.getValue())
final String nachStrassenKnoten = (richtung.getValue() == AttRdsTMCRichtung.ZUSTAND_0_POSITIV.getValue())
? nachStrassenKnotenMap.get(strasse)
: vonStrassenKnotenMap.get(strasse);
if (nachStrassenKnoten != null && !"".equals(nachStrassenKnoten)) {
......@@ -681,27 +607,21 @@ public class NetzCache extends AbstractCache {
}
/**
* Liefert den Namen des Nach-Straßenknotens zu einer gegebenen Straße
* zurück.
* Liefert den Namen des Nach-Straßenknotens zu einer gegebenen Straße zurück.
*
* @param strasse
* die Straße, darf nicht <code>null</code> sein
* @param richtung
* die Straßenrichtung, darf nicht <code>null</code> sein
* @param strasse die Straße, darf nicht <code>null</code> sein
* @param richtung die Straßenrichtung, darf nicht <code>null</code> sein
*
* @return Nach-Straßenknoten zu einer gegebenen Straßennummer, kann
* <code>null</code> sein
*/
public String getNachStrassenKnoten(final Strasse strasse,
final AttTmcRichtung richtung) {
public String getNachStrassenKnoten(final Strasse strasse, final AttTmcRichtung richtung) {
return getNachStrassenKnoten(strasse,
richtung == AttTmcRichtung.ZUSTAND_1_POSITIV
? AttRdsTMCRichtung.ZUSTAND_0_POSITIV
richtung == AttTmcRichtung.ZUSTAND_1_POSITIV ? AttRdsTMCRichtung.ZUSTAND_0_POSITIV
: AttRdsTMCRichtung.ZUSTAND_1_NEGATIV);
}
private Collection<SystemObject> resolveSystemObjects(
final Collection<? extends SystemObjekt> objekte) {
private Collection<SystemObject> resolveSystemObjects(final Collection<? extends SystemObjekt> objekte) {
final ArrayList<SystemObject> objects = new ArrayList<>(objekte.size());
for (final SystemObjekt objekt : objekte) {
objects.add(objekt.getSystemObject());
......
......@@ -26,7 +26,7 @@
package de.bsvrz.sys.funclib.bitctrl.interpreter.logik;
import java.util.List;
import java.util.*;
import com.bitctrl.i18n.Messages;
......@@ -44,13 +44,13 @@ import de.bsvrz.sys.funclib.bitctrl.interpreter.Operator;
*/
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. */
......@@ -68,227 +68,79 @@ public class LogikHandler extends Handler {
@Override
public Object perform(Operator operator, List<?> operanden) {
if (operator == null
|| !validiereHandler(operator, operanden).isValid()) {
throw new InterpreterException(
Messages.get(InterpreterMessages.HandlerNotFound));
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(Operator operator, List<?> 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:
}
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;
}
}
boolean anzahlOk = validiereAnzahl(operator, operanden);
boolean typOk = validiereTyp(operanden);
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);
}
/**
* 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());
}
/**
* 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();
private static boolean validiereAnzahl(Operator operator, List<?> operanden) {
if (UND.equals(operator) || ODER.equals(operator)) {
return operanden.size() >= 2;
} else if (NICHT.equals(operator)) {
return operanden.size() == 1;
} else if (IMPLIKATION.equals(operator)) {
return operanden.size() == 2;
} else {
if (operand.getZugehoerigkeit() > wert) {
wert = operand.getZugehoerigkeit();
}
}
return false;
}
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);
private static boolean validiereTyp(List<?> operanden) {
return operanden.stream()
.map(o -> o instanceof LogischerWert)
.reduce(Boolean::logicalAnd)
.orElse(false);
}
return new LogischerWert(wert);
protected LogischerWert und(LogischerWert... operanden) {
return und(Arrays.asList(operanden));
}
/**
* 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;
protected LogischerWert und(Collection<LogischerWert> operanden) {
return operanden.stream()
.map(LogischerWert::get)
.reduce(Boolean::logicalAnd)
.map(LogischerWert::of)
.get();
}
if (operand.getZugehoerigkeit() < wert) {
wert = operand.getZugehoerigkeit();
protected LogischerWert oder(LogischerWert... operanden) {
return oder(Arrays.asList(operanden));
}
}
}
if (boolWert) {
// XXX assert eventuell anders verwenden
assert wert != null && (wert == 1 || wert == 0);
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,7 +50,7 @@ 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;
}
......@@ -59,7 +59,7 @@ public class LogischesSymbol implements Variable {
* Gibt immer {@code null} zur&uuml;ck, da dies ein Terminalsymbol ist.
*/
@Override
public List<Ausdruck> getNachfolger() {
public List<Ausdruck<?>> getNachfolger() {
return null;
}
......@@ -70,13 +70,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;
public static final LogischerWert of(final boolean wert) {
return wert ? WAHR : FALSCH;
}
return 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();
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;
}
/**
* 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;
}
/**
* 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;
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,7 +33,7 @@ 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
*/
......@@ -51,17 +51,7 @@ public class LogischesLiteral implements Literal<LogischerWert> {
* 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,11 +61,7 @@ public class LogischesLiteral implements Literal<LogischerWert> {
* Wert
*/
public LogischesLiteral(final LogischerWert wert) {
if (wert.isBoolWert()) {
this.wert = new LogischerWert(wert.getBoolWert());
} else {
this.wert = new LogischerWert(wert.getZugehoerigkeit());
}
this.wert = wert;
}
/**
......
......@@ -51,7 +51,7 @@ public final class TestInterpreter {
LogischerWert wert = (LogischerWert) ausdruck.interpret(kontext);
assertTrue(wert.getBoolWert());
assertTrue(wert.get());
}
}