Package org.itsnat.impl.comp.mgr

Source Code of org.itsnat.impl.comp.mgr.ItsNatDocComponentManagerImpl

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

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;
import javax.swing.ButtonGroup;
import org.itsnat.comp.CreateItsNatComponentListener;
import org.itsnat.comp.ItsNatComponent;
import org.itsnat.comp.ItsNatComponentManager;
import org.itsnat.comp.button.ItsNatButtonGroup;
import org.itsnat.comp.button.normal.ItsNatFreeButtonNormal;
import org.itsnat.comp.button.normal.ItsNatFreeButtonNormalLabel;
import org.itsnat.comp.button.toggle.ItsNatFreeCheckBox;
import org.itsnat.comp.button.toggle.ItsNatFreeCheckBoxLabel;
import org.itsnat.comp.button.toggle.ItsNatFreeRadioButton;
import org.itsnat.comp.button.toggle.ItsNatFreeRadioButtonLabel;
import org.itsnat.comp.inc.ItsNatFreeInclude;
import org.itsnat.comp.label.ItsNatFreeLabel;
import org.itsnat.comp.label.ItsNatLabelRenderer;
import org.itsnat.comp.list.ItsNatFreeComboBox;
import org.itsnat.comp.list.ItsNatFreeListMultSel;
import org.itsnat.comp.list.ItsNatListCellRenderer;
import org.itsnat.comp.list.ItsNatListStructure;
import org.itsnat.comp.table.ItsNatFreeTable;
import org.itsnat.comp.table.ItsNatTableCellRenderer;
import org.itsnat.comp.table.ItsNatTableHeaderCellRenderer;
import org.itsnat.comp.table.ItsNatTableStructure;
import org.itsnat.comp.tree.ItsNatFreeTree;
import org.itsnat.comp.tree.ItsNatTreeCellRenderer;
import org.itsnat.comp.tree.ItsNatTreeStructure;
import org.itsnat.core.ItsNatDOMException;
import org.itsnat.core.ItsNatDocument;
import org.itsnat.core.NameValue;
import org.itsnat.impl.comp.button.toggle.ItsNatButtonGroupImpl;
import org.itsnat.impl.comp.factory.FactoryItsNatComponentImpl;
import org.itsnat.impl.comp.factory.button.normal.FactoryItsNatFreeButtonNormalDefaultImpl;
import org.itsnat.impl.comp.factory.button.normal.FactoryItsNatFreeButtonNormalLabelImpl;
import org.itsnat.impl.comp.factory.button.toggle.FactoryItsNatFreeCheckBoxDefaultImpl;
import org.itsnat.impl.comp.factory.button.toggle.FactoryItsNatFreeCheckBoxLabelImpl;
import org.itsnat.impl.comp.factory.button.toggle.FactoryItsNatFreeRadioButtonDefaultImpl;
import org.itsnat.impl.comp.factory.button.toggle.FactoryItsNatFreeRadioButtonLabelImpl;
import org.itsnat.impl.comp.factory.inc.FactoryItsNatFreeIncludeImpl;
import org.itsnat.impl.comp.factory.label.FactoryItsNatFreeLabelImpl;
import org.itsnat.impl.comp.factory.layer.FactoryItsNatModalLayerImpl;
import org.itsnat.impl.comp.factory.list.FactoryItsNatFreeComboBoxImpl;
import org.itsnat.impl.comp.factory.list.FactoryItsNatFreeListMultSelImpl;
import org.itsnat.impl.comp.factory.table.FactoryItsNatFreeTableImpl;
import org.itsnat.impl.comp.factory.tree.FactoryItsNatFreeTreeImpl;
import org.itsnat.impl.comp.label.ItsNatLabelRendererDefaultImpl;
import org.itsnat.impl.comp.list.ItsNatListCellRendererDefaultImpl;
import org.itsnat.impl.comp.list.ItsNatListStructureDefaultImpl;
import org.itsnat.impl.comp.table.ItsNatTableCellRendererDefaultImpl;
import org.itsnat.impl.comp.table.ItsNatTableHeaderCellRendererDefaultImpl;
import org.itsnat.impl.comp.table.ItsNatTableStructureDefaultImpl;
import org.itsnat.impl.comp.tree.ItsNatTreeCellRendererDefaultImpl;
import org.itsnat.impl.comp.tree.ItsNatTreeStructureDefaultImpl;
import org.itsnat.impl.core.doc.ItsNatDocumentImpl;
import org.itsnat.impl.core.domutil.NamespaceUtil;
import org.itsnat.impl.core.listener.AutoBuildCompBeforeAfterMutationRenderListener;
import org.itsnat.impl.core.mut.doc.DocMutationEventListenerImpl;
import org.itsnat.impl.core.servlet.ItsNatServletImpl;
import org.itsnat.impl.core.template.ItsNatDocumentTemplateImpl;
import org.itsnat.impl.core.template.ItsNatDocumentTemplateVersionImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
*
* @author jmarranz
*/
public abstract class ItsNatDocComponentManagerImpl implements ItsNatComponentManager,Serializable
{
    protected static final Map<String,FactoryItsNatComponentImpl> FACTORIES = new HashMap<String,FactoryItsNatComponentImpl>(); // No sincronizamos porque va a ser siempre usada en modo lectura
    static
    {
        addFactory(FactoryItsNatFreeButtonNormalDefaultImpl.SINGLETON);
        addFactory(FactoryItsNatFreeButtonNormalLabelImpl.SINGLETON);
        addFactory(FactoryItsNatFreeCheckBoxDefaultImpl.SINGLETON);
        addFactory(FactoryItsNatFreeCheckBoxLabelImpl.SINGLETON);
        addFactory(FactoryItsNatFreeComboBoxImpl.SINGLETON);
        addFactory(FactoryItsNatFreeIncludeImpl.SINGLETON);
        addFactory(FactoryItsNatFreeLabelImpl.SINGLETON);
        addFactory(FactoryItsNatFreeListMultSelImpl.SINGLETON);
        addFactory(FactoryItsNatFreeRadioButtonDefaultImpl.SINGLETON);
        addFactory(FactoryItsNatFreeRadioButtonLabelImpl.SINGLETON);
        addFactory(FactoryItsNatFreeTableImpl.SINGLETON);
        addFactory(FactoryItsNatFreeTreeImpl.SINGLETON);
        addFactory(FactoryItsNatModalLayerImpl.SINGLETON);
    }

    protected static void addFactory(FactoryItsNatComponentImpl factory)
    {
        FACTORIES.put(factory.getKey(),factory);
    }

    protected static FactoryItsNatComponentImpl getFactoryItsNatComponentStatic(String compName)
    {
        return FACTORIES.get(compName);
    }

    protected FactoryItsNatComponentImpl getFactoryItsNatComponent(Element elem,String compType)
    {
        return getFactoryItsNatComponentStatic(compType);
    }

    protected ItsNatDocumentImpl itsNatDoc;
    protected transient WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByName;  // Un ItsNatButtonGroup necesita estar asociado a un radio button si ninguno lo referencia se puede perder, as� evitamos memory leaks por recreaci�n de radio buttons
    protected transient WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByButtonGroup;  // "
    protected Map<Node,ItsNatComponent> components;
    protected Map<Node,Object> excludedNodesAsComponents;
    protected boolean selectionOnComponentsUsesKeyboard;
    protected boolean markupDrivenComponents;
    protected boolean autoBuildComponents;
    protected LinkedList<CreateItsNatComponentListener> createCompListeners;
    protected transient WeakHashMap<ItsNatComponent,Object> weakMapComponents;

    /** Creates a new instance of ItsNatDocComponentManagerImpl */
    public ItsNatDocComponentManagerImpl(ItsNatDocumentImpl itsNatDoc)
    {
        this.itsNatDoc = itsNatDoc;

        ItsNatDocumentTemplateVersionImpl templateVer = itsNatDoc.getItsNatDocumentTemplateVersion();

        this.selectionOnComponentsUsesKeyboard = templateVer.isSelectionOnComponentsUsesKeyboard();
        this.markupDrivenComponents = templateVer.isMarkupDrivenComponents();
        this.autoBuildComponents = templateVer.isAutoBuildComponents();
    }

    private void writeObject(ObjectOutputStream out) throws IOException
    {
        {
            Map<String,ItsNatButtonGroupImpl> mapTmp = null;

            if (buttonGroupsByName != null)
            {
                // Tenemos que copiar elemento a elemento porque los "values"
                // son WeakReference (no serializables)
                mapTmp = new HashMap<String,ItsNatButtonGroupImpl>();
                for(Map.Entry<String,WeakReference<ItsNatButtonGroupImpl>> entry : buttonGroupsByName.entrySet())
                {
                    String key = entry.getKey();
                    WeakReference<ItsNatButtonGroupImpl> weakRef = entry.getValue();
                    mapTmp.put(key, weakRef.get());
                }
            }
            out.writeObject(mapTmp);
        }
       
        {
            Map<ButtonGroup,ItsNatButtonGroupImpl> mapTmp = null;
            if (buttonGroupsByButtonGroup != null)
            {
                // Tenemos que copiar elemento a elemento porque los "values"
                // son WeakReference (no serializables)
                mapTmp = new HashMap<ButtonGroup,ItsNatButtonGroupImpl>();
                for(Map.Entry<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> entry : buttonGroupsByButtonGroup.entrySet())
                {
                    ButtonGroup key = entry.getKey();
                    WeakReference<ItsNatButtonGroupImpl> weakRef = entry.getValue();
                    mapTmp.put(key, weakRef.get());
                }
            }
            out.writeObject(mapTmp);
        }
       
        {
            Map<ItsNatComponent,Object> mapTmp = null;
            if (weakMapComponents != null)
                mapTmp = new HashMap<ItsNatComponent,Object>(weakMapComponents);
            out.writeObject(mapTmp);
        }
       
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
    {
        {
            @SuppressWarnings("unchecked")
            Map<String,ItsNatButtonGroupImpl> mapTmp = (Map<String,ItsNatButtonGroupImpl>)in.readObject();
            if (mapTmp != null)
            {
                WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByName = getButtonGroupsByNameMap();
                for(Map.Entry<String,ItsNatButtonGroupImpl> entry : mapTmp.entrySet())
                {
                    String key = entry.getKey();
                    ItsNatButtonGroupImpl value = entry.getValue();
                    buttonGroupsByName.put(key,new WeakReference<ItsNatButtonGroupImpl>(value));
                }
            }
        }
       
        {
            @SuppressWarnings("unchecked")
            Map<ButtonGroup,ItsNatButtonGroupImpl> mapTmp = (Map<ButtonGroup,ItsNatButtonGroupImpl>)in.readObject();
            if (mapTmp != null)
            {
                WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByButtonGroup = getButtonGroupsByButtonGroupMap();
                for(Map.Entry<ButtonGroup,ItsNatButtonGroupImpl> entry : mapTmp.entrySet())
                {
                    ButtonGroup key = entry.getKey();
                    ItsNatButtonGroupImpl value = entry.getValue();
                    buttonGroupsByButtonGroup.put(key,new WeakReference<ItsNatButtonGroupImpl>(value));
                }
            }
        }
       
        {
            @SuppressWarnings("unchecked")
            Map<ItsNatComponent,Object> mapTmp = (Map<ItsNatComponent,Object>)in.readObject();
            if (mapTmp != null)
                getItsNatComponentWeakMap().putAll(mapTmp);
        }
       
        in.defaultReadObject();
    }

    public ItsNatDocument getItsNatDocument()
    {
        return itsNatDoc;
    }

    public ItsNatDocumentImpl getItsNatDocumentImpl()
    {
        return itsNatDoc;
    }

    public boolean isSelectionOnComponentsUsesKeyboard()
    {
        return selectionOnComponentsUsesKeyboard;
    }

    public void setSelectionOnComponentsUsesKeyboard(boolean value)
    {
        this.selectionOnComponentsUsesKeyboard = value;
    }

    public boolean isMarkupDrivenComponents()
    {
        return markupDrivenComponents;
    }

    public void setMarkupDrivenComponents(boolean value)
    {
        this.markupDrivenComponents = value;
    }

    public boolean isAutoBuildComponents()
    {
        return autoBuildComponents;
    }

    public void setAutoBuildComponents(boolean value)
    {
        if (this.autoBuildComponents == value)
            return; // No cambia nada

        this.autoBuildComponents = value;

        DocMutationEventListenerImpl mutEventListener = getItsNatDocumentImpl().getDocMutationEventListener();
        AutoBuildCompBeforeAfterMutationRenderListener autoBuildListener;
        if (value)
            autoBuildListener = new AutoBuildCompBeforeAfterMutationRenderListener(this);
        else
            autoBuildListener = null;

        mutEventListener.setAutoBuildCompBeforeAfterMutationRenderListener(autoBuildListener);
    }

    public Map<Node,ItsNatComponent> getComponentMap()
    {
        if (components == null)
            this.components = new HashMap<Node,ItsNatComponent>();
        return components;
    }

    public Map<Node,Object> getExcludedNodesAsComponentsMap()
    {
        if (excludedNodesAsComponents == null)
            this.excludedNodesAsComponents = new HashMap<Node,Object>();
        return excludedNodesAsComponents;
    }

    public WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>> getButtonGroupsByNameMap()
    {
        if (buttonGroupsByName == null)
            this.buttonGroupsByName = new WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>>(); // Ahorramos memoria si no se usan componentes
        return buttonGroupsByName;
    }

    public WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> getButtonGroupsByButtonGroupMap()
    {
        if (buttonGroupsByButtonGroup == null)
            this.buttonGroupsByButtonGroup = new WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>>(); // Ahorramos memoria si no se usan componentes
        return buttonGroupsByButtonGroup;
    }

    public ItsNatButtonGroup getItsNatButtonGroup(String name)
    {
        if ((name == null) || name.equals("")) return null;

        WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByName = getButtonGroupsByNameMap();
        ItsNatButtonGroupImpl itsNatButtonGroup = null;
        WeakReference<ItsNatButtonGroupImpl> weakButtonGrp = buttonGroupsByName.get(name);
        if (weakButtonGrp != null)
            itsNatButtonGroup = weakButtonGrp.get(); // puede ser null
        if (itsNatButtonGroup == null)
            itsNatButtonGroup = addButtonGroup(name);
        return itsNatButtonGroup;
    }

    public ItsNatButtonGroup getItsNatButtonGroup(ButtonGroup group)
    {
        if (group == null) return null;

        WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByButtonGroup = getButtonGroupsByButtonGroupMap();
        ItsNatButtonGroupImpl itsNatButtonGroup = null;
        WeakReference<ItsNatButtonGroupImpl> weakButtonGrp = buttonGroupsByButtonGroup.get(group);
        if (weakButtonGrp != null)
            itsNatButtonGroup = weakButtonGrp.get(); // puede ser null
        if (itsNatButtonGroup == null)
            itsNatButtonGroup = addButtonGroup(group);
        return itsNatButtonGroup;
    }

    public ItsNatButtonGroup createItsNatButtonGroup()
    {
        return addButtonGroup(new ButtonGroup());
    }

    public ItsNatButtonGroupImpl addButtonGroup(String name)
    {
        // Suponemos que el nombre pasado no es usado por otro (ya se ha comprobado).

        return addButtonGroup(new ButtonGroup(),name);
    }

    public ItsNatButtonGroupImpl addButtonGroup(ButtonGroup group)
    {
        // Suponemos que el ButtonGroup pasado no es usado por otro (ya se ha comprobado).

        // El nombre lo generamos para que sea �nico
        String name = itsNatDoc.getUniqueIdGenerator().generateId("buttonGroup");
        return addButtonGroup(group,name);
    }

    public ItsNatButtonGroupImpl addButtonGroup(ButtonGroup group,String name)
    {
        ItsNatButtonGroupImpl itsNatButtonGroup = new ItsNatButtonGroupImpl(name,group);
        return addButtonGroup(itsNatButtonGroup);
    }

    public ItsNatButtonGroupImpl addButtonGroup(ItsNatButtonGroupImpl itsNatButtonGroup)
    {
        // Suponemos que el ItsNatButtonGroupImpl pasado es nuevo (ya se ha comprobado).

        WeakReference<ItsNatButtonGroupImpl> weakButtonGrp = new WeakReference<ItsNatButtonGroupImpl>(itsNatButtonGroup);

        WeakHashMap<String,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByName = getButtonGroupsByNameMap();
        buttonGroupsByName.put(itsNatButtonGroup.getName(),weakButtonGrp); // El objeto String name est� sujeto por el propio ItsNatButtonGroupImpl, si este se pierde se pierde su Id y la entrada en el mapa lo cual es deseable

        WeakHashMap<ButtonGroup,WeakReference<ItsNatButtonGroupImpl>> buttonGroupsByButtonGroup = getButtonGroupsByButtonGroupMap();
        buttonGroupsByButtonGroup.put(itsNatButtonGroup.getButtonGroup(),weakButtonGrp); // El ButtonGroup Swing est� sujeto por el propio ItsNatButtonGroupImpl, si este se pierde se pierde su entrada en el mapa lo cual es deseable

        return itsNatButtonGroup;
    }

    public void removeItsNatComponent(ItsNatComponent comp,boolean dispose)
    {
        Map<Node,ItsNatComponent> components = getComponentMap();
        components.remove(comp.getNode());
        if (dispose) comp.dispose();
    }

    public ItsNatComponent removeItsNatComponent(Node node)
    {
        return removeItsNatComponent(node,false);
    }

    public ItsNatComponent removeItsNatComponent(Node node,boolean dispose)
    {
        ItsNatComponent comp = findItsNatComponent(node);
        if (comp == null) return null;
        removeItsNatComponent(comp,dispose);
        return comp;
    }

    public ItsNatComponent removeItsNatComponent(String id)
    {
        Document doc = getItsNatDocumentImpl().getDocument();
        Element node = doc.getElementById(id);
        return removeItsNatComponent(node);
    }

    public void removeExcludedNodeAsItsNatComponent(Node node)
    {
        Map<Node,Object> nodes = getExcludedNodesAsComponentsMap();
        nodes.remove(node);
    }

    public ItsNatComponent findItsNatComponentById(String id)
    {
        Document doc = getItsNatDocumentImpl().getDocument();
        Element node = doc.getElementById(id);
        return findItsNatComponent(node);
    }

    public ItsNatComponent findItsNatComponent(Node node)
    {
        if (node == null)
            return null;

        if (node.getNodeType() != Node.ELEMENT_NODE)
            return null; // S�lo Element son componentes, as� aceleramos la b�squeda

        Map<Node,ItsNatComponent> components = getComponentMap();
        return components.get(node);
    }

    public boolean isExcludedNodeAsItsNatComponent(Node node)
    {
        if (node.getNodeType() != Node.ELEMENT_NODE)
            return true// S�lo pueden ser componentes los Element, otro tipo de nodos son excluidos por defecto

        Map<Node,Object> nodes = getExcludedNodesAsComponentsMap();
        return nodes.containsKey(node);
    }

    public ItsNatComponent addItsNatComponent(ItsNatComponent comp)
    {
        if (comp == null) return null;

        Map<Node,ItsNatComponent> components = getComponentMap();
        return components.put(comp.getNode(),comp);
    }

    public void addExcludedNodeAsItsNatComponent(Node node)
    {
        if (node.getNodeType() != Node.ELEMENT_NODE)
            throw new ItsNatDOMException("Only Element nodes can be associated to components",node);

        Map<Node,Object> nodes = getExcludedNodesAsComponentsMap();
        nodes.put(node,null);
    }

    public ItsNatComponent createItsNatComponent(Node node)
    {
        return createItsNatComponent(node,null,null);
    }

    public ItsNatComponent createItsNatComponent(Node node,String componentType,NameValue[] artifacts)
    {
        return createItsNatComponent(node,componentType,artifacts,false);
    }

    public ItsNatComponent createItsNatComponentById(String id)
    {
        return createItsNatComponentById(id,null,null);
    }

    public ItsNatComponent createItsNatComponentById(String id,String compType,NameValue[] artifacts)
    {
        Document doc = getItsNatDocumentImpl().getDocument();
        Element node = doc.getElementById(id);
        return createItsNatComponent(node,compType,artifacts);
    }

    public ItsNatComponent createItsNatComponent(Node node,String componentType,NameValue[] artifacts,boolean autoBuildMode)
    {
        if (node == null)
            return null;

        if (node.getNodeType() != Node.ELEMENT_NODE)
            return null; // S�lo Element pueden ser componentes a d�a de hoy
        Element element = (Element)node;

        if (componentType == null) // Esto incluye el caso de creaci�n expl�cita del usuario pero no especifica el componentType, pero sin embargo est� en el HTML
            componentType = getCompTypeAttribute(element);   // Puede ser null

        ItsNatComponent comp = null;
        boolean doFilters = hasBeforeAfterCreateItsNatComponentListener();
        if (doFilters) comp = processBeforeCreateItsNatComponentListener(node,componentType,artifacts);

        if (comp == null)
        {
            // A d�a de hoy s�lo nodos Element pueden ser componentes
            // Si compType est� definido, �ste tiene prioridad sobre el tipo de componente
            // por defecto asociado al tag name.
            // compType puede ser null => el componente se deduce del tagName
            FactoryItsNatComponentImpl factory = getFactoryItsNatComponent(element,componentType);
            if (factory != null)
                comp = factory.createItsNatComponent(element,componentType,artifacts,autoBuildMode,false,this);
        }

        if (comp == null) return null;

        if (doFilters) comp = processAfterCreateItsNatComponentListener(comp);

        registerItsNatComponent(comp);

        return comp; // Puede ser null
    }

    public void registerItsNatComponent(ItsNatComponent comp)
    {
        getItsNatComponentWeakMap().put(comp,null);
    }

    public boolean hasItsNatComponents()
    {
        if (weakMapComponents == null)
            return false;
        return weakMapComponents.size() > 0;
    }

    public WeakHashMap<ItsNatComponent,Object> getItsNatComponentWeakMap()
    {
        if (weakMapComponents == null)
            this.weakMapComponents = new WeakHashMap<ItsNatComponent,Object>();
        return weakMapComponents;
    }

    public boolean hasBeforeAfterCreateItsNatComponentListener()
    {
        ItsNatDocumentTemplateImpl docTemplate = itsNatDoc.getItsNatDocumentTemplateImpl();
        ItsNatServletImpl servlet = docTemplate.getItsNatServletImpl();
        boolean res;

        res = servlet.hasCreateItsNatComponentList();
        if (res) return true;

        res = docTemplate.hasCreateItsNatComponentList();
        if (res) return true;

        res = hasCreateItsNatComponentList();
        if (res) return true;

        return false;
    }

    public ItsNatComponent processBeforeCreateItsNatComponentListener(Node node,String componentType,NameValue[] artifacts)
    {
        ItsNatComponent comp = null;
        Iterator<CreateItsNatComponentListener> createCompIterator = null;

        ItsNatDocumentTemplateImpl docTemplate = itsNatDoc.getItsNatDocumentTemplateImpl();
        ItsNatServletImpl servlet = docTemplate.getItsNatServletImpl();

        createCompIterator = servlet.getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processBeforeCreateItsNatComponentListener(createCompIterator,node,componentType,artifacts);
            if (comp != null) return comp;
        }

        createCompIterator = docTemplate.getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processBeforeCreateItsNatComponentListener(createCompIterator,node,componentType,artifacts);
            if (comp != null) return comp;
        }

        createCompIterator = getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processBeforeCreateItsNatComponentListener(createCompIterator,node,componentType,artifacts);
            if (comp != null) return comp;
        }

        return null;
    }

    public ItsNatComponent processAfterCreateItsNatComponentListener(ItsNatComponent comp)
    {
        // Permitimos as� que el usuario pueda crear sus propios componentes
        // que ser�n instanciados cuando sea llamado este m�todo
        // incluso podr�a substituir a los que hay por defecto segun el nodo
        // Ver m�s arriba la llamada a beforeRender()
        ItsNatDocumentTemplateImpl docTemplate = itsNatDoc.getItsNatDocumentTemplateImpl();
        ItsNatServletImpl servlet = docTemplate.getItsNatServletImpl();

        Iterator<CreateItsNatComponentListener> createCompIterator = null;
        createCompIterator = servlet.getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processAfterCreateItsNatComponentListener(createCompIterator,comp);
            if (comp == null) return null; // Componente rechazado
        }

        createCompIterator = docTemplate.getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processAfterCreateItsNatComponentListener(createCompIterator,comp);
            if (comp == null) return null; // Componente rechazado
        }

        createCompIterator = getCreateItsNatComponentListenerIterator();
        if (createCompIterator != null)
        {
            comp = processAfterCreateItsNatComponentListener(createCompIterator,comp);
            if (comp == null) return null; // Componente rechazado
        }

        return comp;
    }

    public ItsNatComponent processBeforeCreateItsNatComponentListener(Iterator<CreateItsNatComponentListener> it,Node node,String componentType,NameValue[] artifacts)
    {
        ItsNatComponent comp = null;

        // Permitimos as� que el usuario pueda crear sus propios componentes
        // que ser�n instanciados cuando sea llamado este m�todo
        // incluso podr�a substituir a los que hay por defecto segun el nodo
        // No deber�a a�adirse nuevos listeners cuando ya haya documentos cargados
        // El programador deber�a tener en cuenta que se puede llamar a beforeRender/afterRender en multihilo
        // aunque con un s�lo hilo por documento.

        // Aunque se usa una colecci�n del ItsNatDocumentTemplate y servlet no hay problema de hilos
        // mientras no se modifique concurrentemente la lista, esto no deber�a
        // ocurrir, el usuario debe registrar sus CreateItsNatComponentListener
        // en tiempo de creaci�n del template (init() del Servlet).
        while(it.hasNext())
        {
            CreateItsNatComponentListener listener = it.next();
            comp = listener.before(node,componentType,artifacts,this);
            if (comp != null)
                break;
        }

        return comp;
    }

    public ItsNatComponent processAfterCreateItsNatComponentListener(Iterator<CreateItsNatComponentListener> it,ItsNatComponent comp)
    {
        // Permitimos as� que el usuario pueda crear sus propios componentes
        // que ser�n instanciados cuando sea llamado este m�todo
        // incluso podr�a substituir a los que hay por defecto segun el nodo
        // Ver m�s arriba la llamada a beforeRender()
        while(it.hasNext())
        {
            CreateItsNatComponentListener listener = it.next();
            comp = listener.after(comp);
            if (comp == null)
                return null; // Componente rechazado
        }
        return comp;
    }

    public ItsNatComponent addItsNatComponent(Node node)
    {
        return addItsNatComponent(node,null,null);
    }

    public ItsNatComponent addItsNatComponent(Node node,String componentType,NameValue[] artifacts)
    {
        return addItsNatComponent(node,componentType,artifacts,false);
    }

    public ItsNatComponent addItsNatComponentById(String id)
    {
        return addItsNatComponentById(id,null,null);
    }

    public ItsNatComponent addItsNatComponentById(String id,String compType,NameValue[] artifacts)
    {
        Document doc = getItsNatDocumentImpl().getDocument();
        Element node = doc.getElementById(id);
        return addItsNatComponent(node,compType,artifacts);
    }

    public ItsNatComponent addItsNatComponent(Node node,String componentType,NameValue[] artifacts,boolean autoBuildMode)
    {
        if (node == null)
            return null;

        if (isExcludedNodeAsItsNatComponent(node))
            return null;

        if (autoBuildMode)
        {
            if (findItsNatComponent(node) != null) // para evitar a�adir dos veces
                return null;
        }

        ItsNatComponent component = createItsNatComponent(node,componentType,artifacts,autoBuildMode); // puede ser null
        if (component != null)
        {
            ItsNatComponent oldComp = addItsNatComponent(component)// Si es null no hace nada
            if (oldComp != null)
                throw new ItsNatDOMException("A component is already associated to this node",node);
        }
        return component; // puede ser null
    }

    public ItsNatComponent[] buildItsNatComponents()
    {
        Document doc = getItsNatDocument().getDocument();
        return buildItsNatComponents(doc);
    }

    public ItsNatComponent[] buildItsNatComponents(Node node)
    {
        LinkedList<ItsNatComponent> listComp = new LinkedList<ItsNatComponent>();

        buildItsNatComponents(node,listComp);

        return listComp.toArray(new ItsNatComponent[listComp.size()]);
    }

    public void buildItsNatComponentsInternal()
    {
        Document doc = getItsNatDocument().getDocument();
        buildItsNatComponents(doc,null);
    }

    public LinkedList<ItsNatComponent> buildItsNatComponents(Node node,LinkedList<ItsNatComponent> listComp)
    {
        // Primero procesamos el propio nodo pues si es un componente
        // puede crear y eliminar nodos hijo, luego procesamos los hijos tal y como ha quedado

        ItsNatComponent comp = addItsNatComponent(node,null,null,true); // Si no puede ser un componente no hace nada
        if (comp != null)
        {
            if (listComp == null)
                listComp = new LinkedList<ItsNatComponent>(); // Se crea cuando se necesita
            listComp.add(comp);
        }

        Node child = node.getFirstChild();
        while(child != null)
        {
            listComp = buildItsNatComponents(child,listComp);
            child = child.getNextSibling();
        }

        return listComp;
    }

    public ItsNatComponent[] removeItsNatComponents(boolean dispose)
    {
        Map<Node,ItsNatComponent> components = getComponentMap();
        if (!components.isEmpty())
        {
            ItsNatComponent[] listRes = new ItsNatComponent[components.size()];
            int i = 0;
            for (Map.Entry<Node,ItsNatComponent> entry : components.entrySet())
            {
                ItsNatComponent comp = entry.getValue();
                if (dispose) comp.dispose();
                listRes[i] = comp;
                i++;
            }
            components.clear();
            return listRes;
        }
        else
            return null;
    }

    public ItsNatComponent[] removeItsNatComponents(Node node,boolean dispose)
    {
        LinkedList<ItsNatComponent> listComp = new LinkedList<ItsNatComponent>();
        removeItsNatComponents(node,dispose,listComp);
        return listComp.toArray(new ItsNatComponent[listComp.size()]);
    }

    public void removeItsNatComponents(Node node,boolean dispose,LinkedList<ItsNatComponent> listComp)
    {
        // Primero los hijos por si acaso
        Node child = node.getFirstChild();
        while(child != null)
        {
            removeItsNatComponents(child,dispose,listComp);
            child = child.getNextSibling();
        }

        ItsNatComponent comp = removeItsNatComponent(node,dispose);
        if ((comp != null)&&(listComp != null))
            listComp.add(comp);
    }

    public void startLoading()
    {
        if (isAutoBuildComponents())
            initAutoBuildComponents();
    }

    public void initAutoBuildComponents()
    {
        buildItsNatComponentsInternal();

        // Registramos un listener tal que las mutaciones en el documento
        // desde ahora se manifiesten en a�adido o quitado autom�tico de componentes
        // Registramos despu�s de hacer la llamada buildItsNatComponents();
        // porque se hace de arriba abajo tal que aunque el componente a�ada y quite
        // nodos que puedan tener a su vez componentes posteriormente se procesan
        // los hijos del nodo-componente tal y como quedan tras crear el componente
        // Si el componente creara/borrara nodos con posibles componentes en otro lugar diferente a bajo s� mismo
        // no se detectar�a pero no hay ning�n componente que haga esto.
        // En dicho caso se registrar�a antes este listener aunque ralentiza m�s pues hay que evitar
        // a�adir componentes cuando ya se han a�adido

        DocMutationEventListenerImpl mutEventListener = getItsNatDocumentImpl().getDocMutationEventListener();
        mutEventListener.setAutoBuildCompBeforeAfterMutationRenderListener(new AutoBuildCompBeforeAfterMutationRenderListener(this));
    }

    public static String getCompTypeAttribute(Element element)
    {
        String value = element.getAttributeNS(NamespaceUtil.ITSNAT_NAMESPACE,"compType");
        if (value.equals(""))
            return null;
        return value;
    }

    public static boolean isComponentAttribute(Element element)
    {
        String value = element.getAttributeNS(NamespaceUtil.ITSNAT_NAMESPACE,"isComponent");
        return value.equals("true");
    }

    public static boolean explicitIsNotComponentAttribute(Element element)
    {
        // En este caso es true s�lo cuando isComponent existe y est� puesto como "false" expl�citamente
        String value = element.getAttributeNS(NamespaceUtil.ITSNAT_NAMESPACE,"isComponent");
        return value.equals("false");
    }

    public static boolean declaredAsComponent(Element element)
    {
        String type = getCompTypeAttribute(element);
        return (type != null);
    }

    public ItsNatLabelRenderer createDefaultItsNatLabelRenderer()
    {
        return new ItsNatLabelRendererDefaultImpl(this);
    }

    public ItsNatListCellRenderer createDefaultItsNatListCellRenderer()
    {
        return new ItsNatListCellRendererDefaultImpl(this);
    }

    public ItsNatTableCellRenderer createDefaultItsNatTableCellRenderer()
    {
        return new ItsNatTableCellRendererDefaultImpl(this);
    }

    public ItsNatTableHeaderCellRenderer createDefaultItsNatTableHeaderCellRenderer()
    {
        return new ItsNatTableHeaderCellRendererDefaultImpl(this);
    }

    public ItsNatTreeCellRenderer createDefaultItsNatTreeCellRenderer()
    {
        return new ItsNatTreeCellRendererDefaultImpl(this);
    }

    public ItsNatFreeInclude createItsNatFreeInclude(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeIncludeImpl.SINGLETON.createItsNatFreeInclude(element,artifacts,true,this);
    }

    public ItsNatFreeLabel createItsNatFreeLabel(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeLabelImpl.SINGLETON.createItsNatFreeLabel(element,artifacts,true,this);
    }

    public ItsNatFreeButtonNormal createItsNatFreeButtonNormal(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeButtonNormalDefaultImpl.SINGLETON.createItsNatFreeButtonNormalDefault(element,artifacts,true,this);
    }

    public ItsNatFreeButtonNormalLabel createItsNatFreeButtonNormalLabel(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeButtonNormalLabelImpl.SINGLETON.createItsNatFreeButtonNormalLabel(element,artifacts,true,this);
    }

    public ItsNatFreeCheckBox createItsNatFreeCheckBox(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeCheckBoxDefaultImpl.SINGLETON.createItsNatFreeCheckBox(element,artifacts,true,this);
    }

    public ItsNatFreeCheckBoxLabel createItsNatFreeCheckBoxLabel(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeCheckBoxLabelImpl.SINGLETON.createItsNatFreeCheckBoxLabel(element,artifacts,true,this);
    }

    public ItsNatFreeRadioButton createItsNatFreeRadioButton(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeRadioButtonDefaultImpl.SINGLETON.createItsNatFreeRadioButton(element,artifacts,true,this);
    }

    public ItsNatFreeRadioButtonLabel createItsNatFreeRadioButtonLabel(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeRadioButtonLabelImpl.SINGLETON.createItsNatFreeRadioButtonLabel(element,artifacts,true,this);
    }

    public ItsNatFreeComboBox createItsNatFreeComboBox(Element element,ItsNatListStructure structure,NameValue[] artifacts)
    {
        return FactoryItsNatFreeComboBoxImpl.SINGLETON.createItsNatFreeComboBox(element,structure,artifacts,true,this);
    }

    public ItsNatFreeListMultSel createItsNatFreeListMultSel(Element element,ItsNatListStructure structure,NameValue[] artifacts)
    {
        return FactoryItsNatFreeListMultSelImpl.SINGLETON.createItsNatFreeListMultSel(element,structure,artifacts,true,this);
    }

    public ItsNatFreeTable createItsNatFreeTable(Element element,ItsNatTableStructure structure,NameValue[] artifacts)
    {
        return FactoryItsNatFreeTableImpl.SINGLETON.createItsNatFreeTable(element,structure,artifacts,true,this);
    }

    public ItsNatFreeTree createItsNatFreeTree(Element element,NameValue[] artifacts)
    {
        return FactoryItsNatFreeTreeImpl.SINGLETON.createItsNatFreeTree(element,artifacts,true,this);
    }

    public ItsNatFreeTree createItsNatFreeTree(Element element,boolean treeTable,boolean rootless,ItsNatTreeStructure structure,NameValue[] artifacts)
    {
        return FactoryItsNatFreeTreeImpl.SINGLETON.createItsNatFreeTree(element,treeTable,rootless,structure,artifacts,true,this);
    }

    public ItsNatListStructure createDefaultItsNatListStructure()
    {
        return ItsNatListStructureDefaultImpl.newItsNatListStructureDefault();
    }

    public ItsNatTableStructure createDefaultItsNatTableStructure()
    {
        return ItsNatTableStructureDefaultImpl.newItsNatTableStructureDefault();
    }

    public ItsNatTreeStructure createDefaultItsNatTreeStructure()
    {
        return ItsNatTreeStructureDefaultImpl.newItsNatTreeStructureDefault();
    }

    public boolean hasCreateItsNatComponentList()
    {
        if (createCompListeners == null) return false;
        return !createCompListeners.isEmpty();
    }

    public LinkedList<CreateItsNatComponentListener> getCreateItsNatComponentList()
    {
        if (createCompListeners == null)
            this.createCompListeners = new LinkedList<CreateItsNatComponentListener>(); // S�lo se crea si se necesita
        return createCompListeners;
    }

    public Iterator<CreateItsNatComponentListener> getCreateItsNatComponentListenerIterator()
    {
        if (!hasCreateItsNatComponentList()) return null;
        return createCompListeners.iterator();
    }

    public void addCreateItsNatComponentListener(CreateItsNatComponentListener listener)
    {
        LinkedList<CreateItsNatComponentListener> list = getCreateItsNatComponentList();
        list.add(listener);
    }

    public void removeCreateItsNatComponentListener(CreateItsNatComponentListener listener)
    {
        LinkedList<CreateItsNatComponentListener> list = getCreateItsNatComponentList();
        list.remove(listener);
    }

}
TOP

Related Classes of org.itsnat.impl.comp.mgr.ItsNatDocComponentManagerImpl

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.