Package de.dfki.km.text20.browserplugin.services.sessionrecorder.impl.plainxml

Source Code of de.dfki.km.text20.browserplugin.services.sessionrecorder.impl.plainxml.SessionReplayImpl

package de.dfki.km.text20.browserplugin.services.sessionrecorder.impl.plainxml;

import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import net.xeoh.plugins.base.util.OptionUtils;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.ReplayListener;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.SessionReplay;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.events.AbstractSessionEvent;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.events.PropertyEvent;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.events.ScreenSizeEvent;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.options.ReplayOption;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.options.replay.OptionGetMetaInfo;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.options.replay.OptionRealtime;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.options.replay.OptionSlowMotion;
import de.dfki.km.text20.browserplugin.services.sessionrecorder.util.metadata.DisplacementRegion;

/**
* @author rb
*
*/
public class SessionReplayImpl implements SessionReplay {

    /* (non-Javadoc)
     * @see de.dfki.km.augmentedtext.browserplugin.services.sessionrecorder.SessionReplay#replay(de.dfki.km.augmentedtext.browserplugin.services.sessionrecorder.ReplayListener, de.dfki.km.augmentedtext.browserplugin.services.sessionrecorder.options.ReplayOption[])
     */
    @Override
    public void replay(final ReplayListener listener, final ReplayOption... options) {

        final List<AbstractSessionEvent> allEvents = this.record.getAllEvents();
        final CyclicBarrier barrier = new CyclicBarrier(2);

        final OptionUtils<ReplayOption> ou = new OptionUtils<ReplayOption>(options);
        if (ou.contains(OptionGetMetaInfo.class)) setGettingMetaInfo(true);
        if (ou.contains(OptionRealtime.class)) setRealtimeReplay(true);
        if (ou.contains(OptionSlowMotion.class)) {
            setRealtimeReplay(true);
            setSlowdown(ou.get(OptionSlowMotion.class).getFactor());
        }

        // Create replay thread
        final Thread t = new Thread(new Runnable() {

            @Override
            public void run() {

                AbstractSessionEvent previousEvent = null;

                while (allEvents.size() > 0) {
                    AbstractSessionEvent event = null;

                    event = allEvents.get(0);
                    allEvents.remove(0);

                    if (previousEvent == null) {
                        SessionReplayImpl.this.firstEventtime = event.originalEventTime;
                        previousEvent = event;
                    }
                    SessionReplayImpl.this.currentEventime = event.originalEventTime;

                    // Dont process if filtered
                    if (!SessionReplayImpl.this.toFilter.contains(event.getClass())) {
                        if (!isGettingMetaInfo()) {
                            listener.nextEvent(event);

                            // Can be switched off, to make replay as fast as possible.
                            if (SessionReplayImpl.this.realtimeReplay && !isGettingMetaInfo()) {
                                // Sleep till next event
                                long delta = event.originalEventTime - previousEvent.originalEventTime;
                                if (delta <= 0) {
                                    delta = 0;
                                }

                                try {
                                    Thread.sleep(delta * SessionReplayImpl.this.slowdownFactor);
                                } catch (final InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }

                            previousEvent = event;
                        } else {
                            if (event instanceof ScreenSizeEvent) {
                                SessionReplayImpl.this.screenSize = ((ScreenSizeEvent) event).screenSize;
                                //                                                                                System.out.println(event);
                            }
                            if (event instanceof PropertyEvent) {
                                SessionReplayImpl.this.propertyMap.put(((PropertyEvent) event).key, ((PropertyEvent) event).value);
                                //                                                                                System.out.println(event);
                            }
                        }
                    }
                }

                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        t.setDaemon(true);
        t.start();

        // Synchronize with starting of thread.
        try {
            barrier.await();
        } catch (final InterruptedException e) {
            e.printStackTrace();
        } catch (final BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    /**
     * Makes other threads wait for this element to be finished.
     */
    Lock finishedLock = new ReentrantLock();

    /** Should we print timing information */
    @SuppressWarnings("unused")
    private final boolean printTiming = true;

    /** If the replay is in realtime, or as fast as possible */
    boolean realtimeReplay = false;

    /**
     * controls the behaviour of the replay method if true, only the property and screen
     * size 'events' are fetched and stored if false, the listeners will work
     */
    private boolean gettingMetaInfo = false;

    /** How far to slow down "realtime" */
    int slowdownFactor = 1;

    /** List of events to filter */
    final List<Class<? extends AbstractSessionEvent>> toFilter = new ArrayList<Class<? extends AbstractSessionEvent>>();

    /** */
    Map<String, String> propertyMap = new HashMap<String, String>();

    /** the recorded screen size */
    Dimension screenSize;

    /** the file to replay */
    private File file;

    /**  */
    private SessionRecordImpl record;

    /**  */
    protected long firstEventtime;

    /**  */
    protected long currentEventime;

    /**  */
    protected long realtimeDuration;

    /**
     * @return .
     */
    public SessionRecordImpl getRecordProxy() {
        return this.record;
    }

    /**
     * @param file
     */
    public SessionReplayImpl(final File file) {
        this.file = file;
        this.record = SessionRecordImpl.loadFrom(this.file.getAbsolutePath(), true);
    }

    /**
     * Events of that class wont be passed.
     *
     * @param filter
     */
    @SuppressWarnings("unused")
    private void addFilter(final Class<? extends AbstractSessionEvent> filter) {
        this.toFilter.add(filter);
    }

    /**
     * @return the realtimeReplay
     */
    boolean isRealtimeReplay() {
        return this.realtimeReplay;
    }

    /**
     * @param realtimeReplay
     *            the realtimeReplay to set
     */
    public void setRealtimeReplay(final boolean realtimeReplay) {
        this.realtimeReplay = realtimeReplay;
    }

    /**
     * @param factor
     */
    public void setSlowdown(final int factor) {
        this.slowdownFactor = factor;
    }

    /**
     * Waits until the replay thread has finished.
     */
    public void waitForFinish() {
        // If the lock is unlocked, do nothing
        if (this.finishedLock.tryLock()) return;

        // If it's locked, wait.
        this.finishedLock.lock();
        this.finishedLock.unlock();

        return;
    }

    /**
     * @param inStream
     * @return .
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public Object loadFromStream(final ObjectInputStream inStream) throws IOException,
                                                                  ClassNotFoundException {
        return (inStream.readObject());
    }

    /*
     * (non-Javadoc)
     *
     * @see de.dfki.km.augmentedtext.browserplugin.services.sessionrecorder.SessionReplay#getProperties()
     */
    @Override
    public Map<String, String> getProperties(String... properties) {
        return this.record.getProperties();
    }

    /*
     * (non-Javadoc)
     *
     * @see de.dfki.km.augmentedtext.browserplugin.services.sessionrecorder.SessionReplay#getScreenSize()
     */
    @Override
    public Dimension getScreenSize() {
        return this.record.getScreenSize();
    }

    /**
     * @return the gettingMetaInfo
     */
    boolean isGettingMetaInfo() {
        return this.gettingMetaInfo;
    }

    /**
     * @param gettingMetaInfo
     *            the gettingMetaInfo to set
     */
    void setGettingMetaInfo(final boolean gettingMetaInfo) {
        this.gettingMetaInfo = gettingMetaInfo;
    }

    /**
     * @return the duration of the original session
     */
    public long getRealtimeDuration() {
        return this.realtimeDuration;
    }

    /**
     * @return .
     */
    public File getFile() {
        return this.file;
    }

    /* (non-Javadoc)
     * @see de.dfki.km.text20.browserplugin.services.sessionrecorder.SessionReplay#getDisplacements()
     */
    @Override
    public List<DisplacementRegion> getDisplacements() {
        return (this.record.fixationDisplacementRegions != null) ? this.record.fixationDisplacementRegions : new ArrayList<DisplacementRegion>();
    }

}
TOP

Related Classes of de.dfki.km.text20.browserplugin.services.sessionrecorder.impl.plainxml.SessionReplayImpl

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.