Package org.itsnat.impl.comp

Source Code of org.itsnat.impl.comp.ItsNatComponentImpl

/*
  ItsNat Java Web Application Framework
  Copyright (C) 2007-2011 Jose Maria Arranz Santamaria, Spanish citizen

  This software 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.
  This software 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 program.
  If not, see <http://www.gnu.org/licenses/>.
*/

package org.itsnat.impl.comp;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.util.HashMap;
import java.util.Map;
import org.itsnat.comp.ItsNatComponentManager;
import org.itsnat.comp.ItsNatComponentUI;
import org.itsnat.core.ClientDocument;
import org.itsnat.core.ItsNatDOMException;
import org.itsnat.core.ItsNatDocument;
import org.itsnat.core.ItsNatException;
import org.itsnat.core.NameValue;
import org.itsnat.core.event.ItsNatEvent;
import org.itsnat.core.event.ParamTransport;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersAllClientsImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByClientImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByDocImpl;
import org.itsnat.impl.comp.mgr.ItsNatDocComponentManagerImpl;
import org.itsnat.impl.core.ItsNatUserDataImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentAttachedClientImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentImpl;
import org.itsnat.impl.core.doc.ItsNatDocumentImpl;
import org.itsnat.impl.core.domutil.DOMUtilInternal;
import org.itsnat.impl.core.mut.doc.BeforeAfterMutationRenderListener;
import org.itsnat.impl.core.mut.doc.DocMutationEventListenerImpl;
import org.w3c.dom.Node;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.MutationEvent;

/**
*
* @author jmarranz
*/
public abstract class ItsNatComponentImpl extends ItsNatUserDataImpl implements ItsNatComponentInternal,EventListener,BeforeAfterMutationRenderListener
{
    protected ItsNatDocComponentManagerImpl componentMgr;
    protected Map<String,Object> artifacts;
    protected ItsNatCompDOMListenersByDocImpl domListenersByDoc;
    protected ItsNatCompDOMListenersAllClientsImpl domListenersByClient;
    protected boolean disposed = false;
    protected PropertyChangeSupport changeSupport;
    protected VetoableChangeSupport vetoableChangeSupport;
    protected Object dataModel;
    protected ItsNatComponentUI compUI; // puede ser null pues no todos tienen UI (ej. form)
    protected Node node;
    protected boolean hasMutationEventListener = false;
    protected Event currentEvent;

    /** Creates a new instance of ItsNatComponentImpl */
    public ItsNatComponentImpl(Node node,NameValue[] artifacts,ItsNatDocComponentManagerImpl componentMgr)
    {
        super(false);

        this.componentMgr = componentMgr;

        if (artifacts != null)
        {
            Map<String,Object> artifactMap = getArtifactMap();
            for(int i = 0; i < artifacts.length; i++)
            {
                NameValue artif = artifacts[i];
                artifactMap.put(artif.getName(),artif.getValue());
            }
        }

        if (node == null)
            node = createDefaultNode(); // Puede devolver null
        this.node = node; // Se tolera el caso de que sea nulo para permitir un posterior "attach" (ning�n componente est�ndar por ahora)

        this.domListenersByDoc = createItsNatCompDOMListenersByDoc();
        this.domListenersByClient = new ItsNatCompDOMListenersAllClientsImpl(this);
    }

    public void init()
    {
        // Debe llamarse desde alguna clase derivada como parte del proceso de creaci�n
        setDefaultModels();
        setDefaultItsNatComponentUI();

        if (node != null)
        {
            ItsNatDocumentImpl itsNatDoc = getItsNatDocumentImpl();
            if (isNodeBoundToDocument())
            {
                enableEventListeners(); // Hay que tener en cuenta que si no estuviera en el �rbol del documento dar�a error
            }
            else
            {
                // Es un componente preparado para ser a�adido y quitado del �rbol continuamente, es usado por ejemplo por los componentes usados como editores
                DocMutationEventListenerImpl mainListener = itsNatDoc.getDocMutationEventListener();
                mainListener.addBeforeAfterMutationRenderListener(node,this);
                this.hasMutationEventListener = true;

                ItsNatDocComponentManagerImpl compMgr = getItsNatComponentManagerImpl();
                compMgr.addExcludedNodeAsItsNatComponent(node); // Evita que un buildComponents lo a�ada, aunque el nodo no est� unido al �rbol no importa desde el punto de vista del registro de ItsNatDocument
            }
        }

        setEnabled(true);
    }

    public boolean isNodeBoundToDocument()
    {
        return DOMUtilInternal.isNodeInside(node,getItsNatDocumentImpl().getDocument());
    }

    public ItsNatCompDOMListenersAllClientsImpl getItsNatCompDOMListenersAllClients()
    {
        return domListenersByClient;
    }

    public abstract ItsNatCompDOMListenersByDocImpl createItsNatCompDOMListenersByDoc();

    public abstract ItsNatCompDOMListenersByClientImpl createItsNatCompDOMListenersByClient(ClientDocumentImpl clientDoc);

    public ItsNatCompDOMListenersByClientImpl getItsNatCompDOMListenersByClient(ClientDocumentImpl clientDoc)
    {
        return domListenersByClient.getItsNatCompDOMListenersByClient(clientDoc);
    }

    public boolean mayBeInPlaceEditorComponent()
    {
        return hasMutationEventListener;
    }

    public ItsNatCompDOMListenersByDocImpl getItsNatCompDOMListenersByDoc()
    {
        return domListenersByDoc;
    }

    public void setDefaultModels()
    {
        // Derivar para los selection models
        setDefaultDataModel();
    }

    public boolean isDisposed()
    {
        return disposed;
    }

    public void dispose()
    {
        // Derivar disposeEffective(boolean), no dispose()
        if (!disposed)
            disposeEffective(true);
    }

    protected void disposeEffective(boolean updateClient)
    {
        // updateClient es siempre true por ahora

        unbindModels();

        disableEventListeners(updateClient);

        ItsNatDocComponentManagerImpl compMgr = getItsNatComponentManagerImpl();

        compMgr.removeItsNatComponent(this,false);
        if (hasMutationEventListener)
        {
            ItsNatDocumentImpl itsNatDoc = getItsNatDocumentImpl();
            DocMutationEventListenerImpl mainListener = itsNatDoc.getDocMutationEventListener();
            Node node = getNode();
            mainListener.removeBeforeAfterMutationRenderListener(node,this);
            compMgr.removeExcludedNodeAsItsNatComponent(node);
        }
        this.disposed = true;
    }

    public Node getNode()
    {
        return node;
    }

    public void setNode(Node node)
    {
        // Derivar si se permite "reattachment"
        throw new ItsNatDOMException("This component cannot be reattached",node);
    }

    public abstract ItsNatComponentUI createDefaultItsNatComponentUI();

    public void setDefaultItsNatComponentUI()
    {
        setItsNatComponentUI(createDefaultItsNatComponentUI());
    }

    public abstract Node createDefaultNode();

    public ItsNatComponentManager getItsNatComponentManager()
    {
        return componentMgr;
    }

    public ItsNatDocComponentManagerImpl getItsNatComponentManagerImpl()
    {
        return componentMgr;
    }

    public ItsNatDocumentImpl getItsNatDocumentImpl()
    {
        return getItsNatComponentManagerImpl().getItsNatDocumentImpl();
    }

    public ItsNatDocument getItsNatDocument()
    {
        return getItsNatDocumentImpl();
    }

    public ItsNatComponentUI getItsNatComponentUI()
    {
        return compUI;
    }

    public void setItsNatComponentUI(ItsNatComponentUI compUI)
    {
        this.compUI = compUI;
        initialSyncUIWithDataModel();
    }

    public boolean hasArtifacts()
    {
        if (artifacts == null) return false;
        return !artifacts.isEmpty();
    }

    public Map<String,Object> getArtifactMap()
    {
        if (artifacts == null)
            this.artifacts = new HashMap<String,Object>();
        return artifacts;
    }

    public void registerArtifact(String name,Object value)
    {
        Map<String,Object> artifacts = getArtifactMap();
        artifacts.put(name,value);
    }

    public Object getArtifact(String name)
    {
        if (!hasArtifacts()) return null;

        Map<String,Object> artifacts = getArtifactMap();
        return artifacts.get(name);
    }

    public Object removeArtifact(String name)
    {
        Map<String,Object> artifacts = getArtifactMap();
        return artifacts.remove(name);
    }

    public Object getArtifact(String name,boolean cascade)
    {
        Object artif = getArtifact(name);
        if (cascade && (artif == null))
            artif = getItsNatDocumentImpl().getArtifact(name,true);
        return artif;
    }

    public abstract ParamTransport[] getInternalParamTransports(String type,ClientDocumentImpl clientDoc);

    public void setEventListenerParams(String type,boolean useCapture,int commMode,
            ParamTransport[] extraParams,String preSendCode,long eventTimeout)
    {
        domListenersByDoc.setEventListenerParams(type, useCapture, commMode, extraParams, preSendCode, eventTimeout);
    }

    /* DEBE HACERSE PUBLICA */
    public void setEventListenerParams(ClientDocument clientDoc,String type,boolean useCapture,int commMode,
            ParamTransport[] extraParams,String preSendCode,long eventTimeout)
    {
        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.getItsNatCompDOMListenersByClient((ClientDocumentImpl)clientDoc);       
        domListeners.setEventListenerParams(type, useCapture, commMode, extraParams, preSendCode, eventTimeout);
    }

    public void addEventListener(String type,EventListener listener)
    {
        addEventListener(type, listener,false);
    }

    public void removeEventListener(String type,EventListener listener)
    {
        removeEventListener(type, listener,false);
    }

    public void addEventListener(String type,EventListener listener,boolean before)
    {
        domListenersByDoc.addUserEventListener(type,listener,before);
    }

    public void removeEventListener(String type,EventListener listener,boolean before)
    {
        domListenersByDoc.removeUserEventListener(type,listener,before);
    }

    public void enableEventListener(String type)
    {
        domListenersByDoc.enableEventListener(type);
    }

    public void disableEventListener(String type)
    {
        domListenersByDoc.disableEventListener(type);
    }

    /* DEBE HACERSE PUBLICO */
    public void addEventListener(ClientDocument clientDoc,String type,EventListener listener)
    {
        addEventListener(clientDoc,type, listener,false);
    }

    /* DEBE HACERSE PUBLICO */
    public void removeEventListener(ClientDocument clientDoc,String type,EventListener listener)
    {
        removeEventListener(clientDoc,type, listener,false);
    }

    /* DEBE HACERSE PUBLICO */
    public void addEventListener(ClientDocument clientDoc,String type,EventListener listener,boolean before)
    {
        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.getItsNatCompDOMListenersByClient((ClientDocumentImpl)clientDoc);
        domListeners.addUserEventListener(type,listener,before);
    }

    /* DEBE HACERSE PUBLICO */
    public void removeEventListener(ClientDocument clientDoc,String type,EventListener listener,boolean before)
    {
        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.getItsNatCompDOMListenersByClient((ClientDocumentImpl)clientDoc);
        domListeners.removeUserEventListener(type,listener,before);
    }

    /* DEBE HACERSE PUBLICO */
    public void enableEventListener(ClientDocument clientDoc,String type)
    {
        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.getItsNatCompDOMListenersByClient((ClientDocumentImpl)clientDoc);
        domListeners.enableEventListener(type);
    }

    /* DEBE HACERSE PUBLICO */
    public void disableEventListener(ClientDocument clientDoc,String type)
    {
        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.getItsNatCompDOMListenersByClient((ClientDocumentImpl)clientDoc);
        domListeners.disableEventListener(type);
    }

    public void enableEventListener(String type,ItsNatCompDOMListenersByClientImpl domListeners)
    {
        domListeners.enableEventListener(type);
    }

    public void disableEventListener(String type,ItsNatCompDOMListenersByClientImpl domListeners)
    {
        domListeners.disableEventListener(type);
    }

    public void enableEventListeners()
    {
        enableEventListenersByDoc();
        enableEventListenersByClient();
    }

    public void disableEventListeners()
    {
        disableEventListeners(true);
    }

    public void disableEventListeners(boolean updateClient)
    {
        disableEventListenersByDoc(updateClient);
        disableEventListenersByClient(updateClient);
    }

    public void enableEventListenersByDoc()
    {
        // Derivar para a�adir los event type concretos.
    }

    public void disableEventListenersByDoc()
    {
        disableEventListenersByDoc(true);
    }

    public void disableEventListenersByDoc(boolean updateClient)
    {
        domListenersByDoc.disableEventListeners(updateClient);
    }

    public void enableEventListenersByClient()
    {
        ItsNatCompDOMListenersByClientImpl[] clients = domListenersByClient.getAllItsNatCompDOMListenersByClient();
        for(int i = 0; i < clients.length; i++)
            enableEventListenersByClient(clients[i]);
    }

    public void disableEventListenersByClient()
    {
        disableEventListenersByClient(true);
    }

    public void disableEventListenersByClient(boolean updateClient)
    {
        ItsNatCompDOMListenersByClientImpl[] clients = domListenersByClient.getAllItsNatCompDOMListenersByClient();
        for(int i = 0; i < clients.length; i++)
            disableEventListenersByClient(updateClient,clients[i]);
    }

    public void enableEventListenersByClient(ItsNatCompDOMListenersByClientImpl domListeners)
    {
       // Derivar para registrar los event type concretos
    }

    public void disableEventListenersByClient(ItsNatCompDOMListenersByClientImpl domListeners)
    {
        disableEventListenersByClient(true,domListeners);
    }

    public void disableEventListenersByClient(boolean updateClient,ItsNatCompDOMListenersByClientImpl domListeners)
    {
        domListeners.disableEventListeners(updateClient);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener)
    {
        if (listener == null)
            return;

        if (changeSupport == null)
            changeSupport = new PropertyChangeSupport(this);

        changeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener)
    {
        if (listener == null || changeSupport == null)
            return;

        changeSupport.removePropertyChangeListener(listener);
    }

    public PropertyChangeListener[] getPropertyChangeListeners()
    {
        if (changeSupport == null)
            return new PropertyChangeListener[0];

        return changeSupport.getPropertyChangeListeners();
    }

    public void addPropertyChangeListener(String propertyName,PropertyChangeListener listener)
    {
        if (listener == null)
            return;

        if (changeSupport == null)
            changeSupport = new PropertyChangeSupport(this);

        changeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener(String propertyName,PropertyChangeListener listener)
    {
        if (listener == null || changeSupport == null)
            return;

        changeSupport.removePropertyChangeListener(propertyName, listener);
    }

    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName)
    {
        if (changeSupport == null)
            return new PropertyChangeListener[0];

        return changeSupport.getPropertyChangeListeners(propertyName);
    }

    protected void firePropertyChange(String propertyName,Object oldValue, Object newValue)
    {
        PropertyChangeSupport changeSupport = this.changeSupport;
        if ((changeSupport == null) ||
            ((oldValue != null) && (newValue != null) && oldValue.equals(newValue)))
            return;

        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    public void addVetoableChangeListener(VetoableChangeListener listener)
    {
        if (listener == null)
            return;

        if (vetoableChangeSupport == null)
            vetoableChangeSupport = new VetoableChangeSupport(this);

        vetoableChangeSupport.addVetoableChangeListener(listener);
    }

    public void removeVetoableChangeListener(VetoableChangeListener listener)
    {
        if (listener == null || changeSupport == null)
            return;

        vetoableChangeSupport.removeVetoableChangeListener(listener);
    }

    public VetoableChangeListener[] getVetoableChangeListeners()
    {
        if (vetoableChangeSupport == null)
            return new VetoableChangeListener[0];

        return vetoableChangeSupport.getVetoableChangeListeners();
    }

    protected void fireVetoableChange(String propertyName,Object oldValue, Object newValue) throws PropertyVetoException
    {
        if (vetoableChangeSupport == null)
            return;
        // Incluso aunque sea igual el valor hacemos fire as� podemos detectar un intento de cambio (aunque sea al mismo valor) de una propiedad de s�lo lectura
        // de igual manera que se hace en JComponent
        vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
    }

    public void setDefaultDataModel()
    {
        Object dataModel = createDefaultModelInternal();
        if (dataModel != null)
            setDefaultDataModel(dataModel);
        // Si es null es que no tiene modelo
    }

    public void setDefaultDataModel(Object dataModel)
    {
        setDataModel(dataModel);
    }

    public void unbindModels()
    {
        unbindDataModel();
    }

    public abstract void bindDataModel();
    public abstract void unbindDataModel();

    public Object getDataModel()
    {
        return dataModel;
    }

    public void setDataModel(Object dataModel)
    {
        setDataModel(dataModel,false);
    }

    public void setDataModel(Object dataModel,boolean acceptNull)
    {
        if ((dataModel == null) && !acceptNull)
            throw new ItsNatException("Data model cannot be null",this);

        // Aunque el nuevo modelo sea el mismo que el que ya hay
        // hacemos unbindDataModel() siempre pues de esta manera podemos hacer
        // una especie de reset, �ste es �til para poder a�adir un listener desde fuera
        // que se llame antes del listener interno en el caso del data model
        // por defecto, si se hace "reset" el listener se quitar� y se a�adir� de nuevo
        // quedando el �ltimo.

        if (this.dataModel != null)
            unbindDataModel();

        this.dataModel = dataModel;

        // El dataModel del usuario manda sobre el DOM
        initialSyncWithDataModel();

        // A partir de ahora los cambios los repercutimos en el DOM por eventos
        // No se debe cambiar el DOM por otra v�a que por el objeto dataModel
        bindDataModel();
    }

    public Event getCurrentEventProcessing()
    {
        return currentEvent;
    }

    public void setCurrentEventProcessing(Event currentEvent)
    {
        this.currentEvent = currentEvent;
    }

    public void handleEvent(Event evt)
    {
        if (!isEnabled()) return;

        setCurrentEventProcessing(evt);

        try
        {
            processDOMEventUserListeners(evt,true);
            ItsNatEvent itsNatEvt = ((ItsNatEvent)evt);
            if (!itsNatEvt.getItsNatEventListenerChain().isStopped()) // De esta manera en los eventos del usuario previos podemos parar el comportamiento por defecto del componente
                processDOMEvent(evt);
            processDOMEventUserListeners(evt,false);
        }
        finally
        {
            setCurrentEventProcessing(null);
        }
    }

    public void processDOMEventUserListeners(Event evt,boolean before)
    {
        if (((ItsNatEvent)evt).getItsNatEventListenerChain().isStopped())
            return; // No es estrictamente necesario (se chequea despu�s) pero evita llamadas in�tiles
           
        domListenersByDoc.processDOMEventUserListeners(evt,before);

        if (((ItsNatEvent)evt).getItsNatEventListenerChain().isStopped())
            return; // No es estrictamente necesario (se chequea despu�s) pero evita llamadas in�tiles

        // Por ahora no hay listeners por cliente, pero en el futuro...
        ItsNatCompDOMListenersByClientImpl[] clients = domListenersByClient.getAllItsNatCompDOMListenersByClient();
        for(int i = 0; i < clients.length; i++)
            clients[i].processDOMEventUserListeners(evt, before);
    }

    public void processDOMEvent(Event evt)
    {
        // Derivar para hacer lo espec�fico del componente
    }

    public void initialSyncWithDataModel()
    {
        if (getItsNatComponentUI() != null)
            initialSyncUIWithDataModel();
    }

    public void beforeRender(Node node,MutationEvent evt)
    {
        String type = evt.getType();
        if (type.equals("DOMNodeRemoved"))
        {
            // Quitamos el listener porque si se a�ade de nuevo el nodo
            // al documento, en el cliente ser� un objeto nuevo por lo que
            // habr� que registrar de nuevo el listener
            disableEventListeners();
        }
    }

    public void afterRender(Node node,MutationEvent evt)
    {
        String type = evt.getType();
        if (type.equals("DOMNodeInserted"))
        {
            enableEventListeners();
        }
    }

    public void addClientDocumentAttachedClient(ClientDocumentAttachedClientImpl clientDoc)
    {
        domListenersByDoc.addClientDocumentAttachedClient(clientDoc);

        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.addItsNatCompDOMListenersByClient(clientDoc);
        if (isNodeBoundToDocument())
            enableEventListenersByClient(domListeners);
    }

    public void removeClientDocumentAttachedClient(ClientDocumentAttachedClientImpl clientDoc)
    {
        domListenersByDoc.removeClientDocumentAttachedClient(clientDoc);

        ItsNatCompDOMListenersByClientImpl domListeners = domListenersByClient.removeItsNatCompDOMListenersByClient(clientDoc);
        if (isNodeBoundToDocument())
            disableEventListenersByClient(false,domListeners); // updateClient = false para evitar generaci�n in�til de c�digo
    }
}
TOP

Related Classes of org.itsnat.impl.comp.ItsNatComponentImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.