001 /*
002 * Created on 17.04.2004
003 */
004 package de.fub.tip.datenbank.logik;
005
006 import java.sql.Connection;
007 import java.sql.PreparedStatement;
008 import java.sql.ResultSet;
009 import java.sql.SQLException;
010 import java.sql.Statement;
011 import java.util.ArrayList;
012 import java.util.Collection;
013 import java.util.Vector;
014
015 import javax.sql.DataSource;
016
017 import org.apache.log4j.Logger;
018
019 import de.fub.tip.datenanzeige.beans.HtmlCheckboxDarstellungBean;
020 import de.fub.tip.datenanzeige.container.SightGruppeVOContainer;
021 import de.fub.tip.datenanzeige.ormapper.SightGruppeVO;
022 import de.fub.tip.datenanzeige.ormapper.UserdataVO;
023 import de.fub.tip.datenbank.factory.LogicObject;
024 import de.fub.tip.exceptions.NoDataFoundException;
025 import de.fub.tip.exceptions.NoUserLoggedInException;
026
027 /**
028 * Sinn: stellt die Logik zur Verfügung, mit der Sehenswürdigkeitsgruppen
029 * bearbeitet werden können. Das sind Funktionen:
030 * <ul>
031 * <li>zur Anzeige aller Sehenswürdigkeitsgruppen des Systems</li>
032 * <li>zur Anzeige aller nicht abonnierten Sehenswürdigkeitsgruppen
033 * eines Benutzers</li>
034 * <li>zur Anzeige aller abonnierten Sehenswürdigkeitsgruppen eines
035 * Benutzers</li>
036 * <li>zur Bearbeitung und Anzeige des Sehenswürdigkeitsprofils</li>
037 * <li>zur Speicherung der Änderungen am Profil in der Datenbank</li>
038 * </ul>
039 *
040 * vergleichbar zum Themenbearbeiter:
041 * @see de.fub.tip.datenbank.logik.ThemenBearbeiter
042 *
043 * @author hirsch, 17.04.2004
044 * @version 2004-04-22
045 * $Id: SightGruppenBearbeiter.java,v 1.24 2004/06/10 12:05:24 hirsch Exp $
046 *
047 */
048 public class SightGruppenBearbeiter implements LogicObject {
049 /** Logger zur Fehlersuche */
050 private static Logger logger =
051 Logger.getLogger(SightGruppenBearbeiter.class);
052 /** Datenquelle mit der der <code>SightGruppenBearbeiter</code>
053 * arbeitet */
054 private DataSource datasource = null;
055
056 /**
057 * Standardkonstruktor, der einen SightGruppenBearbeiter erzeugt
058 * @param datasource Datenquelle
059 */
060 public SightGruppenBearbeiter(DataSource datasource) {
061 this.datasource = datasource;
062 logger.info("SightGruppenBearbeiter initialized.");
063 } // end of Konstruktor
064
065 /**
066 * gibt alle verfügbaren Sehenswürdigkeitsgruppen zurück
067 *
068 * @return container mit <code>SightGruppeVO</code>-Objekten
069 *
070 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
071 * @throws SQLException bei Datenbankproblemen
072 */
073 public SightGruppeVOContainer getAllSightGroups()
074 throws NoDataFoundException,
075 SQLException {
076
077 SightGruppeVO gruppe = null;
078 String sql = "SELECT * FROM sight_objects ORDER BY name ";
079
080 // die einzelnen Container stets methodenlokal verwalten, da sonst immer
081 // auch die Daten im Container bleiben, die aus anderen Methodenaufrufen
082 // stammen.
083 SightGruppeVOContainer ergebnis = new SightGruppeVOContainer();
084
085 Connection con = this.datasource.getConnection();
086 Statement statement = con.createStatement();
087 ResultSet rs = statement.executeQuery(sql);
088
089 // erste den Erfolgsfall bearbeiten
090 if( rs != null) {
091 while(rs.next()) {
092 // SightGruppeVO zusammenbasteln
093 gruppe = new SightGruppeVO();
094
095 // falls es Unregelmässigkeiten beim Laden der Daten aus der DB
096 // gibt, sollen diese *nie* an STRUTS weitergeleitet werden
097 try {
098 gruppe.setActive(new Boolean(rs.getBoolean("active")));
099 gruppe.setDescription(rs.getString("description"));
100 gruppe.setId(new Integer(rs.getInt("so_id")));
101 gruppe.setName(rs.getString("name"));
102
103 } catch(Exception e) {
104 // Probleme gibt es hier beispielsweise bei NULL-Werten!
105 // Diese werden einfach gefangen und generieren keinen Fehler
106 logger.error("SightGruppenBearbeiter.getAllTopics(): "+
107 e + " - Ausnahme beim Parsen der Daten! " +
108 e.getLocalizedMessage());
109 } // end of catch
110
111 // zur Ergebnismenge hinzufügen und probeweise loggen
112 ergebnis.add(gruppe);
113 gruppe.logObject(logger);
114 } // end of while
115 } // end if
116
117 // Schliessen/Freigabe der Datenbankverbindung
118 try {
119 if( con != null ) con.close();
120 logger.debug("SightGruppenBearbeiter.getAllTopics(): " +
121 "DB-Con geschlossen.");
122 } catch (SQLException e) {
123 logger.debug("SightGruppenBearbeiter.getAllTopics(): " +
124 "geschachtelte Ausnahme beim Schliessen der " +
125 "DB-Verbindung.");
126 } // end of try
127
128 // keine Themen da ?
129 if( rs == null) {
130 throw new NoDataFoundException("SightGruppenBearbeiter." +
131 "getAllTopics(): Ausnahme - keine Themen in der DB zu finden.");
132 } else {
133 return ergebnis;
134 } // end if
135 } // end of getAllSightGroups
136
137 /**
138 * gibt alle abonnierten Themen des angemeldeten Benutzers zurück
139 *
140 * @param user angemeldeter Benutzer
141 *
142 * @return container mit <code>SightGruppeVO</code>-Objekten
143 *
144 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
145 * @throws SQLException bei Datenbankproblemen
146 * @throws NoUserLoggedInException falls keine Anmeldung erfolgt ist
147 */
148 public SightGruppeVOContainer getSelectedSightGroupsForUser(
149 UserdataVO user)
150 throws NoDataFoundException,
151 SQLException,
152 NoUserLoggedInException {
153
154 if ( user == null ) throw new NoUserLoggedInException("Sight" +
155 "GruppenBearbeiter.getSelectedTopicsForUser(): " +
156 "ungültiger User übergeben");
157
158 // die abonnierten Sachen müssen aus der Tabelle profile geholt
159 // werden, die zu jedem Benutzer die IDs der Objekte speichert,
160 // die im jeweiligen Profil enthalten sind
161 String sql = "SELECT so.* " +
162 "FROM user_int_obj int, profile p, sight_objects so " +
163 "WHERE p.pid = int.pid AND p.udid = ? AND so.so_id=int.o_id " +
164 "ORDER BY so.name ";
165
166 SightGruppeVO gruppe = null;
167
168 // die einzelnen Container stets methodenlokal verwalten, da sonst immer
169 // auch die Daten im Container bleiben, die aus anderen Methodenaufrufen
170 // stammen.
171 SightGruppeVOContainer ergebnis = new SightGruppeVOContainer();
172
173 Connection con = this.datasource.getConnection();
174 PreparedStatement prepStatement = con.prepareStatement(sql);
175 prepStatement.setInt(1, user.getId().intValue());
176 ResultSet rs = prepStatement.executeQuery();
177
178 // erste den Erfolgsfall bearbeiten
179 if( rs != null) {
180 while(rs.next()) {
181 // SightGruppeVO zusammenbasteln
182 gruppe = new SightGruppeVO();
183
184 // falls es Unregelmässigkeiten beim Laden der Daten aus der DB
185 // gibt, sollen diese *nie* an STRUTS weitergeleitet werden
186 try {
187 gruppe.setActive(new Boolean(rs.getBoolean("active")));
188 gruppe.setDescription(rs.getString("description"));
189 gruppe.setId(new Integer(rs.getInt("so_id")));
190 gruppe.setName(rs.getString("name"));
191
192 } catch(Exception e) {
193 // Probleme gibt es hier beispielsweise bei NULL-Werten!
194 // Diese werden einfach gefangen und generieren keinen Fehler
195 logger.error("SightGruppenBearbeiter.getSelectedSight" +
196 "GroupsForUser(): "+ e + " - Ausnahme beim Parsen der Daten! " +
197 e.getLocalizedMessage());
198 } // end of catch
199
200 // zur Ergebnismenge hinzufügen und probeweise loggen
201 ergebnis.add(gruppe);
202 gruppe.logObject(logger);
203 } // end of while
204 } // end if
205
206 // Schliessen/Freigabe der Datenbankverbindung
207 try {
208 if( con != null ) con.close();
209 logger.debug("SightGruppenBearbeiter.getSelectedSight" +
210 "GroupsForUser(): DB-Con geschlossen.");
211 } catch (SQLException e) {
212 logger.debug("SightGruppenBearbeiter.getSelectedSight" +
213 "GroupsForUser(): geschachtelte Ausnahme beim Schliessen der "+
214 "DB-Verbindung.");
215 } // end of try
216
217 // keine Gruppen da ?
218 if( rs == null) {
219 throw new NoDataFoundException("SightGruppenBearbeiter." +
220 "getSelectedSightGroupsForUser(): Ausnahme - " +
221 "keine Gruppen in der DB zu finden.");
222 } else {
223 return ergebnis;
224 } // end if
225 } // end of getSelectedSightGroupsForUser
226
227
228 /**
229 * gibt alle nicht abonnierten Sehenswürdigkeitsgruppen
230 * des angemeldeten Benutzers zurück
231 *
232 * @param user angemeldeter Benutzer
233 *
234 * @return container mit <code>SightGruppeVO</code>-Objekten
235 *
236 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
237 * @throws SQLException bei Datenbankproblemen
238 * @throws NoUserLoggedInException falls keine Anmeldung erfolgt ist
239 */
240 public SightGruppeVOContainer getNotSelectedSightGroupsForUser(
241 UserdataVO user)
242 throws NoDataFoundException,
243 SQLException,
244 NoUserLoggedInException {
245
246 if ( user == null ) throw new NoUserLoggedInException(
247 "SightGruppenBearbeiter.getNotSelectedSightGroupsForUser(): "+
248 "ungültiger User übergeben");
249
250 // Die Abfrage der nicht abonnierten Gruppen geht so, dass alle die
251 // Gruppen selektiert werden, deren ID nicht in der positiv-Menge der
252 // Gruppen enthalten ist.
253 String sql = "SELECT so.* " +
254 "FROM sight_objects so " +
255 "WHERE so_id NOT IN (SELECT so.so_id " +
256 "FROM user_int_obj int, profile p, sight_objects so "+
257 "WHERE p.pid = int.pid AND p.udid = ? AND so.so_id=int.o_id) " +
258 "ORDER BY so.name";
259
260 SightGruppeVO gruppe = null;
261
262 // die einzelnen Container stets methodenlokal verwalten, da sonst immer
263 // auch die Daten im Container bleiben, die aus anderen Methodenaufrufen
264 // stammen.
265 SightGruppeVOContainer ergebnis = new SightGruppeVOContainer();
266
267 Connection con = this.datasource.getConnection();
268 PreparedStatement prepStatement = con.prepareStatement(sql);
269 prepStatement.setInt(1, user.getId().intValue());
270 ResultSet rs = prepStatement.executeQuery();
271
272 // erste den Erfolgsfall bearbeiten
273 if( rs != null) {
274 while(rs.next()) {
275 // SightGruppeVO zusammenbasteln
276 gruppe = new SightGruppeVO();
277
278 // falls es Unregelmässigkeiten beim Laden der Daten aus der DB
279 // gibt, sollen diese *nie* an STRUTS weitergeleitet werden
280 try {
281 gruppe.setActive(new Boolean(rs.getBoolean("active")));
282 gruppe.setDescription(rs.getString("description"));
283 gruppe.setId(new Integer(rs.getInt("so_id")));
284 gruppe.setName(rs.getString("name"));
285
286 } catch(Exception e) {
287 // Probleme gibt es hier beispielsweise bei NULL-Werten!
288 // Diese werden einfach gefangen und generieren keinen Fehler
289 logger.error("SightGruppenBearbeiter.getNotSelectedSight" +
290 "GroupsForUser(): "+ e +
291 " - Ausnahme beim Parsen der Daten! " +
292 e.getLocalizedMessage());
293 } // end of catch
294
295 // zur Ergebnismenge hinzufügen und probeweise loggen
296 ergebnis.add(gruppe);
297 gruppe.logObject(logger);
298 } // end of while
299 } // end if
300
301 // Schliessen/Freigabe der Datenbankverbindung
302 try {
303 if( con != null ) con.close();
304 logger.debug("SightGruppenBearbeiter.getNotSelectedSight" +
305 "GroupsForUser(): DB-Con geschlossen.");
306 } catch (SQLException e) {
307 logger.debug("SightGruppenBearbeiter.getNotSelectedSight" +
308 "GroupsForUser(): geschachtelte Ausnahme beim Schliessen " +
309 "der DB-Verbindung.");
310 } // end of try
311
312 // keine Gruppen da ?
313 if( rs == null) {
314 throw new NoDataFoundException("SightGruppenBearbeiter." +
315 "getNotSelectedSightGroupsForUser(): Ausnahme - " +
316 "keine Gruppen in der DB zu finden.");
317 } else {
318 return ergebnis;
319 } // end if
320 } // end of getNotSelectedSightGroupsForUser
321
322
323 /**
324 * gibt alle Sehenswürdigkeitsgruppen des angemeldeten Benutzers zurück.
325 * Die View kann dann je nachdem wie das Attribut aboStatus gesetzt ist,
326 * entscheiden, ob ein Häkchen für "abonniert"
327 * oder keines für "nicht abonniert" gesetzt wird.
328 *
329 * @param user angemeldeter Benutzer
330 *
331 * @return container mit <code>SightGruppeVO</code>-Objekten
332 *
333 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
334 * @throws SQLException bei Datenbankproblemen
335 * @throws NoUserLoggedInException falls keine Anmeldung erfolgt ist
336 */
337 public SightGruppeVOContainer getViewableSightGroupProfile(
338 UserdataVO user)
339 throws NoDataFoundException,
340 SQLException,
341 NoUserLoggedInException {
342
343 SightGruppeVO sgruppe = null;
344
345 // Arbeitsprinzip
346 // 1. alle restlichen Dinge holen und deren IDs speichern.
347 SightGruppeVOContainer alle = this.getAllSightGroups();
348 SightGruppeVOContainer ergebnis = null;
349
350 // 2. alle abonnierten Objekte des Users holen und deren IDs
351 // in einen Vector speichern
352 SightGruppeVOContainer abonnierte =
353 this.getSelectedSightGroupsForUser(user);
354 Vector nurIds = new Vector();
355
356 while( abonnierte.hasNext() ) {
357 nurIds.add( ((SightGruppeVO) abonnierte.next() ).getId());
358 } // end of while
359 nurIds.trimToSize();
360
361 // wenn der Nutzer keine Gruppen abonniert hat, kann einfach
362 // der Container mit allen Sehenswürdigkeitsgruppen
363 // *ohne Modifikationen* zurückgegeben werden,
364 // da die aboStatus-Werte standardmässig
365 // auf falsch gesetzt sind.
366 if(nurIds.size() == 0) return alle;
367
368 // 3. alle IDs auslesen und diesen Container durchklappern und
369 // für jedes gelesene Objekte - je nach Zugehörigkeit zu Schritt 1 oder
370 // 2 - den aboStatus setzen.
371 ergebnis = new SightGruppeVOContainer();
372
373 while( alle.hasNext() ) {
374 sgruppe = (SightGruppeVO) alle.next();
375
376 // ist Gruppe abonniert ?
377 if ( nurIds.contains(sgruppe.getId()) ) {
378 sgruppe.setAboStatus(new Boolean(true));
379 logger.debug("aboPositiv: " + sgruppe);
380 } // end if
381 ergebnis.add(sgruppe);
382
383 } // end of while
384
385 // 4. Ergebnis zurückgeben
386 return ergebnis;
387 } // end of getViewableSightGroupProfile
388
389 /**
390 * schreibt das neue Profil für <code>SightGruppeVO</code>-Objekte
391 * in die Datenbank.<br>
392 * Am Beginn der Transaktion wird das komplett bestehende
393 * <code>SightGruppeVO</code>-Profil des Benutzers gelöscht und
394 * der Inhalt des Containers als neues Profil geschrieben.<br>
395 * Dabei sind im Container jeweils nur die Objekte von Interesse, die den
396 * <code>aboStatus</code> gesetzt haben.
397 *
398 * @param user angemeldeter Benutzer
399 *
400 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
401 * @throws SQLException bei Datenbankproblemen
402 * @throws NoUserLoggedInException falls keine Anmeldung erfolgt ist
403 */
404 public void setSightGroupProfileForUser(UserdataVO user,
405 String[] changes)
406 throws NoDataFoundException,
407 SQLException,
408 NoUserLoggedInException {
409
410 if ( user == null ) throw new NoUserLoggedInException(
411 "SightGruppenBearbeiter.setSightGroupProfileForUser(): " +
412 "ungültiger User übergeben");
413
414 // Prinzip:
415 // 1. Containerelemente checken und in einen neuen Container alle
416 // die schreiben, die aboStatus true haben; also in die DB kommen
417 // 1a. BEGIN WORK
418 // 2. alle Elemente aus der DB zum Profil des Users löschen!
419 // 3. Container hinzufügen mit einer Schleife und INSERT INTO ...
420 // 4. COMMIT o. Rollback
421
422 logger.info("SightGruppenBearbeiter.setSightGroupProfileForUser() " +
423 "startet ...");
424
425 // Auf Grund der Tabellenstruktur wird etwas kompliziert eingefügt ....
426 String loesche = "DELETE FROM user_int_obj WHERE pid= ? ";
427 String profilId = "SELECT pid FROM profile WHERE udid=? ";
428 String fuegeAn = "INSERT INTO user_int_obj (pid, o_id) VALUES (?, ?) ";
429
430 // lokale Variablen
431 // ProfilID des aktuellen Benutzers
432 Integer pid = null;
433 Connection con = null;
434 Statement stat = null;
435 PreparedStatement prepStat = null;
436 ResultSet rs = null;
437
438 try {
439 con = this.datasource.getConnection();
440 stat = con.createStatement();
441
442 // 1. ausserhalb der Transaktion die ProfilID lesen
443 logger.debug("ProfilID lesen");
444 prepStat = con.prepareStatement(profilId);
445 prepStat.setInt(1, user.getId().intValue());
446 rs = prepStat.executeQuery();
447 if ( rs != null && rs.next()) {
448 pid = new Integer(rs.getInt("pid"));
449 } else {
450 throw new SQLException("konnte ProfilID des" +
451 " Benutzers "+ user.getId()+" nicht auslesen!");
452 } // end if
453
454 // 2. Transaktion anfangen, bestehende Daten löschen,
455 // neue hinzufügen
456 logger.debug("Transaktion anfangen ...für Profil "+ pid);
457 con.setAutoCommit(false);
458 stat.execute("BEGIN WORK");
459
460 // 2a. löschen der bestehenden Einträge
461 prepStat = con.prepareStatement(loesche);
462 prepStat.setInt(1, pid.intValue());
463 logger.debug(prepStat.executeUpdate() +
464 " Profileinträge gelöscht.");
465
466 // 2b. jetzt den Inhalt der Collection in die DB schreiben
467 prepStat = con.prepareStatement(fuegeAn);
468
469 // ist NULL, wenn der Benutzer alles deaktiviert hat
470 if ( changes != null ) {
471 // im BatchModus die ganzen Sachen hinzufügen
472 for ( int i = 0; i < changes.length; i++ ) {
473 prepStat.setInt(1, pid.intValue());
474 // die Collection enthält nur die abonnierten IDs!
475 prepStat.setString(2, changes[i]);
476 prepStat.addBatch();
477 } // end for
478
479 // Loslegen und für Ausgabe umbauen
480 int[] gespeichert = prepStat.executeBatch();
481 String erg = "";
482 for ( int i = 0; i < gespeichert.length; i++) {
483 erg+=gespeichert[i]+ "+";
484 } // end of for
485 logger.debug(erg+
486 " SightGroupVO-Datensätze erfolgreich eingefügt");
487 } // end if
488
489 // Transaktion beenden
490 logger.debug("COMMIT machen ...");
491 stat.execute("COMMIT");
492
493 } catch (SQLException e) {
494 logger.error(
495 "SightGruppenBearbeiter.setSightGroupProfileForUser():"+
496 " Fehler - "+e + ", "+ e.getLocalizedMessage());
497
498 try {
499 logger.error("SightGruppenBearbeiter." +
500 "setSightGroupProfileForUser(): ROLLBACK gemacht!");
501 stat.execute("ROLLBACK");
502 } catch (SQLException e1) {
503 logger.error("SightGruppenBearbeiter." +
504 "setSightGroupProfileForUser()-SQLException: " +
505 "verschachtelte Ausnahme beim ROLLBACK aufgetreten!");
506 } // end of try
507
508 } catch(Exception e) {
509 // Damit auf keinen Fall auf den Webseiten Fehler angezeigt werden,
510 // die durch das Logging verursacht wurden ....
511 logger.error("SightGruppenBearbeiter." +
512 "setSightGroupProfileForUser(): " +
513 "Problem - "+e + ", " + e.getLocalizedMessage());
514
515 try {
516 logger.error("SightGruppenBearbeiter." +
517 "setSightGroupProfileForUser(): ROLLBACK gemacht!");
518 stat.execute("ROLLBACK");
519 } catch (SQLException e1) {
520 logger.error("SightGruppenBearbeiter." +
521 "setSightGroupProfileForUser()-SQLException: " +
522 "verschachtelte Ausnahme beim ROLLBACK aufgetreten!");
523 } // end of try
524
525 } // end of try
526
527 // Datenbankverbindung immer korrekt schliessen
528 finally {
529 try {
530 if(con!=null) con.close();
531 logger.debug("SightGruppenBearbeiter." +
532 "setSightGroupProfileForUser(): DB-Con geschlossen.");
533 } catch (SQLException e1) {
534 logger.error("SightGruppenBearbeiter." +
535 "setSightGroupProfileForUser(): " + e1 +
536 "Fehler beim Schliessen der DB-Con: " +
537 e1.getLocalizedMessage());
538 } // end of catch
539 } // end of finally
540
541 logger.info("SightGruppenBearbeiter.setSightGroupProfileForUser() " +
542 "erfolgreich beendet.");
543 } // end of setSightGroupProfileForUser
544
545
546 /**
547 * gibt alle Sehenswürdigkeitsgruppen des angemeldeten Benutzers zurück.
548 * Die View kann dann je nachdem wie das Attribut aboStatus gesetzt ist,
549 * entscheiden, ob ein Häkchen für "abonniert"
550 * oder keines für "nicht abonniert" gesetzt wird.
551 *
552 * @param user angemeldeter Benutzer
553 *
554 * @return collection
555 * <code>HtmlCheckboxDarstellungBean</code>-Objekten
556 *
557 * @throws NoDataFoundException wenn keine Einträge vorhanden sind
558 * @throws SQLException bei Datenbankproblemen
559 * @throws NoUserLoggedInException falls keine Anmeldung erfolgt ist
560 */
561 public Collection getBeanSightGroupProfile(UserdataVO user)
562 throws NoDataFoundException,
563 SQLException,
564 NoUserLoggedInException {
565
566 SightGruppeVOContainer container =
567 getViewableSightGroupProfile(user);
568
569 ArrayList list = new ArrayList(container.size());
570 SightGruppeVO sightgruppe = null;
571 HtmlCheckboxDarstellungBean bean = null;
572
573 // Umwandeln des Containers in eine Collection<Bean>
574 while(container.hasNext()) {
575 try {
576 sightgruppe = ((SightGruppeVO) container.next());
577 bean = new HtmlCheckboxDarstellungBean(sightgruppe);
578 list.add(bean);
579 } catch (ClassCastException e) {
580 logger.debug(e + "," + sightgruppe);
581 }
582 } // end of while
583
584 logger.debug("SightGruppenProfil in Liste mit " + list.size() +
585 " Elementen umgewandelt.");
586 return list;
587 } // end of getBeanSightGroupProfile
588 } // end of class
|