package org.biomoby.registry.sync;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.biomoby.registry.sync.filtering.FilterRuleKeys;
import org.biomoby.registry.sync.filtering.ServiceFilter;
import org.biomoby.registry.sync.logging.MobySecondaryLogging;
import org.biomoby.shared.MobyException;

/**
 * The class <code>MobySecondaryExecuter</code> is the main class to start the synchronization process of a local
 * Biomoby central and a master central.<br>
 * The application checks whether the master repository has changed and then tries to apply all the changes to the local
 * repository.<br>
 * For detailed information about this procedure see <code>MobySynchronize</code>.
 * 
 * @author groscurt
 */
public class MobySyncExecuter {
    private static Logger logger = Logger.getLogger( MobySecondaryLogging.LOGGER_NAME );

    /**
     * Method to initialise the configuration values.<br>
     * The following steps are happening during the initialisation:
     * <ol>
     * <li>The configuration file is read, in which the values are stored as properties.</li>
     * 
     * <li>With the configuration information the <i>logger</i> is initialised by <code>MobySecondaryLoggin</code>.
     * The configuration provides the location of the logfile and the minimal level to determine whether a message is
     * loggable.</li>
     * 
     * <li>Also read from the configuration, the filter rules are set by <code>ServiceFilter</code>. These rules
     * affect if services shall be ignored by the local central for registration.</li>
     * 
     * </ol>
     * 
     * @param configurationFile
     *            a properties file storing the configuration values for the application
     * @throws IOException
     *             whether something failed during the parsing of the configuration fail
     * @throws MobyException
     *             whether the centrals could be initialised
     */
    private void doTheJob( String configurationFile ) throws IOException, MobyException {
        Properties configuration = new Properties();
        // loading the configuration
        configuration.load( new FileInputStream( configurationFile ) );

//        System.setProperty( "RDFagent.home", configuration.getProperty( "RDFagent.home" ) );

        // initialise the logger
        MobySecondaryLogging.initLogger( configuration.getProperty( "log.path" ), configuration
                .getProperty( "log.level" ) );

        logger.fine( "Initialise the filter rules" );
        // the filter rules are read
        initFilterRules( configuration );

        // initialise the centrals
        CentralFactory.init( configuration );

        // set a system property which is needed to deregister services
        // System.setProperty( "RDFagent.home", configuration.getProperty( "RDFagent.home" ) );

        logger.info( "Start the update" );

        // and start the update
        new MobySynchronizeImpl().updateRegistry( configuration );

        logger.info( "update process finished !" );
    }

    /**
     * Method to initialise the filter rules. Each rule is given as a regular expression to determine if a service shall
     * be excluded from the synchronisation process.<br>
     * One can define for the following options a regular expression:
     * <ol>
     * <li>authority</li>
     * <li>servicename</li>
     * <li>category</li>
     * <li>input</li>
     * <li>output</li>
     * <li>type</li>
     * </ol>
     * E.g. the expression <i>mpiz</i> in the authority field would ignore all services which have <i>mpiz</i> as
     * authority<br>
     * Or the expression <i>FASTA</i> in the service name field would ignore all services which have the phrase
     * <i>FASTA</i> (or <i>fasta</i>). See the configuration file for detailed information
     * 
     * @param configuration
     */
    private void initFilterRules( Properties configuration ) {
        ServiceFilter serviceFilter = ServiceFilter.getServiceFilter();
        serviceFilter.addFilterRule( FilterRuleKeys.Authority, configuration.getProperty( "filter.authority" ) );
        serviceFilter.addFilterRule( FilterRuleKeys.ServiceName, configuration.getProperty( "filter.service.name" ) );
        serviceFilter.addFilterRule( FilterRuleKeys.Category, configuration.getProperty( "filter.category" ) );
        serviceFilter.addFilterRule( FilterRuleKeys.Input, configuration.getProperty( "filter.input" ) );
        serviceFilter.addFilterRule( FilterRuleKeys.Output, configuration.getProperty( "filter.output" ) );
        serviceFilter.addFilterRule( FilterRuleKeys.Type, configuration.getProperty( "filter.type" ) );
    }

    public static void main( String[] args ) {
        try {
            if ( args.length == 0 ) {
                System.err.println( "No configuration file given ! The application terminates here" );
            }
            else {
                new MobySyncExecuter().doTheJob( args[ 0 ] );
            }
        }
        catch ( IOException e ) {
            logger.log( Level.SEVERE, "The configuration file could not been parsed: ", e );
        }
        catch ( MobyException e ) {
            logger.log( Level.SEVERE, "An error occured while updating: ", e );
        }
    }
}