/*
* Copyright (c) 2010, Michael Grossmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the jo-widgets.org nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.jowidgets.impl.base.factory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jowidgets.common.widgets.IWidgetCommon;
import org.jowidgets.common.widgets.descriptor.IWidgetDescriptor;
import org.jowidgets.common.widgets.factory.IGenericWidgetFactory;
import org.jowidgets.common.widgets.factory.IWidgetFactory;
import org.jowidgets.common.widgets.factory.IWidgetFactoryListener;
import org.jowidgets.util.Assert;
import org.jowidgets.util.EmptyCheck;
import org.jowidgets.util.IDecorator;
public final class DefaultGenericWidgetFactory implements IGenericWidgetFactory {
@SuppressWarnings("rawtypes")
private final Map factories;
@SuppressWarnings("rawtypes")
private final Map decorators;
@SuppressWarnings("rawtypes")
private final Map factoryDecorators;
private int createdWidgets;
private final Set<IWidgetFactoryListener> widgetFactoryListeners;
@SuppressWarnings("rawtypes")
public DefaultGenericWidgetFactory() {
this.factories = new HashMap();
this.decorators = new HashMap();
this.factoryDecorators = new HashMap();
this.createdWidgets = 0;
this.widgetFactoryListeners = new HashSet<IWidgetFactoryListener>();
}
@Override
public void addWidgetFactoryListener(final IWidgetFactoryListener widgetFactoryListener) {
this.widgetFactoryListeners.add(widgetFactoryListener);
}
@Override
public void removeWidgetFactoryListener(final IWidgetFactoryListener widgetFactoryListener) {
this.widgetFactoryListeners.remove(widgetFactoryListener);
}
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> WIDGET_TYPE create(
final DESCRIPTOR_TYPE descriptor) {
return create(null, descriptor);
}
@SuppressWarnings("unchecked")
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> WIDGET_TYPE create(
final Object parentUiReference,
final DESCRIPTOR_TYPE descriptor) {
return (WIDGET_TYPE) createWidget(parentUiReference, descriptor);
}
@SuppressWarnings("unchecked")
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> void register(
final Class<? extends DESCRIPTOR_TYPE> descriptorClass,
final IWidgetFactory<WIDGET_TYPE, ? extends DESCRIPTOR_TYPE> widgetFactory) {
Assert.paramNotNull(descriptorClass, "descriptorClass");
Assert.paramNotNull(widgetFactory, "widgetFactory");
if (factories.containsKey(descriptorClass)) {
throw new IllegalArgumentException("There was already registered a factory for the descriptor '"
+ descriptorClass
+ "' get name.");
}
factories.put(descriptorClass, widgetFactory);
}
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> void unRegister(
final Class<? extends DESCRIPTOR_TYPE> descriptorClass) {
Assert.paramNotNull(descriptorClass, "descriptorClass");
if (factories.containsKey(descriptorClass)) {
factories.remove(descriptorClass);
}
else {
throw new IllegalArgumentException("There was already registered a factory for the descriptor '"
+ descriptorClass
+ "' get name.");
}
}
@SuppressWarnings("unchecked")
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE> getFactory(
final Class<? extends DESCRIPTOR_TYPE> descriptorClass) {
return decorateFactory((IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE>) factories.get(descriptorClass), descriptorClass);
}
@SuppressWarnings("unchecked")
private <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE> decorateFactory(
final IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE> widgetFactory,
final Class<? extends DESCRIPTOR_TYPE> descriptorClass) {
IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE> result = widgetFactory;
final List<IDecorator<Object>> decoratorsList = (List<IDecorator<Object>>) factoryDecorators.get(descriptorClass);
if (decoratorsList != null) {
for (final IDecorator<Object> decorator : decoratorsList) {
final Object decorated = decorator.decorate(result);
if (decorated instanceof IWidgetFactory) {
result = (IWidgetFactory<WIDGET_TYPE, DESCRIPTOR_TYPE>) decorated;
}
else {
throw new IllegalStateException("Decorator must return an instance of '"
+ IWidgetFactory.class.getName()
+ "'");
}
}
}
return result;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> void addWidgetDecorator(
final Class<? extends DESCRIPTOR_TYPE> descriptorClass,
final IDecorator<? extends WIDGET_TYPE> decorator) {
Assert.paramNotNull(descriptorClass, "descriptorClass");
Assert.paramNotNull(decorator, "decorator");
List decoratorsList = (List) decorators.get(descriptorClass);
if (decoratorsList == null) {
decoratorsList = new LinkedList();
decorators.put(descriptorClass, decoratorsList);
}
decoratorsList.add(decorator);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public <WIDGET_TYPE extends IWidgetCommon, DESCRIPTOR_TYPE extends IWidgetDescriptor<WIDGET_TYPE>> void addWidgetFactoryDecorator(
final Class<? extends DESCRIPTOR_TYPE> descriptorClass,
final IDecorator<? extends IWidgetFactory<WIDGET_TYPE, ? extends DESCRIPTOR_TYPE>> decorator) {
Assert.paramNotNull(descriptorClass, "descriptorClass");
Assert.paramNotNull(decorator, "decorator");
List factoryDecoratorsList = (List) factoryDecorators.get(descriptorClass);
if (factoryDecoratorsList == null) {
factoryDecoratorsList = new LinkedList();
factoryDecorators.put(descriptorClass, factoryDecoratorsList);
}
factoryDecoratorsList.add(decorator);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Object createWidget(final Object parentUiReference, final IWidgetDescriptor descriptor) {
Assert.paramNotNull(descriptor, "descriptor");
final IWidgetFactory factory = getFactory(descriptor.getDescriptorInterface());
if (factory != null) {
Object result = factory.create(parentUiReference, descriptor);
if (result instanceof IWidgetCommon) {
result = decorateWidget((IWidgetCommon) result, descriptor);
fireWidgetCreated((IWidgetCommon) result);
createdWidgets++;
}
else {
throw new IllegalStateException("Created widget must be assignable from '" + IWidgetCommon.class.getName() + "'");
}
return result;
}
else {
throw new IllegalArgumentException("No factory found for descriptor interface'"
+ descriptor.getDescriptorInterface()
+ " / implClass:'"
+ descriptor.getClass().getName()
+ "'");
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private IWidgetCommon decorateWidget(final IWidgetCommon widget, final IWidgetDescriptor descriptor) {
IWidgetCommon result = widget;
final List<IDecorator<Object>> decoratorsList = (List<IDecorator<Object>>) decorators.get(descriptor.getDescriptorInterface());
if (decoratorsList != null) {
for (final IDecorator<Object> decorator : decoratorsList) {
final Object decorated = decorator.decorate(result);
if (decorated instanceof IWidgetCommon) {
result = (IWidgetCommon) decorated;
}
else {
throw new IllegalStateException("Decorated widget must be assignable from '"
+ IWidgetCommon.class.getName()
+ "'");
}
}
}
return result;
}
private void fireWidgetCreated(final IWidgetCommon widget) {
Assert.paramNotNull(widget, "widget");
for (final IWidgetFactoryListener listener : widgetFactoryListeners) {
listener.widgetCreated(widget);
}
}
@Override
@SuppressWarnings({"rawtypes"})
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("--> Generic Widget Factory State <--\n");
result.append("Registered Widgets: " + factories.keySet().size() + "\n");
for (final Object key : getSortedKeys(factories)) {
result.append(key.toString() + " -> " + factories.get(key).getClass().getName() + "\n");
}
result.append("Registered Widget Decorators: " + decorators.keySet().size() + "\n");
for (final Object key : getSortedKeys(decorators)) {
final Collection decoratorsList = (Collection) decorators.get(key);
if (!EmptyCheck.isEmpty(decoratorsList)) {
result.append(key.toString() + " -> " + getDecoratorsString(decoratorsList) + "\n");
}
}
result.append("Registered Widget Factory Decorators: " + factoryDecorators.keySet().size() + "\n");
for (final Object key : getSortedKeys(factoryDecorators)) {
final Collection decoratorsList = (Collection) factoryDecorators.get(key);
if (!EmptyCheck.isEmpty(decoratorsList)) {
result.append(key.toString() + " -> " + getDecoratorsString(decoratorsList) + "\n");
}
}
result.append("Created Widgets: " + createdWidgets + "\n");
return result.toString();
}
@SuppressWarnings({"rawtypes"})
private String getDecoratorsString(final Collection decoratorsList) {
final StringBuilder result = new StringBuilder();
if (!EmptyCheck.isEmpty(decoratorsList)) {
for (final Object decorator : decoratorsList) {
result.append(decorator.getClass().getName() + ",");
}
result.replace(result.length() - 1, result.length(), "");
}
return result.toString();
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static ArrayList getSortedKeys(final Map map) {
final ArrayList keys = new ArrayList(map.keySet());
Collections.sort(keys, new Comparator() {
@Override
public int compare(final Object o1, final Object o2) {
return o1.toString().compareTo(o2.toString());
}
});
return keys;
}
}