Author: scottbw
Date: Mon Jul 18 12:42:22 2011
New Revision: 1147837
URL: http://svn.apache.org/viewvc?rev=1147837&view=rev
Log:
Load the Google Wave Gadget API Feature using the standard Feature loading
system rather than as a "special case". This should make it simpler to swap out
implementations of the Wave API in future.
Added:
incubator/wookie/trunk/features/wave/
incubator/wookie/trunk/features/wave/feature.xml
incubator/wookie/trunk/features/wave/wave.js
Removed:
incubator/wookie/trunk/WebContent/shared/js/wave.js
Modified:
incubator/wookie/trunk/src/org/apache/wookie/feature/Features.java
Added: incubator/wookie/trunk/features/wave/feature.xml
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/features/wave/feature.xml?rev=1147837&view=auto
==============================================================================
--- incubator/wookie/trunk/features/wave/feature.xml (added)
+++ incubator/wookie/trunk/features/wave/feature.xml Mon Jul 18 12:42:22 2011
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<feature>
+ <name>http://wave.google.com</name>
+ <script src="/wookie/dwr/interface/WaveImpl.js"/>
+ <script src="wave.js"/>
+</feature>
\ No newline at end of file
Added: incubator/wookie/trunk/features/wave/wave.js
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/features/wave/wave.js?rev=1147837&view=auto
==============================================================================
--- incubator/wookie/trunk/features/wave/wave.js (added)
+++ incubator/wookie/trunk/features/wave/wave.js Mon Jul 18 12:42:22 2011
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+ /*
+ * State class
+ * Implements Google Wave API for gadget wave.State object
+ * Would be easier if Google in their wisdom had reused HTML5 Storage
+ */
+ state = new function State(){
+ this.map = null;
+
+ this.get = function(key, opt_default){
+ map = state.map;
+ if (!map||map==null||typeof map == 'undefined'){
+ if (opt_default) return opt_default;
+ return null;
+ }
+ obj = map[key];
+ if(!obj || obj === null || typeof obj == 'undefined'){
+ obj = opt_default;
+ }
+ return obj;
+ }
+
+ this.getKeys = function(){
+ var keys = [];
+ var idx = 0;
+ for (key in state.map){
+ keys[idx] = key;
+ idx++;
+ }
+ return keys;
+ }
+
+ this.submitDelta = function(delta){
+ wave.submitDelta(delta);
+ }
+
+ this.submitValue = function(key,value){
+ var delta = {};
+ delta[key] = value;
+ wave.submitDelta(delta);
+ }
+
+ this.clear = function(){
+ var delta = {};
+ for (key in state.map){
+ delta[key] = null;
+ }
+ wave.submitDelta(delta);
+ }
+
+ this.toString = function(){
+ var str = "";
+ for (key in state.map){
+ str+=key+":"+state.get(key);
+ }
+ return str;
+ }
+
+ this.__setState = function(object){
+ state.map = object;
+ }
+ }
+
+/*
+ * Wave, singleton class
+ * Implements Google Wave API for "gadgets"
+ *
+ */
+ wave = new function Wave(){
+ this.participants = null;
+ this.viewer = null;
+ this.callback = null;
+ this.pcallback = null;
+ this.onParticipantUpdate = null;
+ this.isInWaveContainer = function(){ return true};
+
+ this.init = function(){
+ // Instantiate a Wave object, and load all values
+ // Note we do this synchronously, as widgets are likely
+ // to ask for a handle on this as an onLoad() event
+ dwr.engine.beginBatch();
+ WaveImpl.getParticipants(Widget.instanceid_key,
this.setParticipants);
+ WaveImpl.getViewer(Widget.instanceid_key, this.setViewer);
+ WaveImpl.state(Widget.instanceid_key, this.setState);
+ dwr.engine.endBatch({async:false});
+ dwr.engine.setActiveReverseAjax(true);
+ }
+
+ this.setState = function(data){
+ state.__setState(data);
+ }
+
+ this.setParticipants = function(parts){
+ var json = parts;
+ if (json && json!=null && json!=""){
+ var obj = eval('('+json+')');
+ wave.participants = obj.Participants;
+ for(participant in wave.participants){
+ wave.participants[participant].getDisplayName =
function(){return this.participant_display_name}
+ wave.participants[participant].getThumbnailUrl =
function(){return this.participant_thumbnail_url};
+ wave.participants[participant].getId = function(){return
this.participant_id};
+ }
+ }
+ }
+
+ this.setViewer = function(v){
+ if (v && v!=null && v!=""){
+ var vobj = eval('('+v+')');
+ wave.viewer = vobj.Participant;
+ wave.viewer.getDisplayName = function(){return
this.participant_display_name};
+ wave.viewer.getThumbnailUrl = function(){return
this.participant_thumbnail_url};
+ wave.viewer.getId = function(){return this.participant_id};
+ }
+ }
+
+
+ //////////////////////////////////////////////////
+ // State Management
+
+ this.getState = function(){
+ return state;
+ }
+
+ this.submitDelta = function(delta){
+ if (delta && delta!=null){
+ // hack to force into a map
+ var thedelta = {};
+ for (object in delta){
+ thedelta[object] = delta[object];
+ }
+ WaveImpl.submitDelta(Widget.instanceid_key, thedelta);
+ }
+ }
+
+ // Sets the state callback; at this point we'll also do a
+ // state initial load - before this its a bit mean as the
+ // widget won't know if its changed from its initial state.
+ this.setStateCallback = function(callback, opt_context){
+ wave.callback = callback;
+ Widget.onSharedUpdate = wave.__callback;
+ wave.__callback();
+ }
+
+ // We have to capture the callback method and wrap it in our private
functions
+ this.__callback = function(){
+ WaveImpl.state(Widget.instanceid_key, wave.__update);
+ }
+ this.__update = function(data){
+ state.__setState(data);
+ wave.callback();
+ }
+
+ //////////////////////////////////////////////////
+ // Participants
+
+ this.getParticipants = function(){
+ return this.participants;
+ }
+
+ this.getViewer = function(){
+ return this.viewer;
+ }
+
+ this.getHost = function(){
+ return null; // NOT IMPLEMENTED
+ }
+
+ this.getParticipantById = function(id){
+ for (x=0;x<this.participants.length;x++){
+ if (this.participants[x].getId() == id) return
this.participants[x];
+ }
+ return null;
+ }
+
+ this.setParticipantCallback = function(callback, opt_context){
+ wave.pcallback = callback;
+ wave.onParticipantUpdate = wave.__pcallback;
+ wave.__pcallback();
+ }
+ // We have to capture the callback method and wrap it in our private
functions
+ this.__pcallback = function(){
+ WaveImpl.getParticipants(Widget.instanceid_key, wave.__pupdate);
+ }
+ this.__pupdate = function(data){
+ wave.setParticipants(data);
+ wave.pcallback();
+ }
+
+ //////////////////////////////////////////////////
+ // Playback = NOT YET IMPLEMENTED
+ this.getTime = function(){
+ return null;
+ }
+
+ this.isPlayback = function(){ return false};
+ }
+
+ // very important !
+wave.init();
\ No newline at end of file
Modified: incubator/wookie/trunk/src/org/apache/wookie/feature/Features.java
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/feature/Features.java?rev=1147837&r1=1147836&r2=1147837&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/feature/Features.java
(original)
+++ incubator/wookie/trunk/src/org/apache/wookie/feature/Features.java Mon Jul
18 12:42:22 2011
@@ -23,7 +23,6 @@ import java.util.List;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
-import org.apache.wookie.feature.wave.WaveAPIImpl;
import org.apache.wookie.w3c.util.IRIValidator;
import org.jdom.Document;
import org.jdom.Element;
@@ -82,13 +81,6 @@ public class Features {
}
return featureNames.toArray(new String[featureNames.size()]);
}
-
- /**
- * Explicitly load any "special" features
- */
- public static void loadDefaultFeatures(){
- features.add(new WaveAPIImpl());
- }
/**
* Loads features from the default feature folder in the current servlet
context
@@ -99,9 +91,6 @@ public class Features {
// Clear any existing installed features
features = new ArrayList<IFeature>();
- // Load defaults
- loadDefaultFeatures();
-
// Load features from file
loadFeatures(DEFAULT_FEATURE_FOLDER, context.getContextPath() + "/" +
DEFAULT_FEATURE_FOLDER + "/");
}
@@ -159,7 +148,16 @@ public class Features {
// Construct arrays for scripts and stylesheet URLs
String[] scripts = new
String[doc.getRootElement().getChildren("script").size()];
for (int i=0;i<scriptElements.size();i++){
- scripts[i] = basePath + "/" +
scriptElements.get(i).getAttributeValue("src");
+ String src = scriptElements.get(i).getAttributeValue("src");
+ //
+ // If the script begins with "/" append as-is; otherwise prepend with
+ // a base path. This means that a feature can refer to generic shared
scripts
+ // and DWR-generated scripts.
+ //
+ if (!src.startsWith("/")){
+ src = basePath + "/" + src;
+ }
+ scripts[i] = src;
}
String[] stylesheets = new
String[doc.getRootElement().getChildren("stylesheet").size()];
for (int i=0;i<stylesheetElements.size();i++){