FileDocCategorySizeDatePackage
TimeContainerSupport.javaAPI DocphoneME MR2 API (J2ME)9428Wed May 02 18:00:36 BST 2007com.sun.perseus.model

TimeContainerSupport.java

/*
 *
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program 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
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */
package com.sun.perseus.model;

import java.util.Vector;

import java.io.PrintStream;

/**
 *
 * @version $Id: TimeContainerSupport.java,v 1.4 2006/06/29 10:47:35 ln156897 Exp $
 */
public class TimeContainerSupport extends TimedElementSupport {
    /**
     * The container's current simple time
     */
    protected Time simpleTime = Time.UNRESOLVED;

    /**
     * The set of children TimedElementSupport contained
     * in this container.
     */
    protected Vector timedElementChildren = new Vector(5);

    /**
     * Default constructor
     */
    public TimeContainerSupport() {
    }

    /**
     * @return this container's current simple time
     */
    public Time getSimpleTime() {
        return simpleTime;
    }

    /**
     * Resets this container and all its children. This, in effect, moves the
     * container back to the begining of its timeline, i.e., prior to begining
     * the first interval.
     */
    protected void initialize() {
        super.initialize();

        // If a new interval was created, children have already been initialized
        // (see dispatchOnNewInterval). Otherwise, make sure we initialize the 
        // full tree.
        if (currentInterval == null) {
            for (int i = 0; i < timedElementChildren.size(); i++) {
                TimedElementSupport child 
                    = (TimedElementSupport) timedElementChildren.elementAt(i);
                child.initialize();
            }        
        }
    }

    /**
     * When a container resets, it needs to clear all its children which have
     * IntervalTimeInstances on syncBases which are also children 
     * (or descendants) of this container.
     *
     * @see <a href="http://www.w3.org/TR/smil20#smil-timing-Timing-ResetDefaultAttribute">
     *      SMIL 2 Specification, Resetting element state</a>
     */
    void reset() {
        super.reset();

        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child = 
                (TimedElementSupport) timedElementChildren.elementAt(i);
            child.removeSyncBaseTimesUnder(this);
        }
        
    }


    /**
     * Removes  all <code>IntervalTimeInstance</code>s in the begin and end
     * instance list if the syncBase is a descendant of syncTimeContainer
     *
     * @param syncTimeContainer the container under which times should be 
     *        removed.
     */
    void removeSyncBaseTimesUnder(
            final TimeContainerSupport syncTimeContainer) {
        super.removeSyncBaseTimesUnder(syncTimeContainer);

        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child = 
                (TimedElementSupport) timedElementChildren.elementAt(i);
            child.removeSyncBaseTimesUnder(syncTimeContainer);
        }        
    }

    /**
     * Samples this time container at the given simple time.
     *
     * @param simpleTime this timed element's simple time.
     */
    void sampleAt(final long simpleTime) {
        setSimpleTime(simpleTime);

        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child 
                = (TimedElementSupport) timedElementChildren.elementAt(i);
            if (seeking) {
                child.seeking = true;
                child.sample(this.simpleTime);
                child.seeking = false;
            } else {
                child.sample(this.simpleTime);
            }
        }
    }

    /**
     * Dispatches endEvent. As per the SMIL 2 specification, this dispatches
     * an endEvent for the resolved end time, not the observed end
     * time.
     *
     * @param currentTime the current sampling time.
     *
     * @see <a href="http://www.w3.org/TR/smil20/smil-timing.html#Timing-BeginValueSemantics">
     *      SMIL2's Begin value semantics</a>
     */
    void dispatchEndEvent(final Time currentTime) {
        super.dispatchEndEvent(currentTime);

        // Now, force children to end now. Before invoking children, we need 
        // to update the container's simpleTime.
        long time = currentInterval.end.value - currentInterval.begin.value;
        if (simpleDur.isResolved()) {
            if (time > 0) {
                time = time % simpleDur.value;
                if (time == 0) {
                    time = simpleDur.value;
                }
            } 
        }
        
        endChildrenAt(time);
    }

    /**
     * Calls all the registered <code>TimeDependent</code>s so that they
     * are notified of a new TimeInterval creation. When a time container
     * creates a new interval, its children are re-initialized.
     */
    void dispatchOnNewInterval() {
        super.dispatchOnNewInterval();
        
        // Now, re-initialize all children.
        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child = 
                (TimedElementSupport) timedElementChildren.elementAt(i);
            child.initialize();
        }                
    }

    /**
     * Implementation helper to set the simple time object.
     *
     * @param time the new simple time value
     */
    void setSimpleTime(final long time) {
        if (simpleTime == Time.UNRESOLVED) {
            simpleTime = new Time(time);
        } else {
            simpleTime.value = time;
        }
    }

    /**
     * When a container starts a new iteration, it needs to:
     * - end its children at the end of the previous interval.
     * - reset its children.
     *
     * @param prevIter the last iteration this element was playing.
     * @param curIter the new iteration this element is playing.
     */
    protected void onStartingRepeat(final int prevIter, final int curIter) {
        // First, force ending children at the end of the previous iteration.
        long time = currentInterval.begin.value 
                    + 
                    simpleDur.value * (prevIter + 1);
        
        endChildrenAt(time);

        // Now, reset the children so that they are ready for the next sampling
        // at the begining of current interval.
        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child = 
                (TimedElementSupport) timedElementChildren.elementAt(i);
            child.initialize();
        }        
        
    }

    /**
     * Implementation helper. Ends all children at the requested input time.
     *
     * @param time the time, in this container's simple time system, at which
     * children should be stopped.
     */
    void endChildrenAt(final long time) {
        setSimpleTime(time);

        // First, end all children. Adding end times does not cause a state
        // transition. To make the children transition to their new state, we 
        // invoke sample in a second iteration (see below).
        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child 
                = (TimedElementSupport) timedElementChildren.elementAt(i);
            child.end();
        }

        // Now, sample children on the end time
        for (int i = 0; i < timedElementChildren.size(); i++) {
            TimedElementSupport child 
                = (TimedElementSupport) timedElementChildren.elementAt(i);
            child.sample(simpleTime);
        }        
    }

    /**
     * Debug method: Traces the container and all its children.
     */
    /**
     * Traces this viewport tree
     */
    void dump() {
        dump(this, "", System.err);
    }

    /**
     * Debug: traces the input ModelNode, using the input prefix
     * 
     * @param t the node to dump
     * @param prefix the string used to prefix the node information
     * @param out the stream where the node structure is dumped.
     */
    static void dump(final TimedElementSupport t, final String prefix,
                     final PrintStream out) {
        out.println(prefix + t);
        if (t instanceof TimeContainerSupport) {
            TimeContainerSupport tc = (TimeContainerSupport) t;
            for (int i = 0; i < tc.timedElementChildren.size(); i++) {
                TimedElementSupport c 
                    = (TimedElementSupport) tc
                        .timedElementChildren.elementAt(i);
                dump(c, prefix + "+--> ", out);
            }
        }
    }
}