[Buix-commits] r546 - trunk/jaxx/src/main/java/jaxx
Author: tchemit Date: 2008-04-18 17:11:28 +0000 (Fri, 18 Apr 2008) New Revision: 546 Added: trunk/jaxx/src/main/java/jaxx/DialogUIDef.java trunk/jaxx/src/main/java/jaxx/UIFactory.java trunk/jaxx/src/main/java/jaxx/UIProvider.java Log: generic UIPRovider, UIFactory and introduce DialogUIDef Added: trunk/jaxx/src/main/java/jaxx/DialogUIDef.java =================================================================== --- trunk/jaxx/src/main/java/jaxx/DialogUIDef.java (rev 0) +++ trunk/jaxx/src/main/java/jaxx/DialogUIDef.java 2008-04-18 17:11:28 UTC (rev 546) @@ -0,0 +1,57 @@ +/** + * ##% 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 jaxx; + +/** @author chemit */ +public class DialogUIDef<M extends DialogUIModel, U extends DialogUI<?>, H extends DialogUIHandler<M, U>> { + + private final Class<U> uiClass; + private final Class<M> modelClass; + private final Class<H> handlerClass; + + public DialogUIDef(Class<H> handlerClass, Class<U> uiClass, Class<M> modelClass) { + this.handlerClass = handlerClass; + this.uiClass = uiClass; + this.modelClass = modelClass; + } + + public Class<U> getUiClass() { + return uiClass; + } + + public Class<H> getHandlerClass() { + return handlerClass; + } + + public Class<M> getModelClass() { + return modelClass; + } + + @Override + public boolean equals(Object o) { + return this == o || o instanceof DialogUIDef && uiClass.equals(((DialogUIDef) o).uiClass); + + } + + @Override + public int hashCode() { + return uiClass.hashCode(); + } + + @Override + public String toString() { + return super.toString() + "<model:" + modelClass + ", ui:" + uiClass + ", handler:" + handlerClass + '>'; + } +} Added: trunk/jaxx/src/main/java/jaxx/UIFactory.java =================================================================== --- trunk/jaxx/src/main/java/jaxx/UIFactory.java (rev 0) +++ trunk/jaxx/src/main/java/jaxx/UIFactory.java 2008-04-18 17:11:28 UTC (rev 546) @@ -0,0 +1,218 @@ +/** + * ##% 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 jaxx; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.util.ListenerSet; +import org.codelutin.util.StringUtil; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; + +/** + * Factory if VCS UI, using a cache. + * + * @author chemit + */ +public class UIFactory { + + static protected final Log log = LogFactory.getLog(UIFactory.class); + + protected static UIFactory instance; + + protected Map<DialogUIDef, DialogUI> cache; + + protected ServiceLoader<UIProvider> loader; + + protected String applicationName; + + protected ListenerSet<FactoryWindowListener> listeners; + + public static void initFactory(String applicationName, FactoryWindowListener... listeners) { + UIFactory factory = getInstance(); + synchronized (factory) { + factory.applicationName = applicationName; + for (FactoryWindowListener listener : listeners) { + listener.setFactory(factory); + factory.addFactoryWindowListener(listener); + } + } + } + + public void addFactoryWindowListener(FactoryWindowListener l) { + listeners.add(l); + } + + public void removeFactoryWindowListener(FactoryWindowListener l) { + listeners.remove(l); + } + + public void close() { + if (cache != null) { + cache.clear(); + cache = null; + } + if (loader != null) { + loader.reload(); + loader = null; + } + while (listeners.size() > 0) { + removeFactoryWindowListener(listeners.iterator().next()); + } + + } + + protected static UIFactory getInstance() { + if (instance == null) { + instance = new UIFactory(); + } + return instance; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + close(); + } + + protected synchronized Map<DialogUIDef, DialogUI> getCache() { + if (cache == null) { + cache = new HashMap<DialogUIDef, DialogUI>(); + } + return cache; + } + + protected synchronized ServiceLoader<UIProvider> getProviders() { + checkInit(); + if (loader == null) { + long t0 = System.nanoTime(); + + loader = ServiceLoader.load(UIProvider.class); + int nb = 0; + for (UIProvider provider : loader) { + log.info(provider.getName() + " [" + provider + ']'); + nb++; + } + log.info("found " + nb + " ui provider(s) in " + StringUtil.convertTime(t0, System.nanoTime())); + } + return loader; + } + + protected DialogUI newUI(DialogUIDef uiType) { + + DialogUI result = getInstance().getCache().get(uiType); + if (result == null) { + try { + getCache().put(uiType, result = newUI0(uiType)); + for (FactoryWindowListener listener : listeners) { + result.addWindowListener(listener); + } + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui handler " + uiType + " for reason : " + e.getMessage()); + } + } + return result; + } + + protected DialogUI newUI0(DialogUIDef uiType, Object... params) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + for (UIProvider provider : getProviders()) { + DialogUI ui = provider.newUI(uiType); + if (ui != null) { + Class<?>[] prototype = getHandlerPrototype(ui.getClass(), params); + Object[] parameters = getHandlerParameters(ui, params); + uiType.getHandlerClass().getConstructor(prototype).newInstance(ui, parameters); + ui.getHandler().init(); + return ui; + } + } + throw new IllegalStateException("could not find ui " + uiType); + } + + protected UIFactory() { + listeners = new ListenerSet<FactoryWindowListener>(); + } + + protected Class<?>[] getHandlerPrototype(Class<? extends DialogUI> aClass, Object[] params) { + Class<?>[] classes = new Class<?>[1 + params.length]; + classes[0] = aClass.getSuperclass(); + for (int i = 0; i < params.length; i++) { + classes[i + 1] = params[i].getClass(); + } + return classes; + } + + protected Object[] getHandlerParameters(DialogUI ui, Object[] params) { + Object[] classes = new Object[1 + params.length]; + classes[0] = ui; + System.arraycopy(params, 0, classes, 1, params.length); + return classes; + } + + private void checkInit() throws IllegalStateException { + if (applicationName == null) { + throw new IllegalStateException("factory " + this + " was not init "); + } + } + + public static abstract class FactoryWindowListener extends WindowAdapter { + + protected abstract void allWindowsClosed(); + + private UIFactory factory; + + private boolean wasClosed; + + public UIFactory getFactory() { + return factory; + } + + public void setFactory(UIFactory factory) { + this.factory = factory; + } + + @Override + public void windowClosed(WindowEvent e) { + if (log.isDebugEnabled()) { + log.debug(e.getSource()); + } + if (e.getWindow().isVisible()) { + // only deal with real closed and none visible windows... + return; + } + for (DialogUI vcsui : factory.getCache().values()) { + if (vcsui.isVisible()) { + // at least one ui visible, do not kill connexions + return; + } + } + if (wasClosed) { + // make sure to process once + return; + } + synchronized (this) { + try { + allWindowsClosed(); + } finally { + wasClosed = true; + } + } + } + } +} \ No newline at end of file Added: trunk/jaxx/src/main/java/jaxx/UIProvider.java =================================================================== --- trunk/jaxx/src/main/java/jaxx/UIProvider.java (rev 0) +++ trunk/jaxx/src/main/java/jaxx/UIProvider.java 2008-04-18 17:11:28 UTC (rev 546) @@ -0,0 +1,68 @@ +/** + * # #% 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 jaxx; + +/** @author chemit */ +public abstract class UIProvider { + + /** the name of application using this provider */ + protected String applicationName; + + /** the name of ui implementation used by this provider */ + protected String name; + + /** array of ui implementations */ + protected Class<?>[] implementations; + + protected UIProvider(String applicationName, String name, Class<?>... implementations) { + this.applicationName = applicationName; + this.name = name; + this.implementations = implementations; + } + + /** @return the identifier of the ui provider (eg jaxx, swing, ...) */ + public String getName() { + return name; + } + + public String getApplicationName() { + return applicationName; + } + + public Class<?>[] getImplementations() { + return implementations; + } + + public <U extends DialogUI<?>, D extends DialogUIDef<?, U, ?>> U newUI(D def) throws InstantiationException, IllegalAccessException { + Class<U> uiImpl = finImpl(def.getUiClass()); + return uiImpl != null ? uiImpl.newInstance() : null; + } + + @Override + public String toString() { + return super.toString() + " application:" + applicationName + ", provider:" + name + ", uis:" + (java.util.Arrays.toString(implementations)); + } + + @SuppressWarnings({"unchecked"}) + private <X extends DialogUI> Class<X> finImpl(Class<X> uiType) { + for (Class<?> klass : implementations) { + if (uiType.isAssignableFrom(klass)) { + return (Class<X>) klass; + } + } + return null; + } + +} \ No newline at end of file
participants (1)
-
tchemit@users.labs.libre-entreprise.org