I've attached a JRuby port of Echoey.java. Right now, it just lives in
the top-level wave-protocol directory.

Like the original Echoey, it has some major limitations. In
particular, when you add it to an existing wave, it will replay the
conversation from the beginning and echo everything. This could be
fixed by (1) watching for the first SELF_ADDED event and (2) using a
[email protected] wave to store the "read" status of the wave.

It would be possible to make this code much nicer by supplying Ruby
versions of AbstractAgent and DocOpCursor. But there's not much point
in doing that until the "echo everything from start of the
conversation" bug is fixed.

Cheers,
Eric

diff -r eb5755fb954b build.properties
--- a/build.properties  Wed Sep 02 08:56:24 2009 +1000
+++ b/build.properties  Sat Sep 05 15:44:34 2009 +0200
@@ -26,4 +26,5 @@
 jar.outfile-server=${dir.distribute}/fedone-server-$
{fedone.version}.jar
 jar.outfile-client-console=${dir.distribute}/fedone-client-console-$
{fedone.version}.jar
 jar.outfile-agent-echoey=${dir.distribute}/fedone-agent-echoey-$
{fedone.version}.jar
+jar.outfile-agent-api=${dir.distribute}/fedone-agent-api-$
{fedone.version}.jar

diff -r eb5755fb954b build.xml
--- a/build.xml Wed Sep 02 08:56:24 2009 +1000
+++ b/build.xml Sat Sep 05 15:44:34 2009 +0200
@@ -187,7 +187,7 @@
     </copy>
   </target>

-  <target name="dist" depends="test, dist-api, dist-server, dist-
client-console, dist-agent-echoey" description="Compiles, tests and
assembles artifacts">
+  <target name="dist" depends="test, dist-api, dist-server, dist-
client-console, dist-agent-echoey,dist-agent-api"
description="Compiles, tests and assembles artifacts">
   </target>

   <target name="dist-api" depends="stage" description="Assembles the
FedOne API">
@@ -277,6 +277,22 @@
     </jar>
   </target>

+  <target name="dist-agent-api" depends="stage"
description="Assembles the FedOne agent API">
+    <jar destfile="${jar.outfile-agent-api}">
+      <fileset dir="${staging}">
+        <include name="com/google/common/**/*" />
+        <include name="com/google/inject/**/*" />
+        <include name="com/google/protobuf/**/*" />
+        <include name="org/apache/commons/codec/**/*" />
+        <include name="org/waveprotocol/**/*" />
+      </fileset>
+      <manifest>
+        <attribute name="Implementation-Title" value="Wave FedOne
Agent API"/>
+        <attribute name="Implementation-Version" value="$
{fedone.version}"/>
+      </manifest>
+    </jar>
+  </target>
+
   <!-- This rule should be run whenever the build configuration (i.e.
build files, libraries) is changed -->
   <target name="dist-test" depends="dist, test" description="Runs all
the unit tests in the project against the jar files">
     <taskdef name="junit"
classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
diff -r eb5755fb954b rechoey.rb
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/rechoey.rb        Sat Sep 05 15:44:34 2009 +0200
@@ -0,0 +1,118 @@
+# Copyright 2009 Google Inc. (original Java code)
+# Copyright 2009 Eric Kidd (Ruby translation)
+#
+# 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.
+
+# Usage: jruby rechoey.rb rech...@domain server port
+
+require 'java'
+require 'dist/fedone-agent-api-0.2.jar'
+
+import 'com.google.common.collect.ImmutableMap'
+
+import
'org.waveprotocol.wave.examples.fedone.agents.agent.AbstractAgent'
+import
'org.waveprotocol.wave.examples.fedone.agents.agent.AgentConnection'
+import
'org.waveprotocol.wave.examples.fedone.waveclient.common.ClientUtils'
+import
'org.waveprotocol.wave.examples.fedone.waveclient.console.ConsoleUtils'
+import 'org.waveprotocol.wave.model.document.operation.DocOpCursor'
+import
'org.waveprotocol.wave.model.document.operation.impl.AttributesImpl'
+import
'org.waveprotocol.wave.model.document.operation.impl.BufferedDocOpImpl'
+import
'org.waveprotocol.wave.model.operation.wave.WaveletDocumentOperation'
+
+# This is a simple translation of the Java Echoey code.
+class REchoey < AbstractAgent
+  def initialize(username, hostname, port=9876)
+    super(AgentConnection.new_connection(username, hostname, port))
+  end
+
+  def doc_size wavelet, doc_name
+    doc = wavelet.documents.get(doc_name)
+    doc ? ClientUtils.find_document_size(doc) : 0
+  end
+
+  def append_lines(wavelet, lines)
+    # Build the operation we want to perform on the document.
+    builder = BufferedDocOpImpl::DocOpBuilder.new
+    size = doc_size(wavelet, "main")
+    builder.retain(size) if size > 0
+    line_attrs = ImmutableMap.of(ConsoleUtils::LINE_AUTHOR,
participant_id)
+    builder.element_start(ConsoleUtils::LINE, AttributesImpl.new
(line_attrs))
+    builder.element_end
+    lines.each {|line| builder.characters(line) unless line.empty? }
+
+    # Send the operation.
+    op = WaveletDocumentOperation.new("main", builder.finish)
+    send_wavelet_operation(wavelet.wavelet_name, op)
+  end
+
+  def append_line(wavelet, line)
+    append_lines(wavelet, [line])
+  end
+
+  def onDocumentChanged(wavelet, operation)
+    extractor = TextExtractor.new
+    operation.operation.apply(extractor)
+    append_lines(wavelet, extractor.lines)
+  end
+
+  def onParticipantAdded(wavelet, participant)
+    append_line(wavelet, "#{participant.address} was added to this
wavelet.")
+  end
+
+  def onParticipantRemoved(wavelet, participant)
+    append_line(wavelet, "#{participant.added} was removed from this
wavelet.")
+  end
+
+  def onSelfAdded(wavelet)
+    append_line(wavelet, "I'm listening.")
+  end
+
+  def onSelfRemoved(wavelet)
+    append_line(wavelet, "Goodbye.")
+  end
+
+  # Iterate over a document operation and extract all the newly-
inserted text.
+  class TextExtractor
+    include DocOpCursor
+
+    attr_reader :lines
+
+    def initialize()
+      @lines = []
+    end
+
+    def annotationBoundary(map) end
+
+    def characters(chars)
+      lines << chars
+    end
+
+    def deleteCharacters(chars) end
+    def deleteElementEnd() end
+    def deleteElementStart(type, attrs) end
+    def elementEnd() end
+    def elementStart(type, attrs) end
+    def replaceAttributes(oldAttrs, newAttrs) end
+    def retain(itemCount) end
+    def updateAttributes(attrUpdate) end
+  end
+end
+
+# Parse our command-line arguments and run rechoey.
+if ARGV.length != 3
+  STDERR.puts "Usage: jruby rechoey.rb u...@domain server port"
+  exit 1
+end
+username, hostname, port = ARGV
+e = REchoey.new(username, hostname, port.to_i)
+e.run
diff -r eb5755fb954b run-agent-rechoey.sh
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/run-agent-rechoey.sh      Sat Sep 05 15:44:34 2009 +0200
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# This script will start the Echoey the FedOne wave agent.
+#
+
+if [ -f run-config.sh ] ; then
+  . run-config.sh
+else
+  echo "You need to copy run-config.sh.example to run-config.sh and
configure" ; exit 1
+fi
+
+user_name=rech...@$wave_server_domain_name
+echo "running agent.echoey as user: ${USER_NAME}"
+jruby rechoey.rb $USER_NAME $WAVE_SERVER_HOSTNAME $WAVE_SERVER_PORT



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Wave 
Protocol" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/wave-protocol?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to