/******************************************************************************* * Copyright (c) 2009, A. Kaufmann and Elexis * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * A. Kaufmann - initial implementation * *******************************************************************************/ package com.hilotec.elexis.pluginstatistiken.config; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import com.hilotec.elexis.pluginstatistiken.Datensatz; import com.hilotec.elexis.pluginstatistiken.PluginstatistikException; import com.hilotec.elexis.pluginstatistiken.schnittstelle.IDatenquelle; import com.hilotec.elexis.pluginstatistiken.schnittstelle.IDatensatz; import com.hilotec.elexis.pluginstatistiken.schnittstelle.ITabelle; /** * Einzelne Abfrage * * @author Antoine Kaufmann */ public class KonfigurationQuery { String title; String from; String fromAs; KonfigurationWhere where = null; List<String> colsName; List<String> colsSource; /** * Liste mit allen Joins dieser Abfrage */ List<Join> joins; /** * Klasse um einen Join in der Abfrage abzubilden * * @author Antoine Kaufmann */ public static class Join { enum JType { JOIN_INNER, } /** * Tabellenname */ String table; /** * Alias der Tabelle in der Abfrage */ String as; /** * Praedikat fuer den Join, oder null falls keines existiert */ KonfigurationWhere where; /** * Typ des Joins */ JType type; /** * Konstruktor fuer neuen Join * * @param table * Tabelle aus der die Daten fuer den Join kommen * @param as * Alias fuer die Tabelle in der Abfrage * @param w * Praedikat fuer den Join, oder null wenn keines existiert * @param typ * Typ des Joins (z.B. JOIN_INNER). */ public Join(String table, String as, KonfigurationWhere w, JType typ){ this.table = table; this.as = as; this.where = w; } /** * Tabellenname auslesen * * @return Tabellenname */ public String getTable(){ return table; } /** * Tabellenalias auslesen * * @return Tabellenalias */ public String getAs(){ return as; } /** * Praedikat des Joins auslesen * * @return Praedikat als Where-Klausel oder null */ public KonfigurationWhere getWhere(){ return where; } } /** * Neue Abfrage anlegen * * @param t * Titel der Abfrage */ public KonfigurationQuery(String t){ title = t; colsName = new ArrayList<String>(); colsSource = new ArrayList<String>(); joins = new LinkedList<Join>(); } /** * Quelltabelle setzen */ public void setFrom(String table, String as){ from = table; fromAs = as; } /** * Der Abfrage eine neue Spalte anfuegen * * @param name * Name der Spalte * @param source * Quelle fuer diese Spalte (fuer IDataAcees-Schnittstelle) */ public void addCol(String name, String source){ colsName.add(name); colsSource.add(source); } /** * Liste mit den Namen aller Spalten */ public List<String> getColNames(){ return colsName; } /** * Quellen der Spalten in Liste zurueckgeben * * @return */ public List<String> getColSources(){ return colsSource; } /** * Where-Klausel fuer diese Abfrage setzen */ public void setWhere(KonfigurationWhere w){ where = w; } /** * Weiteren Join zur Abfrage hinzufuegen * * @param j * Der neue Join */ public void addJoin(Join j){ joins.add(j); } /** * @return Titel dieser Abfrage */ public String getTitle(){ return title; } /** * Tabelle anhand des Identifiers in der Form Plugin:Tabelle suchen * * @param name * Bezeichner fuer die Tabelle * * @return Tabelle * @throws PluginstatistikException */ private ITabelle getTabelle(String name) throws PluginstatistikException{ String fromParts[] = name.split(":"); if (fromParts.length < 2) { throw new PluginstatistikException( "Abfrage: Tabellenbezeichner ungueltig formatiert: '" + from + "'"); } String dqPart = fromParts[0]; String tabPart = fromParts[1]; IDatenquelle dq = Konfiguration.getInstance().getDatenquelle(dqPart); if (dq == null) { throw new PluginstatistikException("Abfrage: Unbekannte Datenquelle: '" + dqPart + "'"); } ITabelle t = dq.getTabelle(tabPart); if (t == null) { throw new PluginstatistikException("Abfrage: Unbekannte Tabelle: '" + tabPart + "' (in " + " Datenquelle '" + dqPart + "')"); } return t; } /** * Daten heraussuchen * * @param startDatum * Startdatum des angegebenen Bereichs * @param endDatum * Enddatum des angegebenen Bereichs * @param monitor * Archie-ProgressMonitor der es ermoeglcht, dem Benutzer den auktuellen Status der * Abfrage angezeigt werden kann. * * @return Liste mit den gefundenen Datensaetzen * @throws PluginstatistikException */ public List<Datensatz> getDaten(String startDatum, String endDatum, IProgressMonitor monitor) throws PluginstatistikException{ List<Datensatz> data = new LinkedList<Datensatz>(); Map<String, String> parameters = new HashMap<String, String>(); parameters.put("startdatum", startDatum); parameters.put("enddatum", endDatum); monitor.beginTask("Initialisiere Datenquelle", 1); ITabelle from = getTabelle(this.from); monitor.done(); monitor.beginTask("Sammle Datensaetze", 1); List<IDatensatz> dsl = from.getDatensaetze(); monitor.done(); monitor.beginTask("Verarbeite Datensätze", dsl.size()); for (IDatensatz fromDs : dsl) { Datensatz ds = new Datensatz(this, startDatum, endDatum); for (int i = 0; i < colsName.size(); i++) { ds.addSpalte(colsName.get(i), colsSource.get(i)); } ds.addIntDs(this.fromAs, fromDs); joinTable(ds, joins, data); monitor.worked(1); } monitor.done(); return data; } /** * Gejointe Tabellen fuer einen einzelnen Datensatz zusammensammeln. Der uebergebene Datensatz * wird jeweils kopiert und dann die neue Tabelle angehaengt. Die Funktion arbeitet rekursiv die * Liste joinsTodo ab. Bei jedem Aufruf wird ein Eintrag entfernt bis die Liste leer ist. Die * Datensaetze, die durch die Kette von Joins entstehen werden letztendlich in der Liste result * abgelegt. * * @param ds * Datensatz auf den die Tabellen gejoint werden sollen. * @param joinsTodo * Liste mit den noch ausstehenden Joins (wird nicht veraendert) * @param result * Liste in der die Datensaetze, die sich am Ende ergeben, abgelegt werden sollen. * @throws PluginstatistikException */ private void joinTable(Datensatz ds, final List<Join> joinsTodo, List<Datensatz> result) throws PluginstatistikException{ if ((joinsTodo == null) || (joinsTodo.size() == 0)) { if ((where == null) || (where.matches(ds))) { result.add(ds); } } else { Join j = joinsTodo.get(0); LinkedList<Join> newTodo = null; if (joinsTodo.size() > 1) { newTodo = new LinkedList<Join>(joinsTodo); newTodo.remove(0); } ITabelle tab = getTabelle(j.getTable()); List<IDatensatz> dsl = tab.getDatensaetze(); for (IDatensatz ids : dsl) { Datensatz tmpDs = new Datensatz(ds); tmpDs.addIntDs(j.getAs(), ids); if (j.getWhere().matches(tmpDs)) { joinTable(tmpDs, newTodo, result); } } } } }