Package org.itsnat.impl.core.doc

Source Code of org.itsnat.impl.core.doc.ItsNatStfulDocumentImpl

/*
  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.core.doc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
import org.itsnat.core.ItsNatException;
import org.itsnat.core.ItsNatServletRequest;
import org.itsnat.core.ItsNatServletResponse;
import org.itsnat.core.event.CodeToSendListener;
import org.itsnat.core.event.ItsNatAttachedClientEventListener;
import org.itsnat.core.event.ItsNatServletRequestListener;
import org.itsnat.core.event.ParamTransport;
import org.itsnat.core.script.ScriptUtil;
import org.itsnat.impl.comp.mgr.ItsNatStfulDocComponentManagerImpl;
import org.itsnat.impl.core.*;
import org.itsnat.impl.core.browser.Browser;
import org.itsnat.impl.core.clientdoc.ClientDocStfulTask;
import org.itsnat.impl.core.clientdoc.ClientDocumentAttachedClientImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentStfulImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentStfulOwnerImpl;
import org.itsnat.impl.core.domimpl.ElementDocContainer;
import org.itsnat.impl.core.event.CodeToSendEventImpl;
import org.itsnat.impl.core.event.CodeToSendListenersImpl;
import org.itsnat.impl.core.event.server.ServerItsNatDOMEventImpl;
import org.itsnat.impl.core.event.server.domstd.ServerItsNatDOMStdEventImpl;
import org.itsnat.impl.core.jsren.JSScriptUtilFromDocImpl;
import org.itsnat.impl.core.listener.domext.ItsNatDOMExtEventListenerWrapperImpl;
import org.itsnat.impl.core.listener.domext.ItsNatUserEventListenerWrapperImpl;
import org.itsnat.impl.core.listener.domstd.ItsNatDOMStdEventListenerWrapperImpl;
import org.itsnat.impl.core.mut.doc.DocMutationEventListenerStfulImpl;
import org.itsnat.impl.core.registry.ItsNatDOMStdEventListenerRegistryImpl;
import org.itsnat.impl.core.registry.ItsNatUserEventListenerRegistryImpl;
import org.itsnat.impl.core.servlet.ItsNatServletConfigImpl;
import org.itsnat.impl.core.servlet.ItsNatServletRequestImpl;
import org.itsnat.impl.core.servlet.ItsNatSessionImpl;
import org.itsnat.impl.core.template.ItsNatDocumentTemplateVersionImpl;
import org.itsnat.impl.core.template.ItsNatStfulDocumentTemplateVersionImpl;
import org.itsnat.impl.core.util.MapUniqueId;
import org.itsnat.impl.core.util.WeakSetImpl;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventException;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;

/**
*
* @author jmarranz
*/
public abstract class ItsNatStfulDocumentImpl extends ItsNatDocumentImpl
{
    protected JSScriptUtilFromDocImpl jsScriptUtil;
    protected ItsNatDOMStdEventListenerRegistryImpl domStdListenerRegistry;
    protected ItsNatUserEventListenerRegistryImpl userListenerRegistry;
    protected boolean enabledSendCode = true;
    protected WeakSetImpl<ClientDocumentAttachedClientImpl> clientDocAttachedSet; // No se utilizan ids (pues pueden ser generados por otras sesiones), se utiliza la identidad del objeto
    protected int commMode;
    protected long eventTimeout;
    protected CodeToSendListenersImpl codeToSendListeners;
    protected LinkedList<EventListener> globalDomEventListeners;
    protected LinkedList<ItsNatAttachedClientEventListener> attachedClientListeners;
    protected LinkedList<ItsNatServletRequestListener> referrerRequestListeners;
    protected transient ThreadLocal<ClientDocumentStfulImpl> evtDispThreadLocal = new ThreadLocal<ClientDocumentStfulImpl>();
    protected long evtDispMaxWait;
    protected int maxOpenClients;
    protected MapUniqueId<BoundElementDocContainerImpl> boundElemDocContainers;
    protected Random random;

   
    /** Creates a new instance of ItsNatStfulDocumentImpl */
    public ItsNatStfulDocumentImpl(Document doc,ItsNatDocumentTemplateVersionImpl docTemplate,Browser browser,String requestURL,ItsNatSessionImpl ownerSession,boolean stateless)
    {
        super(doc,docTemplate,browser,requestURL,ownerSession,stateless);

        this.commMode = docTemplate.getCommMode();
        this.eventTimeout = docTemplate.getEventTimeout();
        this.evtDispMaxWait = docTemplate.getEventDispatcherMaxWait();
        this.maxOpenClients = docTemplate.getMaxOpenClientsByDocument();
    }

    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
    {
        this.evtDispThreadLocal = new ThreadLocal<ClientDocumentStfulImpl>();

        in.defaultReadObject();
    }

   
    public ItsNatStfulDocComponentManagerImpl getItsNatStfulComponentManager()
    {
        return (ItsNatStfulDocComponentManagerImpl)componentMgr;
    }

    public DocMutationEventListenerStfulImpl getDocMutationListenerEventStful()
    {
        return (DocMutationEventListenerStfulImpl)mutationListener;
    }

    public boolean canRenderAndSendMutationJSCode()
    {
        boolean loading = isLoading();
        return !loading || (loading && !isFastLoadMode());
    }

    public ItsNatStfulDocumentTemplateVersionImpl getItsNatStfulDocumentTemplateVersion()
    {
        return (ItsNatStfulDocumentTemplateVersionImpl)docTemplateVersion;
    }

    public ClientDocumentImpl createClientDocumentOwner(Browser browser,ItsNatSessionImpl ownerSession)
    {
        return new ClientDocumentStfulOwnerImpl(this,browser,ownerSession);
    }

    public ClientDocumentStfulOwnerImpl getClientDocumentStfulOwner()
    {
        return (ClientDocumentStfulOwnerImpl)clientDocOwner;
    }

    public ClientDocumentStfulImpl getRequestingClientDocumentStful()
    {
        ItsNatServletRequestImpl request = getCurrentItsNatServletRequest();
        if (request != null) return (ClientDocumentStfulImpl)request.getClientDocumentImpl(); // No puede ser null el ClientDocument devuelto (no tiene sentido en este contexto)
        return getClientDocumentStfulOwner(); // Caso de que no haya un request en proceso
    }

    public ScriptUtil getScriptUtil()
    {
        return getJSScriptUtilFromDocImpl();
    }

    public JSScriptUtilFromDocImpl getJSScriptUtilFromDocImpl()
    {
        if (jsScriptUtil == null)
            this.jsScriptUtil = new JSScriptUtilFromDocImpl(this);
        return jsScriptUtil;
    }

    public int getCommMode()
    {
        return commMode;
    }

    public void setCommMode(int commMode)
    {
        CommModeImpl.checkMode(commMode);
        this.commMode = commMode;
    }

    public long getEventTimeout()
    {
        return eventTimeout;
    }

    public void setEventTimeout(long timeout)
    {
        this.eventTimeout = timeout;
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture)
    {
        int commMode = getCommMode();
        long eventTimeout = getEventTimeout();
        addEventListener(nodeTarget,type,listener,useCapture,commMode,null,null,eventTimeout);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,int commMode)
    {
        long eventTimeout = getEventTimeout();
        addEventListener(nodeTarget,type,listener,useCapture,commMode,null,null,eventTimeout);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,ParamTransport extraParam)
    {
        ParamTransport[] extraParams = new ParamTransport[]{ extraParam };
        addEventListener(nodeTarget,type,listener,useCapture,extraParams);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,ParamTransport[] extraParams)
    {
        int commMode = getCommMode();
        long eventTimeout = getEventTimeout();
        addEventListener(nodeTarget,type,listener,useCapture,commMode,extraParams,null,eventTimeout);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,String preSendCode)
    {
        int commMode = getCommMode();
        long eventTimeout = getEventTimeout();
        addEventListener(nodeTarget,type,listener,useCapture,commMode,null,preSendCode,eventTimeout);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout)
    {
        addEventListener(nodeTarget,type,listener,useCapture,commMode,extraParams,preSendCode,eventTimeout,null);
    }

    public void addEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout,String bindToListener)
    {
        if (ItsNatDOMExtEventListenerWrapperImpl.isExtensionType(type))
            addDOMExtEventListener(nodeTarget,type,listener,useCapture,commMode,extraParams,preSendCode,eventTimeout,bindToListener);
        else
            addDOMStdEventListener(nodeTarget,type,listener,useCapture,commMode,extraParams,preSendCode,eventTimeout,bindToListener);
    }

    public void addDOMStdEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout,String bindToListener)
    {
        getDOMStdEventListenerRegistry().addItsNatDOMStdEventListener(nodeTarget,type,listener,useCapture,commMode,extraParams,preSendCode,eventTimeout,bindToListener);
    }

    public void addDOMExtEventListener(EventTarget nodeTarget,String type,EventListener listener,boolean useCapture,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout,String bindToListener)
    {
        if (useCapture) throw new ItsNatException("Capturing is not allowed for this type:" + type,this);

        if (ItsNatUserEventListenerWrapperImpl.isUserType(type))
        {
            String name = ItsNatUserEventListenerWrapperImpl.getNameFromType(type,false);
            addUserEventListener(nodeTarget,name,listener,commMode,extraParams,preSendCode,eventTimeout,bindToListener);
        }
        else // itsnat:continue, itsnat:timer, itsnat:asynctask o itsnat:comet
            throw new ItsNatException("This method is not allowed to register this event listener type:" + type,this);
    }

    public void addMutationEventListener(EventTarget nodeTarget,EventListener mutationListener,boolean useCapture)
    {
        getDOMStdEventListenerRegistry().addMutationEventListener(nodeTarget,mutationListener,useCapture,getCommMode(),getEventTimeout());
    }

    public void addMutationEventListener(EventTarget target,EventListener listener,boolean useCapture,int commMode,String preSendCode,long eventTimeout)
    {
        addMutationEventListener(target,listener,useCapture,commMode,preSendCode,eventTimeout,null);
    }

    public void addMutationEventListener(EventTarget target,EventListener listener,boolean useCapture,int commMode,String preSendCode,long eventTimeout,String bindToListener)
    {
        getDOMStdEventListenerRegistry().addMutationEventListener(target,listener,useCapture,commMode,preSendCode,eventTimeout,bindToListener);
    }

    public void removeMutationEventListener(EventTarget target,EventListener listener,boolean useCapture)
    {
        getDOMStdEventListenerRegistry().removeMutationEventListener(target,listener,useCapture,true);
    }

    public boolean hasDOMStdEventListeners()
    {
        if (domStdListenerRegistry == null)
            return false;
        return !domStdListenerRegistry.isEmpty();
    }

    public ItsNatDOMStdEventListenerRegistryImpl getDOMStdEventListenerRegistry()
    {
        if (domStdListenerRegistry == null) // Evita instanciar si no se usa, caso de servir XML
            this.domStdListenerRegistry = new ItsNatDOMStdEventListenerRegistryImpl(this,null);
        return domStdListenerRegistry;
    }

    public void removeEventListener(EventTarget target,String type,EventListener listener,boolean useCapture)
    {
        removeEventListener(target,type,listener,useCapture,true);
    }

    public void removeEventListener(EventTarget target,String type,EventListener listener,boolean useCapture,boolean updateClient)
    {
        if (ItsNatDOMExtEventListenerWrapperImpl.isExtensionType(type))
            removeDOMExtEventListener(target,type,listener,useCapture,updateClient);
        else
            removeDOMStdEventListener(target,type,listener,useCapture,updateClient);
    }

    public void removeDOMStdEventListener(EventTarget target,String type,EventListener listener,boolean useCapture,boolean updateClient)
    {
        getDOMStdEventListenerRegistry().removeItsNatDOMStdEventListener(target,type,listener,useCapture,updateClient);
    }

    public void removeDOMExtEventListener(EventTarget target,String type,EventListener listener,boolean useCapture,boolean updateClient)
    {
        if (useCapture) return; // Como no puede haber listeners registrados capturing no hacemos nada

        if (ItsNatUserEventListenerWrapperImpl.isUserType(type))
        {
            String name = ItsNatUserEventListenerWrapperImpl.getNameFromType(type,false);
            removeUserEventListener(target,name,listener,updateClient);
        }
        else  // itsnat:continue, itsnat:timer, itsnat:asynctask o itsnat:comet , en estos tipos el desregistro se hace internamente.
            throw new ItsNatException("This method is not allowed to unregister this event listener type:" + type,this);
    }

    public int removeAllDOMStdEventListeners(EventTarget target,boolean updateClient)
    {
        if (!hasDOMStdEventListeners()) return 0;

        return getDOMStdEventListenerRegistry().removeAllItsNatDOMStdEventListeners(target,updateClient);
    }

    public ItsNatDOMStdEventListenerWrapperImpl getDOMStdEventListenerById(String listenerId)
    {
        if (!hasDOMStdEventListeners()) return null;

        return getDOMStdEventListenerRegistry().getItsNatDOMStdEventListenerById(listenerId);
    }

    public boolean hasUserEventListeners()
    {
        if (userListenerRegistry == null)
            return false;
        return !userListenerRegistry.isEmpty();
    }

    public ItsNatUserEventListenerRegistryImpl getUserEventListenerRegistry()
    {
        if (userListenerRegistry == null)
            userListenerRegistry = new ItsNatUserEventListenerRegistryImpl(this,null); // para ahorrar memoria si no se usa
        return userListenerRegistry;
    }

    public void addUserEventListener(EventTarget target,String name,EventListener listener,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout)
    {
        addUserEventListener(target,name,listener,commMode,extraParams,preSendCode,eventTimeout,null);
    }

    public void addUserEventListener(EventTarget target,String name,EventListener listener)
    {
        addUserEventListener(target,name,listener,getCommMode(),null,null,getEventTimeout(), null);
    }

    public void addUserEventListener(EventTarget target,String name,EventListener listener,int commMode,ParamTransport[] extraParams,String preSendCode,long eventTimeout,String bindToListener)
    {
        getUserEventListenerRegistry().addItsNatUserEventListener(target,name,listener,commMode,extraParams,preSendCode,eventTimeout,bindToListener);
    }

    public ItsNatUserEventListenerWrapperImpl getUserEventListenerById(String listenerId)
    {
        if (!hasUserEventListeners()) return null;

        return getUserEventListenerRegistry().getItsNatUserEventListenerById(listenerId);
    }

    public void removeUserEventListener(EventTarget target,String name,EventListener listener)
    {
        removeUserEventListener(target,name,listener,true);
    }

    public void removeUserEventListener(EventTarget target,String name,EventListener listener,boolean updateClient)
    {
        getUserEventListenerRegistry().removeItsNatUserEventListener(target,name,listener,updateClient);
    }

    public int removeAllUserEventListeners(EventTarget target,boolean updateClient)
    {
        if (!hasUserEventListeners()) return 0;

        return getUserEventListenerRegistry().removeAllItsNatUserEventListeners(target,updateClient);
    }

    public boolean isSendCodeEnabled()
    {
        return enabledSendCode;
    }

    public void disableSendCode()
    {
        this.enabledSendCode = false;
    }

    public void enableSendCode()
    {
        this.enabledSendCode = true;
    }

    public boolean hasClientDocumentAttachedClient()
    {
        if (clientDocAttachedSet == null)
            return false;
        return !clientDocAttachedSet.isEmpty();
    }

    public int getClientDocumentAttachedCount()
    {
        if (clientDocAttachedSet == null)
            return 0;
        return clientDocAttachedSet.size();
    }

    public WeakSetImpl<ClientDocumentAttachedClientImpl> getClientDocumentAttachedClientSet()
    {
        if (clientDocAttachedSet == null)
            this.clientDocAttachedSet = new WeakSetImpl<ClientDocumentAttachedClientImpl>();
        return clientDocAttachedSet;
    }

    public ClientDocumentAttachedClientImpl[] getClientDocumentAttachedClientArray()
    {
        if (!hasClientDocumentAttachedClient()) return null;

        WeakSetImpl<ClientDocumentAttachedClientImpl> attachedClients = getClientDocumentAttachedClientSet();
        return attachedClients.toArray(new ClientDocumentAttachedClientImpl[attachedClients.size()]);
    }

    public void addClientDocumentAttachedClient(ClientDocumentAttachedClientImpl clientDoc)
    {
        getClientDocumentAttachedClientSet().add(clientDoc);

        if (clientDoc.canReceiveSOMENormalEvents()) // Con este chequeo nos ahorramos llamadas in�tiles
        {
            if (hasDOMStdEventListeners())
                getDOMStdEventListenerRegistry().renderItsNatDOMEventListeners(clientDoc);
            if (hasUserEventListeners())
                getUserEventListenerRegistry().renderItsNatDOMEventListeners(clientDoc);
        }

        getItsNatStfulComponentManager().addClientDocumentAttachedClient(clientDoc);
    }

    public void removeClientDocumentAttachedClient(ClientDocumentAttachedClientImpl clientDoc)
    {
        clientDoc.setInvalid();
        getClientDocumentAttachedClientSet().remove(clientDoc);

        getItsNatStfulComponentManager().removeClientDocumentAttachedClient(clientDoc);
    }

    public boolean allClientDocumentWillReceiveCodeSent()
    {
        if (!isSendCodeEnabled())
            return false; // No, pues est� desactivado

        ClientDocumentStfulOwnerImpl owner = getClientDocumentStfulOwner();
        if (!owner.isSendCodeEnabled())
            return false;

        if (hasClientDocumentAttachedClient())
        {
            WeakSetImpl<ClientDocumentAttachedClientImpl> clientDocs = getClientDocumentAttachedClientSet();
            for(ClientDocumentAttachedClientImpl client : clientDocs)
            {
                if (!client.isSendCodeEnabled())
                    return false;
            }
        }

        return true; // Todos pueden recibir c�digo
    }

    public ClientDocumentStfulImpl[] getAllClientDocumentStfulsCopy()
    {
        return (ClientDocumentStfulImpl[])getAllClientDocumentsCopy();
    }

    public ClientDocumentImpl[] getAllClientDocumentsCopy()
    {
        ClientDocumentStfulOwnerImpl ownerClient = getClientDocumentStfulOwner();
        if (!hasClientDocumentAttachedClient())
            return new ClientDocumentStfulImpl[] { ownerClient };

        WeakSetImpl<ClientDocumentAttachedClientImpl> attachedClients = getClientDocumentAttachedClientSet();
        ClientDocumentStfulImpl[] res = new ClientDocumentStfulImpl[1 + attachedClients.size()];
        res[0] = ownerClient;
        int i = 1;
        for(Iterator<ClientDocumentAttachedClientImpl> it = attachedClients.iterator(); it.hasNext(); i++)
        {
            ClientDocumentAttachedClientImpl clientDoc = it.next();
            res[i] = clientDoc;
        }
        return res;
    }

    public boolean executeTaskOnClients(ClientDocStfulTask clientTask,Object arg)
    {
        ClientDocumentStfulOwnerImpl owner = getClientDocumentStfulOwner();
        boolean cont = clientTask.doTask(owner,arg);
        if (!cont) return false;

        if (hasClientDocumentAttachedClient())
        {
            WeakSetImpl<ClientDocumentAttachedClientImpl> attachedClient = getClientDocumentAttachedClientSet();
            for(ClientDocumentAttachedClientImpl clientDoc : attachedClient)
            {
                cont = clientTask.doTask(clientDoc,arg);
                if (!cont) return false;
            }
        }

        return true; // recorri� todos y siempre se devolvi� true
    }

    public void addCodeToSend(Object code)
    {
        if (!isScriptingEnabled())
            return;

        if (!isSendCodeEnabled()) // No enviar a nadie
            return;

        CodeToSendEventImpl event = null;
        if (hasCodeToSendListeners())
        {
            event = getCodeToSendListeners().preProcessCodeToSend(code);
            code = event.getCode();
            if (code == null) return; // Ha sido rechazado
        }

        ClientDocumentStfulImpl[] allClient = getAllClientDocumentStfulsCopy();
        for(int i = 0; i < allClient.length; i++)
        {
            ClientDocumentStfulImpl clientDoc = allClient[i];
            if (clientDoc.isSendCodeEnabled())
                clientDoc.addCodeToSend(code);
        }

        if (event != null)
            getCodeToSendListeners().postProcessCodeToSend(event);
    }

    public boolean hasCodeToSendListeners()
    {
        if (codeToSendListeners == null)
            return false;
        return codeToSendListeners.hasCodeToSendListeners();
    }

    public CodeToSendListenersImpl getCodeToSendListeners()
    {
        if (codeToSendListeners == null)
            this.codeToSendListeners = new CodeToSendListenersImpl(this);
        return codeToSendListeners;
    }

    public void addCodeToSendListener(CodeToSendListener listener)
    {
        getCodeToSendListeners().addCodeToSendListener(listener);
    }

    public void removeCodeToSendListener(CodeToSendListener listener)
    {
        getCodeToSendListeners().removeCodeToSendListener(listener);
    }

    @Override
    protected void setInvalidInternal()
    {
        super.setInvalidInternal();

        ClientDocumentStfulImpl[] allClient = getAllClientDocumentStfulsCopy();
        for(int i = 0; i < allClient.length; i++)
        {
            ClientDocumentStfulImpl clientDoc = allClient[i];
            clientDoc.setInvalid();
        }
    }

    public boolean isNodeCacheEnabled()
    {
        // No tiene sentido activar la cach� cuando es una p�gina sin JavaScript
        if (!isScriptingEnabled())
           return false;
        return getItsNatDocumentTemplateVersion().isNodeCacheEnabled();
    }

    public LinkedList<ItsNatAttachedClientEventListener> getItsNatAttachedClientEventListeners()
    {
        if (attachedClientListeners == null)
            this.attachedClientListeners = new LinkedList<ItsNatAttachedClientEventListener>();
        return attachedClientListeners;
    }

    public void getItsNatAttachedClientEventListenerList(LinkedList<ItsNatAttachedClientEventListener> list)
    {
        // No sincronizamos porque s�lo admitimos s�lo lectura
        if (attachedClientListeners == null)
            return;
        list.addAll(attachedClientListeners);
    }

    public void addItsNatAttachedClientEventListener(ItsNatAttachedClientEventListener listener)
    {
        LinkedList<ItsNatAttachedClientEventListener> attachedEventListeners = getItsNatAttachedClientEventListeners();
        attachedEventListeners.add(listener);
    }

    public void removeItsNatAttachedClientEventListener(ItsNatAttachedClientEventListener listener)
    {
        LinkedList<ItsNatAttachedClientEventListener> attachedEventListeners = getItsNatAttachedClientEventListeners();
        attachedEventListeners.remove(listener);
    }

    public boolean hasGlobalEventListenerListeners()
    {
        if (globalDomEventListeners == null)
            return false;
        return !globalDomEventListeners.isEmpty();
    }   
   
    public LinkedList<EventListener> getGlobalEventListenerList()
    {
        if (globalDomEventListeners == null)
            this.globalDomEventListeners = new LinkedList<EventListener>();
        return globalDomEventListeners;
    }

    public void getGlobalEventListenerList(LinkedList<EventListener> list)
    {
        if (globalDomEventListeners == null)
            return;
        list.addAll(globalDomEventListeners);
    }

    public void addEventListener(EventListener listener)
    {
        LinkedList<EventListener> globalDomEventListeners = getGlobalEventListenerList();
        globalDomEventListeners.add(listener);
    }

    public void addEventListener(int index,EventListener listener)
    {
        LinkedList<EventListener> globalDomEventListeners = getGlobalEventListenerList();
        globalDomEventListeners.add(index,listener);
    }

    public void removeEventListener(EventListener listener)
    {
        LinkedList<EventListener> globalDomEventListeners = getGlobalEventListenerList();
        globalDomEventListeners.remove(listener);
    }

    public Event createEvent(String eventType) throws DOMException
    {
        return ServerItsNatDOMEventImpl.createServerDOMEvent(eventType,this);
    }

    public void lockThread(long maxWait)
    {
        synchronized(this) // si ya est� sincronizado (lo normal) es redundante
        {
            // Al esperar liberamos el lock sobre el documento y otro hilo lo podr� usar
            try { wait(maxWait); } catch(InterruptedException ex) { throw new ItsNatException(ex,this); }
        }
    }

    public void unlockThreads()
    {
        synchronized(this)
        {
            notifyAll(); // Liberamos el hilo request/response bloqueado
        }
    }

    public boolean dispatchEvent(EventTarget target,Event evt) throws EventException
    {
        ClientDocumentStfulImpl clientDoc = getEventDispatcherClientDocByThread();
        if (clientDoc != null)
            return clientDoc.dispatchEvent(target,evt);
        else
            return dispatchEventLocally(target,evt);
    }

    public boolean dispatchEventLocally(EventTarget target,Event evt) throws EventException
    {
        return ServerItsNatDOMStdEventImpl.dispatchEventLocally(target,evt);
    }

    public long getEventDispatcherMaxWait()
    {
        return evtDispMaxWait;
    }

    public void setEventDispatcherMaxWait(long wait)
    {
        this.evtDispMaxWait = wait;
    }

    public int getMaxOpenClientsByDocument()
    {
        return maxOpenClients;
    }

    public void setMaxOpenClientsByDocument(int value)
    {
        ItsNatServletConfigImpl.checkMaxOpenClientsByDocument(value);
        this.maxOpenClients = value;
        getClientDocumentStfulOwner().getItsNatSessionImpl().cleanExcessClientDocumentAttachedClients(this); // Lo hacemos efectivo ya mismo
    }

    public ThreadLocal<ClientDocumentStfulImpl> getEventDispatcherThreadLocal()
    {
        return evtDispThreadLocal;
    }

    public ClientDocumentStfulImpl getEventDispatcherClientDocByThread()
    {
        return evtDispThreadLocal.get();
    }

    public void setEventDispatcherClientDocByThread(ClientDocumentStfulImpl clientDoc)
    {
        evtDispThreadLocal.set(clientDoc);
    }

    public LinkedList<ItsNatServletRequestListener> getReferrerItsNatServletRequestListenerList()
    {
        if (referrerRequestListeners == null)
            this.referrerRequestListeners = new LinkedList<ItsNatServletRequestListener>();
        return referrerRequestListeners;
    }

    public Iterator<ItsNatServletRequestListener> getReferrerItsNatServletRequestListenerIterator()
    {
        if (referrerRequestListeners == null) return null;
        if (referrerRequestListeners.isEmpty()) return null;
        return referrerRequestListeners.iterator();
    }

    public void addReferrerItsNatServletRequestListener(ItsNatServletRequestListener listener)
    {
        if (!isReferrerEnabled())
            throw new ItsNatException("Referrer feature is not enabled",this);

        LinkedList<ItsNatServletRequestListener> referrerRequestListeners = getReferrerItsNatServletRequestListenerList();
        referrerRequestListeners.add(listener);
    }

    public void removeReferrerItsNatServletRequestListener(ItsNatServletRequestListener listener)
    {
        LinkedList<ItsNatServletRequestListener> referrerRequestListeners = getReferrerItsNatServletRequestListenerList();
        referrerRequestListeners.remove(listener);
    }

    public void dispatchReferrerRequestListeners(ItsNatServletRequest request,ItsNatServletResponse response)
    {
        // Sincronizar el documento antes de llamar a este m�todo
        Iterator<ItsNatServletRequestListener> iterator = getReferrerItsNatServletRequestListenerIterator();
        if (iterator != null)
        {
            while(iterator.hasNext())
            {
                ItsNatServletRequestListener listener = iterator.next();
                listener.processRequest(request,response);
            }
        }
    }

    public void normalEventReceived(ClientDocumentStfulImpl clientDocSource)
    {
        // clientDoc es el cliente que lo recibi�, no lo notificamos pues ya
        // sabe que ha recibido un evento "normal", adem�s en el caso
        // de control remoto (Comet) evitamos refrescos in�tiles (y que pueden bloquear el navegador),
        // si ha de refrescarse que lo decida el m�todo del cliente que lo recibi�.

        ClientDocumentStfulOwnerImpl clientDocOwner = getClientDocumentStfulOwner();
        if (clientDocOwner != clientDocSource)
            clientDocOwner.normalEventReceivedInDocument();

        if (hasClientDocumentAttachedClient())
        {
            WeakSetImpl<ClientDocumentAttachedClientImpl> clientDocs = getClientDocumentAttachedClientSet();
            for(ClientDocumentAttachedClientImpl clientDocAttached : clientDocs)
            {
                if (clientDocAttached != clientDocSource)
                    clientDocAttached.normalEventReceivedInDocument();
            }
        }
    }

    public Random getRandom()
    {
        if (random == null) this.random = new Random();
        return random;
    }

    public boolean hasBoundElementDocContainers()
    {
        if (boundElemDocContainers == null) return false;
        return !boundElemDocContainers.isEmpty();
    }

    public MapUniqueId<BoundElementDocContainerImpl> getBoundElementDocContainerMap()
    {
        if (boundElemDocContainers == null) this.boundElemDocContainers = new MapUniqueId<BoundElementDocContainerImpl>(getUniqueIdGenerator());
        return boundElemDocContainers;
    }

    public BoundElementDocContainerImpl getBoundElementDocContainer(String id,int random)
    {
        if (!hasBoundElementDocContainers()) return null;

        BoundElementDocContainerImpl bindInfo = getBoundElementDocContainerMap().get(id);
        if (bindInfo == null) return null;
        if (bindInfo.getRandomNumber() != random) return null; // Podr�amos provocar un error pero por si acaso es un extra�o caso de expiraci�n
        return bindInfo;
    }

    public BoundElementDocContainerImpl addBoundElementDocContainer(ElementDocContainer elem,String docName)
    {
        BoundElementDocContainerImpl bindInfo = new BoundElementDocContainerImpl(elem,docName,this);

        Object res = getBoundElementDocContainerMap().put(bindInfo);
        if (res != null) throw new ItsNatException("INTERNAL ERROR");
        return bindInfo;
    }

    public boolean removeBoundElementDocContainer(BoundElementDocContainerImpl bindInfo)
    {
        if (!hasBoundElementDocContainers()) return false; // Ya no est� registrado (RARO)

        Object res = getBoundElementDocContainerMap().remove(bindInfo);
        if (res != bindInfo) throw new ItsNatException("INTERNAL ERROR");

        return true;
    }

    public boolean isDisconnectedChildNodesFromClient(Node node)
    {
        return getDocMutationListenerEventStful().isDisconnectedChildNodesFromClient(node);
    }

    public Node disconnectChildNodesFromClient(Node node)
    {
        return getDocMutationListenerEventStful().disconnectChildNodesFromClient(node);
    }
   
    public void reconnectChildNodesToClient(Node node)
    {
        getDocMutationListenerEventStful().reconnectChildNodesToClient(node);
    }

    public abstract Element getVisualRootElement();
    public abstract boolean isNewNodeDirectChildOfContentRoot(Node newNode);
}
TOP

Related Classes of org.itsnat.impl.core.doc.ItsNatStfulDocumentImpl

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.