org.richfaces.cdk.model.ComponentLibrary Maven / Gradle / Ivy
The newest version!
/*
* $Id$
*
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.richfaces.cdk.model;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import org.richfaces.cdk.util.JavaUtils;
import org.richfaces.cdk.util.Strings;
import com.google.inject.Singleton;
/**
*
* That class contains model of all JSF components asscoiated with that project
*
*
* To keep consistence of library references, only library methods are allowed to components manipulations.
*
*
* @author [email protected]
*
*/
@Singleton
public class ComponentLibrary implements Serializable, Extensible, Trackable, Visitable, Cacheable {
public static final String CDK_EXTENSIONS_NAMESPACE = "http://jboss.org/schema/richfaces/cdk/extensions";
public static final String FACES_CONFIG_NAMESPACE = "http://java.sun.com/xml/ns/javaee";
public static final String FACES_CONFIG_SCHEMA_LOCATION = "http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd";
public static final String TAGLIB_SCHEMA_LOCATION = "http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd";
private static final long serialVersionUID = -6055670836731899832L;
private final ModelCollection components = ModelSet.create();
/**
*
* JSF renderer associated with that library
*
*/
private final ModelCollection renderKits = ModelSet.create();
private final ModelCollection converters = ModelSet.create();
private final ModelCollection validators = ModelSet.create();
private final ModelCollection listeners = ModelSet.create();
private final ModelCollection functions = ModelSet.create();
private long lastModified = Long.MIN_VALUE;
/**
*
* Application level events fired by the component
*
*/
private final ModelCollection events = ModelSet.create();
private final ModelCollection behaviors = ModelSet.create();
private ConfigExtension extension = new ConfigExtension();
private String prefix;
private Taglib taglib;
private boolean metadataComplete;
/**
*
*
*
*/
public ComponentLibrary() {
}
public R accept(Visitor visitor, D data) {
R result = visitor.visitComponentLibrary(this, data);
result = renderKits.accept(result, visitor, data);
result = components.accept(result, visitor, data);
result = converters.accept(result, visitor, data);
result = validators.accept(result, visitor, data);
result = listeners.accept(result, visitor, data);
result = events.accept(result, visitor, data);
result = behaviors.accept(result, visitor, data);
result = functions.accept(result, visitor, data);
return result;
}
/**
*
*
*
* @param renderKitId
* @return
*/
public RenderKitModel addRenderKit(String renderKitId) {
FacesId renderKitType = new FacesId(renderKitId);
RenderKitModel renderKit = addRenderKit(renderKitType);
return renderKit;
}
public RenderKitModel addRenderKit(FacesId renderKitType) {
RenderKitModel renderKit = getRenderKit(renderKitType);
if (null == renderKit) {
renderKit = new RenderKitModel();
renderKit.setId(renderKitType);
renderKits.add(renderKit);
}
return renderKit;
}
/**
*
*
*
* @return the components
*/
public ModelCollection getComponents() {
return components;
}
public ComponentModel getComponentByRenderer(FacesId family, FacesId rendererType) {
if (family == null) {
return null;
}
for (ComponentModel component : components) {
if (family.equals(component.getFamily()) && rendererType.equals(component.getRendererType())) {
return component;
}
}
return null;
}
public ComponentModel getComponentByType(FacesId componentType) {
for (ComponentModel component : components) {
if (componentType.equals(component.getId())) {
return component;
}
}
return null;
}
public ComponentModel getComponentByFamily(FacesId family) {
if (family == null) {
return null;
}
for (ComponentModel component : components) {
if (family.equals(component.getFamily())) {
return component;
}
}
return null;
}
public ComponentModel getComponentByFamily(String componentFamily) {
return getComponentByFamily(FacesId.parseId(componentFamily));
}
public RendererModel getRendererByType(FacesId rendererType) {
for (RenderKitModel renderKit : getRenderKits()) {
for (RendererModel renderer : renderKit.getRenderers()) {
if (rendererType.equals(renderer.getId())) {
return renderer;
}
}
}
return null;
}
/**
*
*
*
* @return the renderKits
*/
public ModelCollection getRenderKits() {
return renderKits;
}
public RenderKitModel getRenderKit(FacesId id) {
if (null != id) {
for (RenderKitModel renderKit : renderKits) {
if (id.equals(renderKit.getId())) {
return renderKit;
}
}
}
return null;
}
public void addRenderer(FacesId renderKitId, RendererModel rendererModel) {
RenderKitModel renderKit = addRenderKit(renderKitId);
renderKit.getRenderers().add(rendererModel);
}
public void addRenderer(String renderKitId, RendererModel rendererModel) {
this.addRenderer(new FacesId(renderKitId), rendererModel);
}
public RendererModel getRenderer(String componentFamily, String componentType) {
if (Strings.isEmpty(componentFamily)) {
return null;
}
List res = new ArrayList();
for (RenderKitModel renderKitModel : renderKits) {
for (RendererModel rendererModel : renderKitModel.getRenderers()) {
if (componentFamily.equals(rendererModel.getFamily())) {
res.add(rendererModel);
}
}
}
if (res.size() == 0) {
return null;
}
if (res.size() > 1) {
for (RendererModel renderer : res) {
String rendererComponentType = renderer.getComponentType();
if (componentType.equals(rendererComponentType)) {
return renderer;
}
}
}
return res.get(0);
}
/**
*
*
*
* @return the converters
*/
public ModelCollection getConverters() {
return converters;
}
/**
*
*
*
* @return the validators
*/
public ModelCollection getValidators() {
return validators;
}
/**
*
*
*
* @return the behaviors
*/
public ModelCollection getBehaviors() {
return behaviors;
}
/**
*
*
*
* @return the listeners
*/
public ModelCollection getListeners() {
return listeners;
}
/**
*
*
*
* @return the events
*/
public ModelCollection getEvents() {
return events;
}
/**
*
*
*
* @return the functions
*/
public ModelCollection getFunctions() {
return this.functions;
}
/**
*
*
*
* @return the extension
*/
public ConfigExtension getExtension() {
return extension;
}
/**
*
*
*
* @param extension the extension to set
*/
public void setExtension(ConfigExtension extension) {
this.extension = extension;
}
/**
*
*
*
* @return the metadataComplete
*/
public boolean isMetadataComplete() {
return this.metadataComplete;
}
/**
*
*
*
* @param metadataComplete the metadataComplete to set
*/
public void setMetadataComplete(boolean metadataComplete) {
this.metadataComplete = metadataComplete;
}
public Boolean getMetadataComplete() {
return metadataComplete;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Taglib getTaglib() {
return taglib;
}
public void setTaglib(Taglib taglib) {
this.taglib = taglib;
}
@Override
public long lastModified() {
return lastModified;
}
/**
*
* Check that library is empty
*
*
*
* @return
*/
public boolean isEmpty() {
return this.getComponents().isEmpty() && this.getBehaviors().isEmpty() && this.getConverters().isEmpty()
&& this.getEvents().isEmpty() && this.getFunctions().isEmpty() && this.getListeners().isEmpty()
&& this.getRenderKits().isEmpty() && this.getValidators().isEmpty()
&& (null == this.getExtension() || this.getExtension().getExtensions().isEmpty());
}
static > void merge(Collection target, Collection source) {
for (T element : source) {
T targetElement = null;
try {
// TODO - lookup for equivalent element in target collection.
// find(target, element.getKey());
} catch (NoSuchElementException e) {
// TODO: handle exception
}
if (null == targetElement) {
target.add(element);
} else {
targetElement.merge(element);
}
}
}
static > void merge(T target, T source) {
try {
PropertyDescriptor[] properties = Introspector.getBeanInfo(target.getClass()).getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : properties) {
Method readMethod = propertyDescriptor.getReadMethod();
Method writeMethod = propertyDescriptor.getWriteMethod();
if (null != readMethod && null != writeMethod && readMethod.isAnnotationPresent(Merge.class)) {
boolean preferTrue = readMethod.getAnnotation(Merge.class).preferTrue();
boolean overwrite = readMethod.getAnnotation(Merge.class).overwrite();
Object oldValue = readMethod.invoke(target);
Object newValue = readMethod.invoke(source);
if (preferTrue) {
if (boolean.class == readMethod.getReturnType()) {
if ((Boolean) oldValue || (Boolean) newValue) {
writeMethod.invoke(target, Boolean.TRUE);
continue;
}
} else {
throw new IllegalStateException("@Merge methods can be enforceTrue=true only for boolean properties: " + readMethod);
}
}
if (null != newValue && (overwrite || null == oldValue)) {
writeMethod.invoke(target, newValue);
}
}
}
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
}
}
public void merge(ComponentLibrary library) {
this.getComponents().addAll(library.getComponents());
this.getRenderKits().addAll(library.getRenderKits());
this.getConverters().addAll(library.getConverters());
this.getValidators().addAll(library.getValidators());
this.getBehaviors().addAll(library.getBehaviors());
this.getFunctions().addAll(library.getFunctions());
this.getEvents().addAll(library.getEvents());
if (null != library.getMetadataComplete()) {
this.setMetadataComplete(library.getMetadataComplete());
}
this.getExtension().getExtensions().addAll(library.getExtension().getExtensions());
if (null != library.getTaglib()) {
if (null == this.getTaglib()) {
this.setTaglib(library.getTaglib());
} else {
JavaUtils.copyProperties(library.getTaglib(), this.getTaglib());
}
}
if (null != library.getPrefix()) {
this.setPrefix(library.getPrefix());
}
}
@Override
public void markUnchanged() {
for (RenderKitModel renderKit : getRenderKits()) {
for (RendererModel renderer : renderKit.getRenderers()) {
renderer.markUnchanged();
}
}
for (ComponentModel component : getComponents()) {
component.markUnchanged();
}
}
/**
* This method does not track all changes in library,
* but only models marked as {@link Cacheable}.
*/
@Override
public boolean hasChanged() {
for (RenderKitModel renderKit : getRenderKits()) {
for (RendererModel renderer : renderKit.getRenderers()) {
if (renderer.hasChanged()) {
return true;
}
}
}
for (ComponentModel component : getComponents()) {
if (component.hasChanged()) {
return true;
}
}
return false;
}
@Override
public void stopTrackingChanges() {
for (RenderKitModel renderKit : getRenderKits()) {
for (RendererModel renderer : renderKit.getRenderers()) {
renderer.stopTrackingChanges();
}
}
for (ComponentModel component : getComponents()) {
component.stopTrackingChanges();
}
}
}