/*
 * $Id: VKCDBCleaner.java,v 1.14 2006/07/12 12:21:55 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: VKCDBCleaner.java,v $
 * Revision 1.14  2006/07/12 12:21:55  marbobo
 * + Bugfix
 *
 * Revision 1.13  2005/02/24 11:19:13  jonyp
 * *** empty log message ***
 *
 * Revision 1.12  2004/12/07 21:37:05  marbobo
 * + Statement auf PreparedStatement umgestellt
 *
 * Revision 1.11  2004/11/24 09:26:02  lawern
 * Hibernate ist VKC-Geschichte!
 *
 * Revision 1.10  2004/11/22 14:53:40  jonyp
 * delete osbsolote statement DBHelper.close() for resultset
 *
 * Revision 1.9  2004/11/10 15:02:49  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.8  2004/11/04 10:37:59  koppy
 * Logmessage geändert
 *
 * Revision 1.7  2004/06/27 17:28:26  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.6  2004/03/15 13:38:48  bigmac
 * getAllArchiveIds() aus GenericDB ausgelagert
 *
 * Revision 1.5  2004/02/09 13:19:35  bigmac
 * *** empty log message ***
 *
 * Revision 1.4  2003/12/18 16:59:47  koppy
 * Anpassung an geänderte DB SS
 *
 * Revision 1.3  2003/12/10 14:43:43  koppy
 * ID-Generierung auf UUID umgestellt
 *
 * Revision 1.2  2003/11/29 22:21:06  koppy
 * StackTrace Ausgabe über den VKCLogManager
 *
 * Revision 1.1  2003/11/21 14:46:36  koppy
 * Initiale Version
 *
 *
 */
package vkc.server.archive;

import java.sql.Connection;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import vkc.db.helper.DBHelper;
import vkc.db.serializer.VKCSysParameterSerializer;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.view.WebShare;

/**
 * VKCDBCleaner impementiert einen Cleaner, welcher das Datenlager
 * anhand der vorhandenen Dokumente in der VKC Datenbank aufräumt.
 * D.h. alle Dokumente, die nicht in der Datenbank vorhanden sind,
 * werden aus dem Datenlager gelöscht. Die zu löschenden Dateien
 * müssen dabei ein Mindestalter von "getMinimumAge()" haben.
 *
 * @author koppy
 */
public class VKCDBCleaner implements Cleaner {
	/**
	 * @see vkc.server.archive.Cleaner#cleanDataStore(vkc.server.archive.DataStore)
	 */
	public void cleanDataStore( DataStore ds ) {
		if ( ds == null) {
			throw new IllegalArgumentException( "dataStore must be not null!" );
		}

		VKCLogManager.infoLog( this, "Cleaning DataStore: " + ds.getStorageUrl() );

		long minimumAge = this.getMinimumAge();

		try {
			Set archiveIdsInDB = getAllArchiveIds();

			for ( Iterator it = ds.iterator(); it.hasNext(); ) {
				String archiveId = it.next().toString();

				if ( archiveIdsInDB.contains( archiveId ) ) {
					continue;
				} 

				// Nur Dateien löschen, die älter als
				// der vorgegebene Zeitraum sind
				if ( System.currentTimeMillis() - ds.getFile( archiveId ).lastModified() < minimumAge ) {
					VKCLogManager.debug( this, "Data for archiveId = " + archiveId + " to fresh for deletion!" );
					continue;
				}

				it.remove();
				VKCLogManager.infoLog( this, "Data for archiveId = " + archiveId + " deleted!" );
			}
			
			archiveIdsInDB.clear();
			archiveIdsInDB = null;
		} catch ( DBException e ) {
			VKCLogManager.errorLog( this, "", "Cleaning aborted due to DB-Exception!", e );
		} catch ( DataStoreException e ) {
			VKCLogManager.errorLog( this, "", "Cleaning aborted due to DataStoreException!", e );
		}
	}

	/**
	 * Gibt alle in der Datenbank referenzierten Archive IDs zurück
	 * @return
	 * @throws DBException
	 */
	private Set getAllArchiveIds() throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;
		PreparedStatement pStmt2 = null;
		ResultSet rs = null;
		ResultSet rs2 = null;
		Set ids = new HashSet();

		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement( "select archiveId from Documents where archiveId <> '0'" );
			rs = pStmt.executeQuery();
			
			while ( rs.next() ) {
				ids.add( rs.getString( "archiveId" ) );
			}

			pStmt2 = conn.prepareStatement( "select archiveId from AdditionalDocumentFormats where archiveId <> '0'" );
			rs2 = pStmt2.executeQuery();
			
			while ( rs2.next() ) {
				ids.add( rs2.getString( "archiveId" ) );
			}

			return ids;
		} catch ( Exception e ) {
			throw new DBException( e );
		} finally {
			DBHelper.close( rs );
			DBHelper.close( rs2 );
		    DBHelper.close( pStmt );
			DBHelper.close( pStmt2 );
			DBHelper.close( conn );
		}
	}

    /** 
     * (non-Javadoc)
     * @see vkc.server.archive.Cleaner#getMinimumAge()
     */
    public long getMinimumAge() {
        int defaultMinAgeMinutes = 30;
        
        try {
            return VKCSysParameterSerializer.retrieveIntValue( "ARCHIVE", "MinimumAge", defaultMinAgeMinutes ) * 60 * 1000L;
        } catch ( DBException e ) {
            VKCLogManager.errorLog( this, "", "Error while retrieving sysparameter: [ARCHIVE] MinimumAge", e );
            
            return defaultMinAgeMinutes * 60 * 1000L;
        }
    }

    /** 
     * (non-Javadoc)
     * @see vkc.server.archive.Cleaner#getCleaningPeriod()
     */
    public long getCleaningPeriod() {
        int defaultPeriodDays = 7;
        
        try {
            return VKCSysParameterSerializer.retrieveIntValue( "ARCHIVE", "CleaningPeriod", defaultPeriodDays ) * 24 * 3600 * 1000L;
        } catch ( DBException e ) {
            VKCLogManager.errorLog( this, "", "Error while retrieving sysparameter: [ARCHIVE] CleaningPeriod", e );
            
            return defaultPeriodDays * 24 * 3600 * 1000L;
        }
    }
}