blob: 1b8d3bee2c032babbfccdffde54af7e7597cc946 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.rt.ui.swing;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.TreeMap;
import javax.swing.JComponent;
import org.eclipse.core.runtime.Platform;
import org.eclipse.scout.commons.CompositeObject;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
import org.eclipse.scout.rt.ui.swing.extension.FormFieldsExtensionPoint;
import org.eclipse.scout.rt.ui.swing.extension.IFormFieldExtension;
import org.eclipse.scout.rt.ui.swing.extension.IFormFieldFactory;
import org.eclipse.scout.rt.ui.swing.form.fields.ISwingScoutFormField;
import org.osgi.framework.Bundle;
public class FormFieldFactory implements IFormFieldFactory {
private static IScoutLogger LOG = ScoutLogManager.getLogger(FormFieldFactory.class);
private LinkedHashMap<Class<?>, IFormFieldFactory> m_fields;
@SuppressWarnings("unchecked")
public FormFieldFactory() {
TreeMap<CompositeObject, P_FormFieldExtension> sortedMap = new TreeMap<CompositeObject, P_FormFieldExtension>();
for (IFormFieldExtension extension : FormFieldsExtensionPoint.getFormFieldExtensions()) {
if (extension.isActive()) {
Bundle loaderBundle = Platform.getBundle(extension.getContibuterBundleId());
if (loaderBundle != null) {
Class<?> modelClazz;
Class<? extends ISwingScoutFormField> uiClazz = null;
Class<? extends IFormFieldFactory> factoryClazz = null;
try {
modelClazz = loaderBundle.loadClass(extension.getModelClassName());
if (!StringUtility.isNullOrEmpty(extension.getUiClassName())) {
uiClazz = (Class<? extends ISwingScoutFormField>) loaderBundle.loadClass(extension.getUiClassName());
if (!ISwingScoutFormField.class.isAssignableFrom(uiClazz)) {
LOG.warn("extension '" + extension.getName() + "' contributed by '" + extension.getContibuterBundleId() + "' has an ui class not instanceof " + ISwingScoutFormField.class.getName() + ".");
uiClazz = null;
}
}
else if (!StringUtility.isNullOrEmpty(extension.getFactoryClassName())) {
factoryClazz = (Class<? extends IFormFieldFactory>) loaderBundle.loadClass(extension.getFactoryClassName());
if (!IFormFieldFactory.class.isAssignableFrom(factoryClazz)) {
LOG.warn("extension '" + extension.getName() + "' contributed by '" + extension.getContibuterBundleId() + "' has a facotry class not instanceof " + IFormFieldFactory.class.getName() + ".");
factoryClazz = null;
}
}
IFormFieldFactory factory = null;
if (uiClazz != null) {
factory = new P_DirectLinkFormFieldFactory(uiClazz);
}
else if (factoryClazz != null) {
try {
factory = factoryClazz.newInstance();
}
catch (Exception e) {
LOG.warn("could not create a factory instance of '" + factoryClazz.getName() + "' ", e);
}
}
else {
LOG.debug("extension '" + extension.getName() + "' contributed by '" + extension.getContibuterBundleId() + "' has neither an UiClass nor a factory defined! Skipping extension.");
break;
}
int distance = -distanceToIFormField(modelClazz, 0);
CompositeObject key = new CompositeObject(distance, modelClazz.getName());
if (sortedMap.containsKey(key)) {
P_FormFieldExtension existingExt = sortedMap.get(key);
// check scope
if (existingExt.getFormFieldExtension().getScope() == extension.getScope()) {
LOG.warn("The bundles '" + extension.getContibuterBundleId() + "' and '" + existingExt.getFormFieldExtension().getContibuterBundleId() + "' are both providing " + "an form field extension to '" + extension.getModelClassName() + "' with the same scope.");
}
else if (existingExt.getFormFieldExtension().getScope() < extension.getScope()) {
// replace
sortedMap.put(key, new P_FormFieldExtension(modelClazz, factory, extension));
}
}
else {
sortedMap.put(key, new P_FormFieldExtension(modelClazz, factory, extension));
}
}
catch (ClassNotFoundException e) {
LOG.debug("local extension '" + extension.getName() + "' contributed by '" + extension.getContibuterBundleId() + "' is not visible from bundle: '" + loaderBundle.getSymbolicName() + "'.");
}
}
}
}
m_fields = new LinkedHashMap<Class<?>, IFormFieldFactory>();
for (P_FormFieldExtension ext : sortedMap.values()) {
m_fields.put(ext.getModelClazz(), ext.getFactory());
}
}
private static int distanceToIFormField(Class<?> visitee, int dist) {
if (visitee == IFormField.class) {
return dist;
}
else {
int locDist = 100000;
Class<?> superclass = visitee.getSuperclass();
if (superclass != null) {
locDist = distanceToIFormField(superclass, (dist + 1));
}
Class[] interfaces = visitee.getInterfaces();
if (interfaces != null) {
for (Class<?> i : interfaces) {
locDist = Math.min(locDist, distanceToIFormField(i, (dist + 1)));
}
}
dist = locDist;
return dist;
}
}
@Override
public ISwingScoutFormField<?> createFormField(JComponent parent, IFormField model, ISwingEnvironment environment) {
IFormFieldFactory factory = null;
for (Entry<Class<?>, IFormFieldFactory> link : m_fields.entrySet()) {
if (link.getKey().isAssignableFrom(model.getClass())) {
// create instance
factory = link.getValue();
try {
return factory.createFormField(parent, model, environment);
}
catch (Throwable e) {
LOG.error("could not create form field for: [model = '" + model.getClass().getName() + "'; ui = '" + factory.toString() + "'].", e);
}
}
}
if (factory != null) {
try {
return factory.createFormField(parent, model, environment);
}
catch (Throwable t) {
t.printStackTrace();
return null;
}
}
return null;
}
private class P_DirectLinkFormFieldFactory implements IFormFieldFactory {
private final Class<? extends ISwingScoutFormField> m_uiClazz;
public P_DirectLinkFormFieldFactory(Class<? extends ISwingScoutFormField> uiClazz) {
m_uiClazz = uiClazz;
}
@SuppressWarnings("unchecked")
@Override
public ISwingScoutFormField<?> createFormField(JComponent parent, IFormField field, ISwingEnvironment environment) {
try {
ISwingScoutFormField newInstance = m_uiClazz.newInstance();
newInstance.createField(field, environment);
return newInstance;
}
catch (Exception e) {
LOG.warn(null, e);
return null;
}
}
@Override
public String toString() {
return "DirectLinkFactory to: " + m_uiClazz.getName();
}
}// end class P_DirectLinkFormFieldFactory
private class P_FormFieldExtension {
private final Class<?> m_modelClazz;
private final IFormFieldFactory m_factory;
private final IFormFieldExtension m_formFieldExtension;
public P_FormFieldExtension(Class<?> modelClazz, IFormFieldFactory factory, IFormFieldExtension formFieldExtension) {
m_modelClazz = modelClazz;
m_factory = factory;
m_formFieldExtension = formFieldExtension;
}
public Class<?> getModelClazz() {
return m_modelClazz;
}
public IFormFieldFactory getFactory() {
return m_factory;
}
public IFormFieldExtension getFormFieldExtension() {
return m_formFieldExtension;
}
} // end class P_FormFieldExtension
}