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

org.apache.tapestry5.internal.structure.PageImpl Maven / Gradle / Ivy

Go to download

Central module for Tapestry, containing interfaces to the Java Servlet API and all core services and components.

There is a newer version: 5.8.6
Show newest version
// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.internal.structure;

import java.util.List;
import java.util.Locale;

import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.internal.services.PersistentFieldManager;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.internal.util.OneShotLock;
import org.apache.tapestry5.ioc.services.PerThreadValue;
import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.PageLifecycleListener;
import org.apache.tapestry5.services.PersistentFieldBundle;
import org.slf4j.Logger;

public class PageImpl implements Page
{
    private final String name;

    private final Locale locale;

    private final PersistentFieldManager persistentFieldManager;

    private ComponentPageElement rootElement;

    private final List lifecycleListeners = CollectionFactory.newThreadSafeList();

    private final List resetListeners = CollectionFactory.newList();

    private final PerThreadValue dirtyCount;

    private boolean loadComplete;

    private final OneShotLock lock = new OneShotLock();

    /**
     * Obtained from the {@link org.apache.tapestry5.internal.services.PersistentFieldManager} when
     * first needed,
     * discarded at the end of the request.
     */
    private final PerThreadValue fieldBundle;

    /**
     * @param name
     *            canonicalized page name
     * @param locale
     *            locale for page and all components
     * @param persistentFieldManager
     *            for access to cross-request persistent values
     * @param perThreadManager
     *            for managing per-request mutable state
     * @param pooled
     *            if pooling enabled, or is this page a singleton
     */
    public PageImpl(String name, Locale locale, PersistentFieldManager persistentFieldManager,
            PerthreadManager perThreadManager, boolean pooled)
    {
        this.name = name;
        this.locale = locale;
        this.persistentFieldManager = persistentFieldManager;

        if (pooled)
        {
            dirtyCount = perThreadManager.createValue();
        }
        else
        {
            dirtyCount = null;
        }

        fieldBundle = perThreadManager.createValue();
    }

    @Override
    public String toString()
    {
        return String.format("Page[%s %s]", name, locale);
    }

    public ComponentPageElement getComponentElementByNestedId(String nestedId)
    {
        assert nestedId != null;
        ComponentPageElement element = rootElement;

        if (InternalUtils.isNonBlank(nestedId))
        {
            for (String id : nestedId.split("\\."))
                element = element.getEmbeddedElement(id);
        }

        return element;
    }

    public Locale getLocale()
    {
        return locale;
    }

    public void setRootElement(ComponentPageElement component)
    {
        lock.check();

        rootElement = component;
    }

    public ComponentPageElement getRootElement()
    {
        return rootElement;
    }

    public Component getRootComponent()
    {
        return rootElement.getComponent();
    }

    public void addLifecycleListener(PageLifecycleListener listener)
    {
        lock.check();

        lifecycleListeners.add(listener);
    }

    public void removeLifecycleListener(PageLifecycleListener listener)
    {
        lock.check();

        lifecycleListeners.remove(listener);
    }

    public boolean detached()
    {
        boolean result = dirtyCount != null && dirtyCount.exists() && dirtyCount.get() > 0;

        for (PageLifecycleListener listener : lifecycleListeners)
        {
            try
            {
                listener.containingPageDidDetach();
            }
            catch (RuntimeException ex)
            {
                getLogger().error(StructureMessages.detachFailure(listener, ex), ex);
                result = true;
            }
        }

        return result;
    }

    public void loaded()
    {
        lock.check();

        for (PageLifecycleListener listener : lifecycleListeners)
            listener.containingPageDidLoad();

        loadComplete = true;

        lock.lock();
    }

    public void attached()
    {
        if (dirtyCount != null && dirtyCount.exists() && !dirtyCount.get().equals(0))
            throw new IllegalStateException(StructureMessages.pageIsDirty(this));

        for (PageLifecycleListener listener : lifecycleListeners)
            listener.restoreStateBeforePageAttach();

        for (PageLifecycleListener listener : lifecycleListeners)
            listener.containingPageDidAttach();
    }

    public Logger getLogger()
    {
        return rootElement.getLogger();
    }

    public void persistFieldChange(ComponentResources resources, String fieldName, Object newValue)
    {
        if (!loadComplete)
            throw new RuntimeException(StructureMessages.persistChangeBeforeLoadComplete());

        persistentFieldManager.postChange(name, resources, fieldName, newValue);
    }

    public Object getFieldChange(String nestedId, String fieldName)
    {
        if (!fieldBundle.exists())
            fieldBundle.set(persistentFieldManager.gatherChanges(name));

        return fieldBundle.get().getValue(nestedId, fieldName);
    }

    public void decrementDirtyCount()
    {
        if (dirtyCount != null)
        {
            int newCount = dirtyCount.get() - 1;

            dirtyCount.set(newCount);
        }
    }

    public void discardPersistentFieldChanges()
    {
        persistentFieldManager.discardChanges(name);
    }

    public void incrementDirtyCount()
    {
        if (dirtyCount != null)
        {
            int newCount = dirtyCount.get(0) + 1;

            dirtyCount.set(newCount);
        }
    }

    public String getName()
    {
        return name;
    }

    public void addResetListener(PageResetListener listener)
    {
        assert listener != null;
        lock.check();

        resetListeners.add(listener);
    }

    public void pageReset()
    {
        for (PageResetListener l : resetListeners)
        {
            l.containingPageDidReset();
        }
    }

    public boolean hasResetListeners()
    {
        return !resetListeners.isEmpty();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy