All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.vesalainen.code.PropertyDispatcher Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Timo Vesalainen
 *
 * 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 3 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, see .
 */

package org.vesalainen.code;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.vesalainen.util.Transactional;

/**
 * PropertyDispatcher can pass setter methods properties to observers efficiently
 * without auto-boxing.
 * 
 * 

Class is transactional, meaning that properties are transferred only when * commit method is called. * *

If PropertySetter class implements also Transactional, its commit or * rollback method is called. * *

Example: * Create PropertyDispatcher sub class. * * @PropertyDispatcherClass("org.vesalainen.code.impl.PDImpl") * public abstract class PD extends PropertyDispatcher implements TrIntf * { * * protected PD(int[] sizes) * { * super(sizes); * } * } * * Create PropertySetter implementation. * * public class PS implements PropertySetter * { * * * * Get instance of PropertyDispatcher sublass and add observer(s) * * PS ps = new PS(); * PD pd = PD.getInstance(PD.class); * * pd.addObserver(ps, "string", "i"); * pd.setI(123); * * @author Timo Vesalainen * @see org.vesalainen.util.Transactional */ public abstract class PropertyDispatcher extends AbstractDispatcher { protected List transactionalObservers = new ArrayList<>(); protected Semaphore semaphore = new Semaphore(1); protected PropertySetterDispatcher observers; /** * Creates a PropertyDispatcher. This is called by generated sub class. * @param sizes Defines how many method class per type can be stored. Default * implementation allows interfaces all methods being called once. Size per type * is in the same order as in JavaType enum. * @see org.vesalainen.code.JavaType */ protected PropertyDispatcher(int[] sizes) { this(sizes, new SimplePropertySetterDispatcher()); } /** * Creates a PropertyDispatcher. This is called by generated sub class. * @param sizes Defines how many method class per type can be stored. Default * implementation allows interfaces all methods being called once. Size per type * is in the same order as in JavaType enum. * @param observers * @see org.vesalainen.code.JavaType */ protected PropertyDispatcher(int[] sizes, PropertySetterDispatcher observers) { super(sizes); this.observers = observers; } /** * Adds a PropertySetter observer for properties. * @param observer * @param properties */ public void addObserver(PropertySetter observer, String... properties) { try { semaphore.acquire(); } catch (InterruptedException ex) { throw new IllegalArgumentException(ex); } try { addObserver(observer); for (String p : properties) { observers.addObserver(p, observer); } } finally { semaphore.release(); } } protected void addObserver(PropertySetter observer) { if (observer instanceof Transactional) { Transactional tr = (Transactional) observer; transactionalObservers.add(tr); } } /** * Remove a PropertySetter observer for properties. * @param observer * @param properties */ public void removeObserver(PropertySetter observer, String... properties) { try { semaphore.acquire(); } catch (InterruptedException ex) { throw new IllegalArgumentException(ex); } try { removeObserver(observer); for (String p : properties) { observers.removeObserver(p, observer); } } finally { semaphore.release(); } } protected void removeObserver(PropertySetter observer) { if (observer instanceof Transactional) { Transactional tr = (Transactional) observer; transactionalObservers.remove(tr); } } /** * Return true if no observers * @return */ public boolean hasObservers() { return !observers.isEmpty(); } /** * Creates a instance of a class PropertyDispatcher subclass. * @param Type of PropertyDispatcher subclass * @param cls PropertyDispatcher subclass class * @return */ public static T getInstance(Class cls) { return getInstance(cls, null); } /** * Creates a instance of a class PropertyDispatcher subclass. * @param Type of PropertyDispatcher subclass * @param cls PropertyDispatcher subclass class * @param dispatcher * @return */ public static T getInstance(Class cls, PropertySetterDispatcher dispatcher) { try { PropertyDispatcherClass annotation = cls.getAnnotation(PropertyDispatcherClass.class); if (annotation == null) { throw new IllegalArgumentException("@"+PropertyDispatcherClass.class.getSimpleName()+" missing in cls"); } Class c = Class.forName(annotation.value()); if (dispatcher == null) { T t =(T) c.newInstance(); return t; } else { Constructor constructor = c.getConstructor(PropertySetterDispatcher.class); return (T) constructor.newInstance(dispatcher); } } catch (InvocationTargetException | SecurityException | NoSuchMethodException | ClassNotFoundException | InstantiationException | IllegalAccessException ex) { throw new IllegalArgumentException(ex); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy