Index: lutincommandline/src/java/org/codelutin/option/AbstractContext.java diff -u lutincommandline/src/java/org/codelutin/option/AbstractContext.java:1.3 lutincommandline/src/java/org/codelutin/option/AbstractContext.java:1.4 --- lutincommandline/src/java/org/codelutin/option/AbstractContext.java:1.3 Sun Mar 16 21:15:58 2008 +++ lutincommandline/src/java/org/codelutin/option/AbstractContext.java Mon Mar 17 22:39:33 2008 @@ -1,14 +1,30 @@ +/** + * ##% Copyright (C) 2008 Code Lutin, Tony Chemit + * This program 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 2 + * of the License, or (at your option) any later version. This program 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 this + * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place + * - Suite 330, Boston, MA 02111-1307, USA. ##%* + */ package org.codelutin.option; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.codelutin.util.ReflectUtil; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -44,6 +60,12 @@ protected final File home; + /** les clefs d'options connues par le parseur */ + protected final List> configKeys; + + /** les configs */ + protected final Config[] configs; + protected AbstractContext(Class

parserClass) throws Exception { String home = System.getProperty("user.home"); if (home == null) { @@ -54,18 +76,26 @@ this.parser = parserClass.newInstance(); - for (ConfigKey configKey : parser.getConfigKeys()) { - configKey.instanciateConfig(); + List> keyList = new ArrayList>(); + List c = ReflectUtil.getConstants(getClass(), ConfigKey.class); + for (ConfigKey configKey : c) { + keyList.add(configKey); + } + this.configKeys = Collections.unmodifiableList(keyList); + this.configs = new Config[this.configKeys.size()]; + int i = 0; + for (ConfigKey configKey : getConfigKeys()) { + this.configs[i++] = configKey.instanciateConfig(); } - } + public void init(String[] args) throws Exception { // parse arguments parser.doParse(args); - if (parser.getLastResult().getError()!=null) { + if (parser.getLastResult().getError() != null) { throw parser.getLastResult().getError(); } // set config file location @@ -81,7 +111,6 @@ save(); } - /** * Initialize all configs, simply by instanciate them. * @@ -89,10 +118,13 @@ */ protected void initConfigs() throws Exception { - for (ConfigKey configKey : getParser().getConfigKeys()) { + for (ConfigKey configKey : getConfigKeys()) { - Config config = getParser().getConfig(configKey); + Config config = getConfig(configKey); config.setSource(getSource()); + if (config.isMain()) { + config.setProperty(config.getFileNameConfigKey(), getSource()); + } config.doInit(); } @@ -100,9 +132,10 @@ loadFromOptions(); } + protected void initSource() throws Exception { - Config main = getConfig(); + Config main = getMainConfig(); OptionParserResult result = parser.getLastResult(); @@ -124,7 +157,7 @@ public abstract void initI18n(); /** @return la configuration principale de l'application */ - public abstract Config getConfig(); + public abstract Config getMainConfig(); /** * @return le parseur utilisé pour parser les options de la ligne de @@ -135,6 +168,17 @@ } /** + * Obtenir une instance de configuration à partir de sa clef. + * + * @param key la clef de la configuration recherchée + * @return l'instance de la configuration + */ + public C getConfig(ConfigKey key) { + int index = configKeys.indexOf(key); + return (C) configs[index]; + } + + /** * @return true si on doit quitter l'application (uniquement utilisé * lors du démarrage de l'application lors de l'exécution des options * utilisateurs) @@ -173,11 +217,11 @@ protected void loadFromOptions() throws Exception { - if (!getParser().getLastResult().isOptionEnabled(getConfig().getConfigOptionKey())) { + if (!getParser().getLastResult().isOptionEnabled(getMainConfig().getConfigOptionKey())) { return; } - parser.getLastResult().doActions(this, getConfig().getConfigOptionKey()); + parser.getLastResult().doActions(this, getMainConfig().getConfigOptionKey()); } /** @@ -189,21 +233,16 @@ * sauvegarder. */ public void save() throws IOException, IllegalStateException { - List configs = getParser().getConfigKeys(); + List> configs = getConfigKeys(); if (configs.isEmpty()) { // no config return; } - Config main = null; - List others = new ArrayList(); - for (ConfigKey configKey : configs) { - Config config = configKey.getConfig(); - if (config.isMain()) { - main = config; - } else { - others.add(config); - } - } + + Config main = getMainConfig(); + List others = new ArrayList(Arrays.asList(this.configs)); + others.remove(getMainConfig()); + if (main == null || main.getSource() == null) { // no main config, or source is null throw new IllegalStateException("could not find main config, nor his source file"); @@ -243,4 +282,53 @@ public File getSource() { return source; } + + public List> getConfigKeys() { + return configKeys; + } + + public Config[] getConfigs() { + return configs; + } + + /** + * Obtient une clef typée d'une config à partir de sa clef non typée. + * + * @param key la clef non typée + * @return la clef typée ou null si non trouvée. + */ + public ConfigKey getConfigKey(String key) { + for (ConfigKey optionKey : configKeys) { + if (optionKey.getCategory().equals(key)) { + return optionKey; + } + } + return null; + } + + public Config getConfig(String key) { + for (int i = 0; i < configKeys.size(); i++) { + ConfigKey optionKey = configKeys.get(i); + if (optionKey.getCategory().equals(key)) { + return configs[i]; + } + } + return null; + } + + /** + * Enregistre une implanation concrete de config. + * + * @param aClass la classe à enregister + */ + @SuppressWarnings({"unchecked"}) + public void registerConfig(Class aClass) { + for (ConfigKey key : configKeys) { + if (key.getAbstractConfigClass().isAssignableFrom(aClass)) { + // found a matching key + ((ConfigKey) key).setConfigClass(aClass); + } + } + } + } \ No newline at end of file Index: lutincommandline/src/java/org/codelutin/option/OptionActionRunnable.java diff -u lutincommandline/src/java/org/codelutin/option/OptionActionRunnable.java:1.1 lutincommandline/src/java/org/codelutin/option/OptionActionRunnable.java:1.2 --- lutincommandline/src/java/org/codelutin/option/OptionActionRunnable.java:1.1 Sun Mar 16 07:11:27 2008 +++ lutincommandline/src/java/org/codelutin/option/OptionActionRunnable.java Mon Mar 17 22:39:33 2008 @@ -6,6 +6,6 @@ * @author chemit */ public interface OptionActionRunnable, A extends OptionAction> { - void run(A action, C context) throws Exception; + void run(A action) throws Exception; } Index: lutincommandline/src/java/org/codelutin/option/OptionActionAnnotation.java diff -u lutincommandline/src/java/org/codelutin/option/OptionActionAnnotation.java:1.1 lutincommandline/src/java/org/codelutin/option/OptionActionAnnotation.java:1.2 --- lutincommandline/src/java/org/codelutin/option/OptionActionAnnotation.java:1.1 Sat Mar 15 21:18:09 2008 +++ lutincommandline/src/java/org/codelutin/option/OptionActionAnnotation.java Mon Mar 17 22:39:33 2008 @@ -1,3 +1,17 @@ +/** + * ##% Copyright (C) 2008 Code Lutin, Tony Chemit + * This program 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 2 + * of the License, or (at your option) any later version. This program 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 this + * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place + * - Suite 330, Boston, MA 02111-1307, USA. + * ##% + */ package org.codelutin.option; import java.lang.annotation.ElementType; Index: lutincommandline/src/java/org/codelutin/option/OptionParser.java diff -u lutincommandline/src/java/org/codelutin/option/OptionParser.java:1.7 lutincommandline/src/java/org/codelutin/option/OptionParser.java:1.8 --- lutincommandline/src/java/org/codelutin/option/OptionParser.java:1.7 Sun Mar 16 21:15:58 2008 +++ lutincommandline/src/java/org/codelutin/option/OptionParser.java Mon Mar 17 22:39:33 2008 @@ -50,10 +50,6 @@ * implantations doivent être présentes en tant qu'inner class d'une ou plusieurs * classes container. *

- * Le fonctionnement est identique pour les config (celles générées sont abstraites), - * on doit enregistre des implantation concretes par l'intermédiaire de la méthode - * {@link #registerConfig(Class)}. - *

* Attention, contrairement aux actions, ici les classes de Config ne sont * pas des inner-classes. */ @@ -93,8 +89,6 @@ /** les clefs d'options connues par le parseur */ protected final List optionKeys; - /** les clefs d'options connues par le parseur */ - protected final List configKeys; /** le dernier result de parsing, ou null si aucun parsing lancé */ protected OptionParserResult lastResult; @@ -110,12 +104,8 @@ I18n.initISO88591(); optionKeys = Collections.unmodifiableList(ReflectUtil.getConstants(getClass(), OptionKey.class)); - configKeys = Collections.unmodifiableList(ReflectUtil.getConstants(getClass(), ConfigKey.class)); - } - public List getConfigKeys() { - return configKeys; } public List getOptionKeys() { @@ -163,15 +153,6 @@ return null; } - /** - * Obtenir une instance de configuration à partir de sa clef. - * - * @param key la clef de la configuration recherchée - * @return l'instance de la configuration - */ - public C getConfig(ConfigKey key) { - return key.getConfig(); - } /** * Print usage of the parser @@ -208,20 +189,6 @@ } } - /** - * Enregistre une implanation concrete de config. - * - * @param aClass la classe à enregister - */ - @SuppressWarnings({"unchecked"}) - public void registerConfig(Class aClass) { - for (ConfigKey key : configKeys) { - if (key.getAbstractConfigClass().isAssignableFrom(aClass)) { - // found a matching key - ((ConfigKey) key).setConfigClass(aClass); - } - } - } @Override protected void finalize() throws Throwable { @@ -229,30 +196,6 @@ cleanResult(); } - /** - * Obtient une clef typée d'une config à partir de sa clef non typée. - * - * @param key la clef non typée - * @return la clef typée ou null si non trouvée. - */ - public ConfigKey getConfigKey(String key) { - for (ConfigKey optionKey : configKeys) { - if (optionKey.getCategory().equals(key)) { - return optionKey; - } - } - return null; - } - - public Config getConfig(String key) { - for (ConfigKey optionKey : configKeys) { - if (optionKey.getCategory().equals(key)) { - return optionKey.getConfig(); - } - } - return null; - } - /** nettoye les résultat du parseur (utilisé avant tout parsing) */ protected void cleanResult() { if (lastResult != null) { Index: lutincommandline/src/java/org/codelutin/option/ConfigKey.java diff -u lutincommandline/src/java/org/codelutin/option/ConfigKey.java:1.3 lutincommandline/src/java/org/codelutin/option/ConfigKey.java:1.4 --- lutincommandline/src/java/org/codelutin/option/ConfigKey.java:1.3 Sun Mar 16 21:15:58 2008 +++ lutincommandline/src/java/org/codelutin/option/ConfigKey.java Mon Mar 17 22:39:33 2008 @@ -46,18 +46,11 @@ *

*

* Le but de cette classe pivot, est de pouvoir accéder de manière typée à une config. - * Elle sera utilisée dans le parseur {@link OptionParser}, grâce à la méthode - * {@link OptionParser#getConfig(ConfigKey)} pour + * Elle sera utilisée dans le context {@link AbstractContext}, grâce à la méthode + * {@link AbstractContext#getConfig(ConfigKey)} pour *

* pouvoir accéder de manière typée à une config. *

- *

- * De plus, cette clef sert aussi pour contenir l'unique instance partagée de - * l'implantation de la config {@link #config}. - *

- * Pour obtenir l'instance, on utilise la méthode {@link #getConfig()} qui retourne - * l'instance typée de la config. - *

* Comme pour les autres types de clefs ({@link ConfigPropertyKey}, {@link OptionKey}), * on dispose de méthodes d'instanciation par factory : *

@@ -91,9 +84,6 @@ /** la classe concrete de la config (calculé au runtime) */ protected Class configClass; - /** l'unique instance de la config liée */ - protected C config; - // constructeur privé, pour empécher les instanciations multiples private ConfigKey(String key, Class abstractConfigClass, String description) { this.category = key; @@ -124,24 +114,12 @@ this.configClass = configClass; } - /** - * Get the shared config linked with this key. - * - * @return the share config's instance - */ - public synchronized C getConfig() { - if (config == null) { - throw new IllegalStateException("the config was not init, use first method initConfig " + this); - } - return config; - } - public C instanciateConfig() { if (configClass == null) { throw new IllegalStateException("no concrete config found for " + abstractConfigClass); } try { - return config = configClass.getConstructor().newInstance(); + return configClass.getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } Index: lutincommandline/src/java/org/codelutin/option/ParserUtil.java diff -u lutincommandline/src/java/org/codelutin/option/ParserUtil.java:1.2 lutincommandline/src/java/org/codelutin/option/ParserUtil.java:1.3 --- lutincommandline/src/java/org/codelutin/option/ParserUtil.java:1.2 Sun Mar 16 07:11:27 2008 +++ lutincommandline/src/java/org/codelutin/option/ParserUtil.java Mon Mar 17 22:39:33 2008 @@ -66,7 +66,7 @@ return; } w.append(addTitle(prefixConfig, '-', false)).append("\n"); - for (ConfigKey key : configKeys) { + for (ConfigKey key : configKeys) { w.append("\n").append(addTitle(key.getDescription() + " (" + key.getCategory() + ")", '~', false)).append("\n"); for (ConfigPropertyKey propertyKey : ReflectUtil.getConstants(key.getAbstractConfigClass(), ConfigPropertyKey.class)) { w.append(prefix).append(propertyKey.getKey()).append(" (").append(propertyKey.getType().getSimpleName()).append(")"); Index: lutincommandline/src/java/org/codelutin/option/OptionAction.java diff -u lutincommandline/src/java/org/codelutin/option/OptionAction.java:1.4 lutincommandline/src/java/org/codelutin/option/OptionAction.java:1.5 --- lutincommandline/src/java/org/codelutin/option/OptionAction.java:1.4 Sun Mar 16 11:08:27 2008 +++ lutincommandline/src/java/org/codelutin/option/OptionAction.java Mon Mar 17 22:39:33 2008 @@ -10,13 +10,13 @@ *

* This method offers some hooks to use for controling running : *

- * {@link #beforeAll(AbstractContext,Option...)} : no {@link #option} is set, before any doRun. + * {@link #beforeAll(Option...)} : no {@link #option} is set, before any doRun. *

- * {@link #beforeRun(AbstractContext)} : an {@link #option} has been set in action, just before {@link #run(AbstractContext)} + * {@link #beforeRun()} : an {@link #option} has been set in action, just before {@link #run()} *

- * {@link #afterRun(AbstractContext)} : just after {@link #run(AbstractContext)}, the current {@link #option} is still available. + * {@link #afterRun()} : just after {@link #run()}, the current {@link #option} is still available. *

- * {@link #afterAll(AbstractContext,Option...)} : no more {@link #option} is set, after all doRun. + * {@link #afterAll(Option...)} : no more {@link #option} is set, after all doRun. * * @author chemit */ @@ -31,40 +31,51 @@ * This method will never by directly called, you have to use * {@link #doRun(AbstractContext,Option[])} method instead which offers some hooks to control actions. * - * @param context the used context * @throws Exception if any problem while action */ - protected abstract void run(C context) throws Exception; + protected abstract void run() throws Exception; + /** the current context to be used for running. */ + protected C context; /** the current option to be used for running. */ protected O option; public void doRun(C context, O... options) throws Exception { - beforeAll(context, options); - for (O option : options) { - this.option = option; - beforeRun(context); - run(context); - afterRun(context); - this.option = null; + try { + this.context=context; + beforeAll( options); + for (O option : options) { + this.option = option; + beforeRun(); + run(); + afterRun(); + this.option = null; + } + afterAll( options); + } finally { + this.context=null; + this.option=null; } - afterAll(context, options); } - protected void beforeAll(C context, O... options) { + protected void beforeAll(O... options) { } - protected void beforeRun(C context) { + protected void beforeRun() { } - protected void afterRun(C context) { + protected void afterRun() { } - protected void afterAll(C context, O... options) throws Exception { + protected void afterAll( O... options) throws Exception { } public Option getOption() { return option; } + + public C getContext() { + return context; + } }