/* * Copyright 2010 Research Studios Austria Forschungsgesellschaft mBH * * This file is part of easyrec. * * easyrec is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * easyrec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with easyrec. If not, see <http://www.gnu.org/licenses/>. */ package org.easyrec.plugin.cli; import com.google.common.collect.ObjectArrays; import org.apache.commons.cli.*; import org.easyrec.model.core.TenantVO; import org.easyrec.plugin.Executable; import org.easyrec.plugin.Plugin; import org.easyrec.plugin.generator.Generator; import org.easyrec.plugin.generator.GeneratorConfiguration; import org.easyrec.plugin.stats.GeneratorStatistics; import org.easyrec.plugin.util.Observer; import org.easyrec.service.core.TenantService; import org.easyrec.utils.spring.cli.AbstractDependencyInjectionSpringCLI; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import java.util.Date; import java.util.LinkedList; import java.util.List; /** * Abstract base class for implementing CLI utilities for {@link org.easyrec.plugin.generator.Generator}s. * <p><b>Company: </b> SAT, Research Studios Austria</p> <p><b>Copyright: </b> (c) 2007</p> <p><b>last * modified:</b><br/> $Author$<br/> $Date$<br/> $Revision$</p> * * @author Patrick Marschik */ public abstract class AbstractGeneratorCLI<GC extends GeneratorConfiguration, GS extends GeneratorStatistics> extends AbstractDependencyInjectionSpringCLI { // ------------------------------ FIELDS ------------------------------ private TenantService tenantService; // --------------------- GETTER / SETTER METHODS --------------------- /** * Spring injected tenant service. * * @param tenantService The tenant service. */ public void setTenantService(TenantService tenantService) { this.tenantService = tenantService; } // -------------------------- OTHER METHODS -------------------------- @Override protected String[] getConfigLocations() { String[] generatorConfigurations = getConfigurations(); return ObjectArrays.concat(generatorConfigurations, new String[]{"classpath:spring/core/spring.easyrec-core.PropertyPlaceholderConfigurerDB.xml", "classpath:spring/core/easyrecDataSource.xml", "classpath:spring/core/ItemAssocDAO.xml", "classpath:spring/core/AuthenticationDAO.xml", "classpath:spring/core/TenantConfig_DEFAULT.xml", "classpath:spring/core/TenantDAO.xml", "classpath:spring/core/spring.easyrec-core.SQLScriptServiceSatRecommenderDS.xml", "classpath:spring/core/TenantService.xml", "classpath:spring/core/ActionDAO.xml", "classpath:spring/core/ItemAssocDAO.xml", "easyrec-plugin.xml"}, String.class); } public abstract String[] getConfigurations(); private final Options options; protected AbstractGeneratorCLI() { options = new Options(); OptionBuilder optionBuilder = OptionBuilder.withArgName("tenants"); optionBuilder.withLongOpt("tenant"); optionBuilder.isRequired(false); optionBuilder.hasArg(true); optionBuilder.withDescription( "Specifiy a tenant to generate rules for. Ranges can be specified e.g. 1 - 3 will generate rules for tenants 1 to 3. Alternatively you can specify a list of tenants like 1,2,4. If omitted rules for all tenants are generated."); Option tenantOption = optionBuilder.create('t'); optionBuilder = OptionBuilder.withLongOpt("uninstall"); optionBuilder.isRequired(false); optionBuilder.hasArg(false); optionBuilder.withDescription("When true the generator is uninstalled when execution finished"); Option uninstallOption = optionBuilder.create('u'); options.addOption(tenantOption); options.addOption(uninstallOption); } @Override protected int processCommandLineCall(final String[] args) { final Generator<GC, GS> generator = getGenerator(); super.context.getAutowireCapableBeanFactory() .autowireBeanProperties(generator, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false); List<GC> configurations = new LinkedList<GC>(); CommandLineParser parser = new PosixParser(); CommandLine commandLine; try { commandLine = parser.parse(options, args); } catch (ParseException e) { e.printStackTrace(); usage(); return -1; } boolean doUninstall = commandLine.hasOption('u'); if (!commandLine.hasOption('t')) { List<TenantVO> tenants = tenantService.getAllTenants(); for (TenantVO tenant : tenants) { GC configuration = generator.newConfiguration(); configuration.setTenantId(tenant.getId()); configuration.setConfigurationName(String.format("Configuration for tenant %d", tenant.getId())); configurations.add(configuration); } } else { String strTenants = commandLine.getOptionValue('t'); if (strTenants.contains("-")) { String[] argParts = strTenants.split("-"); if (argParts.length != 2) { usage(); return -1; } int lowerBound = Integer.parseInt(argParts[0]); int upperBound = Integer.parseInt(argParts[1]); if (lowerBound > upperBound) { int tmp = lowerBound; lowerBound = upperBound; upperBound = tmp; } for (int i = lowerBound; i <= upperBound; i++) { GC configuration = generator.newConfiguration(); configuration.setTenantId(i); configuration.setConfigurationName(String.format("Configuration for tenant %d", i)); configurations.add(configuration); } } else if (strTenants.contains(",")) { String[] argParts = strTenants.split(","); for (String argPart : argParts) { int tenant = Integer.parseInt(argPart); GC configuration = generator.newConfiguration(); configuration.setTenantId(tenant); configuration.setConfigurationName(String.format("Configuration for tenant %d", tenant)); configurations.add(configuration); } } else { GC configuration = generator.newConfiguration(); configuration.setTenantId(Integer.parseInt(strTenants)); configuration.setConfigurationName( String.format("Configuration for tenant %d", configuration.getTenantId())); configurations.add(configuration); } } final ExecutableObserver executableObserver = new ExecutableObserver(); final PluginObserver pluginObserver = new PluginObserver(); generator.getExecutableObserverRegistry().addObserver(executableObserver); generator.getPluginObserverRegistry().addObserver(pluginObserver); generator.install(true); for (GC configuration : configurations) { generator.initialize(); generator.setConfiguration(configuration); System.out.println("##################################################"); System.out.println( String.format("[%s] Starting generator with configuration: \"%s\"", new Date().toString(), configuration.getConfigurationName())); System.out.println("##################################################"); try { generator.execute(); } catch (Exception e) { e.printStackTrace(); } // need to sleep 1s to avoid duplicate keys try { Thread.sleep(1000); } catch (InterruptedException e) { } generator.cleanup(); } if (doUninstall) generator.uninstall(); return 0; } public abstract Generator<GC, GS> getGenerator(); @Override protected void usage() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(String.format("java -jar %s", getClass().getCanonicalName()), options); } // -------------------------- INNER CLASSES -------------------------- private static class ExecutableObserver implements Observer<Executable> { // ------------------------------ FIELDS ------------------------------ private Date start = new Date(); // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface Observer --------------------- public void stateChanged(final Executable target) { Date end = new Date(); double durationInSeconds = end.getTime() - start.getTime(); durationInSeconds /= 1000.0; float progressPercentage = 0.0f; if (target.getProgress().getTotalSteps() != 0.0f) progressPercentage = (target.getProgress().getCurrentSteps() / target.getProgress().getTotalSteps()) * 100.0f; System.out.println(String.format("\ttook %.2fs", durationInSeconds)); System.out.println( String.format("[%s] %s: %s - %.2f%% (%d/%d)", end.toString(), target.getExecutionState().toString(), target.getProgress().getMessage(), progressPercentage, target.getProgress().getCurrentSteps() + 1, target.getProgress().getTotalSteps())); start = new Date(); } } private static class PluginObserver implements Observer<Plugin> { // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface Observer --------------------- public void stateChanged(final Plugin target) { System.out.println("Lifecycle-Phase changed to " + target.getLifecyclePhase().toString()); } } }