edu.stanford.junction.JunctionMaker.java Source code

Java tutorial

Introduction

Here is the source code for edu.stanford.junction.JunctionMaker.java

Source

/*
 * Copyright (C) 2010 Stanford University
 *
 * 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 edu.stanford.junction;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONObject;

import edu.stanford.junction.api.activity.ActivityScript;
import edu.stanford.junction.api.activity.Cast;
import edu.stanford.junction.api.activity.JunctionActor;
import edu.stanford.junction.api.messaging.MessageHeader;
import edu.stanford.junction.JunctionException;
import edu.stanford.junction.provider.JunctionProvider;
import edu.stanford.junction.provider.jvm.JVMSwitchboardConfig;
import edu.stanford.junction.provider.jx.JXSwitchboardConfig;
import edu.stanford.junction.provider.xmpp.XMPPSwitchboardConfig;
import edu.stanford.junction.provider.irc.IRCSwitchboardConfig;

/**
 * This class creates {@link Junction} objects, binding {@link JunctionActor}
 * objects to an activity.
 */
public class JunctionMaker {
    public static final String DIRECTOR_ACTIVITY = "edu.stanford.junction.director";
    public static final URI CASTING_DIRECTOR = URI.create("junction://jx-director-local/cast");
    protected JunctionProvider mProvider;

    public static final URI SWITCHBOARD_ACTIVITY = URI.create("junction://sb.openjunction.org/switchboard");

    /**
     * Returns a new {@link JunctionMaker} object with the type specified
     * by the given {@link SwitchboardConfig} object.
     */
    public static JunctionMaker getInstance(SwitchboardConfig switchboardConfig) {
        // TODO: map config to maker?
        JunctionMaker maker = new JunctionMaker();
        maker.mProvider = maker.getProvider(switchboardConfig);
        maker.mProvider.setJunctionMaker(maker);
        return maker;
    }

    public static String getSessionIDFromURI(URI uri) {
        try {
            return uri.getPath().substring(1);
        } catch (Exception e) {
            return null;
        }
    }

    public JunctionMaker() {

    }

    /**
     * Binds a {@link JunctionActor} to a session URI, using the default
     * switchboard for that URI.
     */
    public static Junction bind(URI uri, JunctionActor actor) throws JunctionException {
        return JunctionMaker.getInstance(JunctionMaker.getDefaultSwitchboardConfig(uri)).newJunction(uri, actor);
    }

    /**
     * Binds a {@link JunctionActor} to a randomly generated sesssion, using the default
     * switchboard.
     */
    public static Junction bind(JunctionActor actor) throws JunctionException {
        // default
        SwitchboardConfig config = new XMPPSwitchboardConfig("prpl.stanford.edu");
        JunctionMaker maker = JunctionMaker.getInstance(config);
        return maker.newJunction(maker.generateSessionUri(), actor);
    }

    protected JunctionProvider getProvider(SwitchboardConfig switchboardConfig) {
        if (switchboardConfig instanceof XMPPSwitchboardConfig) {
            return new edu.stanford.junction.provider.xmpp.JunctionProvider(
                    (XMPPSwitchboardConfig) switchboardConfig);
        } else if (switchboardConfig instanceof JVMSwitchboardConfig) {
            return new edu.stanford.junction.provider.jvm.JunctionProvider(
                    (JVMSwitchboardConfig) switchboardConfig);
        } else if (switchboardConfig instanceof JXSwitchboardConfig) {
            return new edu.stanford.junction.provider.jx.JunctionProvider((JXSwitchboardConfig) switchboardConfig);
        } else if (switchboardConfig instanceof IRCSwitchboardConfig) {
            return new edu.stanford.junction.provider.irc.JunctionProvider(
                    (IRCSwitchboardConfig) switchboardConfig);
        } else {
            // Unknown implementation;.
            return null;
        }
    }

    /*
     * JunctionMaker has three functions:
     * (1) Connect an Actor to a Junction
     * (2) Retrieve an activity's script given a URI
     * (3) Support various invitation mechanisms (often platform-specific)
     */

    /**
     * This method has been deprecated. Please see 
     * {@link newJunction(URI, ActivityScript, JunctionActor)}
     */
    public Junction newJunction(URI uri, JunctionActor actor) throws JunctionException {
        return mProvider.newJunction(uri, null, actor);
    }

    @Deprecated
    public Junction newJunction(URI uri, ActivityScript script, JunctionActor actor) throws JunctionException {
        return mProvider.newJunction(uri, script, actor);
    }

    @Deprecated
    public Junction newJunction(ActivityScript desc, JunctionActor actor) throws JunctionException {
        URI sessionUri;
        if (desc == null) {
            desc = new ActivityScript();
        }
        if (desc.getSessionID() == null) {
            sessionUri = mProvider.generateSessionUri();
            desc.isActivityCreator(true);
            desc.setUri(sessionUri);
        } else {
            // TODO: get rid of this.
            try {
                sessionUri = new URI("junction://" + desc.getHost() + "/" + desc.getSessionID());
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException("Bad URI from activity script");
            }
        }

        return mProvider.newJunction(sessionUri, desc, actor);
    }

    public URI generateSessionUri() {
        return mProvider.generateSessionUri();
    }

    /**
     * Creates a new Junction and requests the casting of various roles.
     * There is no guarantee if and when the roles will be filled.
     * There may or may not be user interaction at the casting director.
     * 
     * @param desc
     * @param actor
     * @param support
     * @return
     */
    public Junction newJunction(ActivityScript desc, JunctionActor actor, Cast support) throws JunctionException {
        Junction jx = newJunction(desc, actor);
        //System.out.println("creating activity " + desc.getJSON());
        int size = support.size();
        System.out.println("going to cast " + size + " roles");
        for (int i = 0; i < size; i++) {
            if (support.getDirector(i) != null) {
                //System.out.println("Casting role " + support.getRole(i) + " on " + support.getDirector(i));
                URI invitationURI = jx.getInvitationURI(support.getRole(i));
                this.castActor(support.getDirector(i), invitationURI);
            }
        }

        return jx;
    }

    /**
     * Sends a message to an activity. In the
     * unoptimized case, joins an activity, sends
     * a message, and leaves.
     * 
     * @param activitySession
     * @param msg
     */
    public void sendMessageToActivity(URI activitySession, JSONObject msg) throws JunctionException {
        mProvider.sendMessageToActivity(activitySession, msg);
    }

    public ActivityScript getActivityScript(URI uri) throws JunctionException {
        return mProvider.getActivityScript(uri);
    }

    /**
     * Sends a request to a Director activity
     * to cast an actor to accept a given invitation.
     * 
     * @param directorURI The director listening for requests
     * @param invitationURI The activity to join (potentially including role information)
     */
    public void castActor(final URI directorURI, final URI invitationURI) throws JunctionException {
        JunctionActor actor = new JunctionActor("inviter") {
            @Override
            public void onActivityJoin() {
                JSONObject invitation = new JSONObject();
                try {
                    invitation.put("action", "cast");
                    invitation.put("activity", invitationURI.toString());
                    getJunction().sendMessageToSession(invitation);
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                }

                leave();
            }

            @Override
            public void onMessageReceived(MessageHeader header, JSONObject message) {

            }
        };

        JunctionMaker.this.newJunction(directorURI, actor);
    }

    /**
     * Returns the role associated with a given Junction invitation.
     * @param uri
     * @return
     */
    public static String getRoleFromInvitation(URI uri) {
        String query = uri.getQuery();
        if (query == null)
            return null;
        int pos = query.indexOf("role=");
        if (pos == -1) {
            return null;
        }

        query = query.substring(pos + 5);
        pos = query.indexOf('&');
        if (pos > -1) {
            query = query.substring(0, pos);
        }
        return query;
    }

    @Deprecated
    public void inviteActorByListenerService(final URI invitationURI, URI listenerServiceURI)
            throws JunctionException {
        JunctionActor actor = new JunctionActor("inviter") {
            @Override
            public void onActivityJoin() {
                JSONObject invitation = new JSONObject();
                try {
                    invitation.put("activity", invitationURI.toString());
                    getJunction().sendMessageToSession(invitation);
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                }
                leave();
            }

            @Override
            public void onMessageReceived(MessageHeader header, JSONObject message) {

            }
        };

        JunctionMaker.this.newJunction(listenerServiceURI, actor);
    }

    /**
     * Requests a listening service to join this activity as the prescribed role. Here,
     * the service must be detailed in the activity description's list of roles.
     * 
     * An example platform in the role specification:
     * { role: "dealer", platforms: [ 
     *                   { platform: "jxservice", 
     *                     classname: "edu.stanford.prpl.poker.dealer",
     *                     switchboard: "my.foreign.switchboard" } ] }
     * 
     * If switchboard is not present, it is assumed to be on the same switchboard
     * on which this activity is being run.
     * 
     * @param role
     * @param host
     * @param serviceName
     */
    @Deprecated
    public void inviteActorService(final Junction jx, final String role) throws JunctionException {
        ActivityScript desc = jx.getActivityScript();
        System.out.println("Desc: " + desc.getJSON().toString());
        // find service platform spec

        System.out.println("inviting service for role " + role);

        JSONObject platform = desc.getRolePlatform(role, "jxservice");
        System.out.println("got platform " + platform);
        if (platform == null)
            return;

        String switchboard = platform.optString("switchboard");
        System.out.println("switchboard: " + switchboard);
        if (switchboard == null || switchboard.length() == 0) {
            switchboard = jx.getSwitchboard();
            System.out.println("switchboard is null, new: " + switchboard);
        }
        final String serviceName = platform.optString("serviceName");

        // // // // // // // // // // // // // // // // 
        JunctionActor actor = new JunctionActor("inviter") {
            @Override
            public void onActivityJoin() {
                JSONObject invitation = new JSONObject();
                try {
                    invitation.put("activity", jx.getInvitationURI(role));
                    invitation.put("serviceName", serviceName);
                } catch (Exception e) {
                }
                getJunction().sendMessageToSession(invitation);
                leave();
            }

            @Override
            public void onMessageReceived(MessageHeader header, JSONObject message) {

            }
        };

        // remote jxservice activity:
        URI remoteServiceActivity = null;
        try {
            remoteServiceActivity = new URI("junction://" + switchboard + "/jxservice");
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return;
        }
        System.out.println("Inviting service at uri " + remoteServiceActivity);
        JunctionMaker.this.newJunction(remoteServiceActivity, actor);
    }

    public static SwitchboardConfig getDefaultSwitchboardConfig(URI uri) {
        String fragment = uri.getFragment();
        if (fragment == null) {
            fragment = "xmpp";
        }
        fragment = fragment.toLowerCase();
        if (fragment.equals("jvm")) {
            return new edu.stanford.junction.provider.jvm.JVMSwitchboardConfig();
        } else if (fragment.equals("jx")) {
            return new edu.stanford.junction.provider.jx.JXSwitchboardConfig();
        } else if (fragment.equals("jx")) {
            return new edu.stanford.junction.provider.jx.JXSwitchboardConfig();
        } else if (fragment.equals("irc")) {
            return new edu.stanford.junction.provider.irc.IRCSwitchboardConfig();
        }

        // assume xmpp
        return new edu.stanford.junction.provider.xmpp.XMPPSwitchboardConfig(uri);
    }
}