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

net.contextfw.web.application.component.Component Maven / Gradle / Ivy

package net.contextfw.web.application.component;

import java.util.HashSet;
import java.util.Set;

import net.contextfw.web.application.WebApplicationException;
import net.contextfw.web.application.internal.component.ComponentBuilder;

/**
 * The base class of a component
 *
 */
@Buildable
public abstract class Component {

    private final Set partialUpdates = new HashSet();
    private String partialUpdateName;
    private RefreshMode refreshMode = RefreshMode.NONE;
    private Component parent = null;
    private Set children = null;
    private Set waitingToRegister = null;
    
    private boolean enabled = true;

    private enum RefreshMode {
        NONE, PASS, UPDATE
    };

    @Attribute
    private String id;

    /**
     * Assigns an id for the component
     * 
     * 

* Id is generated automatically by the web framework so setting an id is not necesssary. * the id is of a form el[n] where [n] is an incrementing * value. *

*

* It is also possible to set a custom id, but to be sure that setting succceeds it must be don * during initialization. *

*/ public void setId(String id) { if (this.id != null) { throw new WebApplicationException("Component id can be set only once"); } this.id = id; } /** * Get's component id * *

* The id is null initially, but when component is registered to thes * system id is generated automatically. This means that id may not be in use * at initialization phase and developer should not rely on using id in class properties. *

*/ public String getId() { return id; } /** * Adds a component to be a child of this component. * *

* Registering child components is a mandatory task so that the framework is able to * register all components in the page and assign proper ids for them. *

* *

* Component registering is lazy. If parent component has not yet been registered then * registering for child components is delayd untit parent is also registered. *

* * @param * Component type * @param el * The Component * @return * The added component */ public T registerChild(T el) { if (children == null) { children = new HashSet(); waitingToRegister = new HashSet(); } children.add(el); el.parent = this; if (bubbleRegisterUp(el)) { el.registerChildren(); } else { waitingToRegister.add(el); } return el; } private void registerChildren() { if (waitingToRegister != null) { for (Component comp : waitingToRegister) { registerChild(comp); } waitingToRegister.clear(); } } /** * For internal use only */ protected boolean bubbleRegisterUp(Component el) { if (parent != null) { return parent.bubbleRegisterUp(el); } else { return false; } } /** * For internal use only */ protected void bubbleUnregisterUp(Component el) { if (parent != null) { parent.bubbleUnregisterUp(el); } } /** * Removes child component from the framework */ public void unregisterChild(Component el) { if (children != null) { children.remove(el); bubbleUnregisterUp(el); } } /** * Refreshes component state to web client * *

* When component needs to update its state on web client, this * method must be called. Framework recognizes the request and * creates property update during rendering phase. *

* *

* Note! If paren component also requests update, then the update * of this component is canceled, because in normal circumstances this * component if fully redrawn by the parent component. *

*/ public void refresh() { if (id != null) { refreshMode = RefreshMode.UPDATE; Component p = parent; while (p != null) { if (p.refreshMode == RefreshMode.NONE) { p.refreshMode = RefreshMode.PASS; p = p.parent; } else { p = null; } } } } /** * For internal use only */ public final void buildComponentUpdate(DOMBuilder domBuilder, ComponentBuilder builder) { boolean isNormalUpdate = (partialUpdateName == null); if (refreshMode == RefreshMode.UPDATE) { if (isNormalUpdate) { builder.buildUpdate(domBuilder, this, isNormalUpdate ? "update" : partialUpdateName); } else { builder.buildPartialUpdate(domBuilder, this, isNormalUpdate ? "update" : partialUpdateName, partialUpdates); } } if (refreshMode == RefreshMode.PASS || !isNormalUpdate) { if (children != null) { for (Component child : children) { child.buildComponentUpdate(domBuilder, builder); } } } clearCascadedUpdate(); } /** * Requests a partial update for component * *

* When there is a need to only partially update component, then this method is used *

* * * @param buildName * @param updates */ public void partialRefresh(String buildName, String... updates) { if (partialUpdates != null) { this.partialUpdateName = buildName; for (String partialUpdate : updates) { partialUpdates.add(partialUpdate); } partialUpdates.add("id"); } refresh(); } /** * For internal use only */ public void clearCascadedUpdate() { if (refreshMode == RefreshMode.NONE) return; refreshMode = RefreshMode.NONE; if (children != null) { for (Component child : children) { child.clearCascadedUpdate(); } } partialUpdates.clear(); partialUpdateName = null; } /** * Defines if this component is enabled or disabled. * *

* If component is disabled then it is not added to DOM-tree during rendering phase. Also * disabled component does not listen remote calls. *

* @param enabled */ public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return enabled; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy