org.jspresso.framework.application.model.BeanModule.java Source code

Java tutorial

Introduction

Here is the source code for org.jspresso.framework.application.model.BeanModule.java

Source

/*
 * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved.
 *
 *  This file is part of the Jspresso framework.
 *
 *  Jspresso is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Jspresso 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 Jspresso.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jspresso.framework.application.model;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Collections;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import org.jspresso.framework.application.backend.IBackendController;
import org.jspresso.framework.application.model.descriptor.BeanModuleDescriptor;
import org.jspresso.framework.model.descriptor.IComponentDescriptor;
import org.jspresso.framework.model.descriptor.IComponentDescriptorProvider;
import org.jspresso.framework.util.bean.IPropertyChangeCapable;
import org.jspresso.framework.util.lang.ObjectUtils;
import org.jspresso.framework.view.descriptor.EBorderType;
import org.jspresso.framework.view.descriptor.IViewDescriptor;
import org.jspresso.framework.view.descriptor.basic.BasicBorderViewDescriptor;
import org.jspresso.framework.view.descriptor.basic.BasicComponentViewDescriptor;
import org.jspresso.framework.view.descriptor.basic.BasicViewDescriptor;

/**
 * This type of module keeps a reference on a single bean. There is no
 * assumption made on whether this bean is actually a persistent entity or any
 * other type of java bean.
 * <p>
 * Bean modules must have their referenced bean initialized somehow. So it's
 * rather common to have the module content initialized through a startup action
 * depending on the session state or dynamically constructed by a standard
 * action like {@code AddBeanAsSubModuleAction}.
 * <p>
 * This type of module is definitely the one that offers maximum flexibility to
 * handle arbitrary models.
 *
 * @author Vincent Vandenschrick
 */
public class BeanModule extends Module implements PropertyChangeListener {

    /**
     * {@code MODULE_OBJECT} is "moduleObject".
     */
    public static final String MODULE_OBJECT = "moduleObject";

    private IComponentDescriptor<Object> componentDescriptor;
    private Object moduleObject;

    /**
     * Equality based on projected object.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof BeanModule)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        BeanModule rhs = (BeanModule) obj;
        EqualsBuilder equalsBuilder = new EqualsBuilder().appendSuper(super.equals(obj));
        if (moduleObject != null) {
            equalsBuilder.append(moduleObject, rhs.moduleObject);
        }
        return equalsBuilder.isEquals();
    }

    /**
     * Gets the componentDescriptor.
     *
     * @return the componentDescriptor.
     */
    @SuppressWarnings("unchecked")
    public IComponentDescriptor<?> getComponentDescriptor() {
        if (componentDescriptor == null) {
            if (getProjectedViewDescriptor() != null && getProjectedViewDescriptor()
                    .getModelDescriptor() instanceof IComponentDescriptorProvider<?>) {
                return ((IComponentDescriptorProvider<Object>) getProjectedViewDescriptor().getModelDescriptor())
                        .getComponentDescriptor();
            }
        }
        return componentDescriptor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<String> getGrantedRoles() {
        Collection<String> grantedRoles = super.getGrantedRoles();
        if (grantedRoles == null && componentDescriptor != null) {
            grantedRoles = componentDescriptor.getGrantedRoles();
        }
        return grantedRoles;
    }

    /**
     * Gets the module's projected object.
     *
     * @return the projected object.
     */
    public Object getModuleObject() {
        return moduleObject;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IViewDescriptor getProjectedViewDescriptor() {
        IViewDescriptor projectedViewDescriptor = super.getProjectedViewDescriptor();
        if (componentDescriptor != null) {
            if (projectedViewDescriptor == null) {
                projectedViewDescriptor = createDefaultProjectedViewDescriptor();
                setProjectedViewDescriptor(projectedViewDescriptor);
            }
            if (projectedViewDescriptor.getModelDescriptor() == null
                    && projectedViewDescriptor instanceof BasicViewDescriptor) {
                ((BasicViewDescriptor) projectedViewDescriptor).setModelDescriptor(componentDescriptor);
            }
        }
        return projectedViewDescriptor;
    }

    /**
     * Create default projected view descriptor.
     *
     * @return the view descriptor
     */
    protected IViewDescriptor createDefaultProjectedViewDescriptor() {
        BasicComponentViewDescriptor defaultProjectedViewDescriptor = new BasicComponentViewDescriptor();
        defaultProjectedViewDescriptor.setModelDescriptor(componentDescriptor);
        defaultProjectedViewDescriptor.setBorderType(EBorderType.TITLED);
        defaultProjectedViewDescriptor.setName(componentDescriptor.getName());
        defaultProjectedViewDescriptor.setColumnCount(3);
        return defaultProjectedViewDescriptor;
    }

    /**
     * Returns the projectedViewDescriptor nested in a "moduleObject" property
     * view.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public IViewDescriptor getViewDescriptor() {
        if (getProjectedViewDescriptor() != null) {
            BeanModuleDescriptor beanModuleDescriptor = getDescriptor();
            BasicBorderViewDescriptor nestingViewDescriptor = new BasicBorderViewDescriptor();
            nestingViewDescriptor.setCenterViewDescriptor(getProjectedViewDescriptor());
            nestingViewDescriptor.setModelDescriptor(beanModuleDescriptor.getPropertyDescriptor(MODULE_OBJECT));
            BasicBorderViewDescriptor viewDescriptor = new BasicBorderViewDescriptor();
            viewDescriptor.setModelDescriptor(beanModuleDescriptor);
            viewDescriptor.setCenterViewDescriptor(nestingViewDescriptor);
            return viewDescriptor;
        }
        return null;
    }

    /**
     * Hash code based on projected object.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return new HashCodeBuilder(23, 53).append(getModuleObject()).toHashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String oldI18nName = getI18nName();
        setI18nName(String.valueOf(this.moduleObject));
        firePropertyChange(I18N_NAME, oldI18nName, getI18nName());
    }

    /**
     * Configures the type of bean this module manages. A bunch of default values
     * are inferred from this component descriptor. For instance, icon image URL
     * or even granted roles can be inferred from the configured component
     * descriptor. The latter means that bean modules based on forbidden entities
     * will automatically be excluded from the workspace of the logged-in user.
     * <p>
     * However, when not set, the component descriptor it self can be inferred from
     * the configured projected view descriptor model.
     *
     * @param componentDescriptor
     *          the componentDescriptor to set.
     */
    public void setComponentDescriptor(IComponentDescriptor<Object> componentDescriptor) {
        this.componentDescriptor = componentDescriptor;
    }

    /**
     * Assigns the bean this module manages. The projected view will automatically
     * reflect this change since a &quot;moduleObject&quot; property change will
     * be fired.
     *
     * @param moduleObject
     *          the projected object.
     */
    public void setModuleObject(Object moduleObject) {
        if (ObjectUtils.equals(this.moduleObject, moduleObject)) {
            return;
        }
        String toStringProperty = getComponentDescriptor().getToStringProperty();
        if (getName() == null && this.moduleObject instanceof IPropertyChangeCapable) {
            if (toStringProperty != null) {
                ((IPropertyChangeCapable) this.moduleObject).removePropertyChangeListener(toStringProperty, this);
            } else {
                ((IPropertyChangeCapable) this.moduleObject).removePropertyChangeListener(this);
            }
        }
        Object oldValue = getModuleObject();
        this.moduleObject = moduleObject;
        if (getName() == null && this.moduleObject instanceof IPropertyChangeCapable) {
            if (toStringProperty != null) {
                ((IPropertyChangeCapable) this.moduleObject).addPropertyChangeListener(toStringProperty, this);
            } else {
                ((IPropertyChangeCapable) this.moduleObject).addPropertyChangeListener(this);
            }
        }
        firePropertyChange(MODULE_OBJECT, oldValue, getModuleObject());
    }

    /**
     * Gets the module descriptor.
     *
     * @return the module descriptor.
     */
    protected BeanModuleDescriptor getDescriptor() {
        return new BeanModuleDescriptor(getComponentDescriptor());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public BeanModule clone() {
        BeanModule clone = (BeanModule) super.clone();
        clone.moduleObject = null;
        return clone;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isLocallyDirty(IBackendController backendController) {
        boolean locallyDirty = backendController.isAnyDirtyInDepth(Collections.singleton(getModuleObject()));
        return locallyDirty;
    }
}