Skip to content
Browse files

Factor annotation code out into separate classes

This will eventually make it easier to have more than one annotator.
  • Loading branch information...
1 parent c13a832 commit 30c13d6a727255a8188913aa96b7d1a56477065e @emk committed Aug 29, 2009
Showing with 137 additions and 57 deletions.
  1. +78 −0 src/buglinky/Annotator.java
  2. +49 −0 src/buglinky/BugLinkAnnotator.java
  3. +10 −57 src/buglinky/BugLinkyServlet.java
View
78 src/buglinky/Annotator.java
@@ -0,0 +1,78 @@
+// buglinky - A robot for adding bugtracker links to a wave
+// Copyright 2009 Eric Kidd
+//
+// 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 buglinky;
+
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.wave.api.Annotation;
+import com.google.wave.api.Blip;
+import com.google.wave.api.Range;
+import com.google.wave.api.TextView;
+
+/**
+ * Adds annotations to a blip.
+ */
+abstract class Annotator {
+ private static final Logger LOG =
+ Logger.getLogger(Annotator.class.getName());
+
+ /** Return a regular expression matching the text we want to process. */
+ protected abstract Pattern getPattern();
+
+ /** Process a regular expression match. */
+ protected abstract void processMatch(TextView doc, Range range,
+ Matcher match);
+
+ /** Add links to the specified blip. */
+ public void processBlip(Blip blip) {
+ LOG.fine("Annotating blip " + blip.getBlipId());
+ // Adapted from http://senikk.com/min-f%C3%B8rste-google-wave-robot,
+ // a robot which links to @names on Twitter.
+ TextView doc = blip.getDocument();
+ Matcher matcher = getPattern().matcher(doc.getText());
+ while (matcher.find()) {
+ LOG.fine("Found text to annotate: " + matcher.group());
+ Range range = new Range(matcher.start(), matcher.end());
+ processMatch(doc, range, matcher);
+ }
+ }
+
+ /**
+ * Add an annotation if it isn't already present.
+ *
+ * The Wave Robot API does not currently filter out duplicate annotation
+ * requests, which causes extra network traffic and more possibilities for
+ * nasty bot loops. So we do this screening on our end.
+ */
+ protected void maybeAnnotate(TextView doc, Range range, String name,
+ String value) {
+ // If this annotation is already present, give up now. Note that
+ // we allow the existing annotation to be bigger than the one we're
+ // creating, because in that case, setting the new annotation won't
+ // do anything useful.
+ for (Annotation annotation : doc.getAnnotations(range, name)) {
+ if (annotation.getValue().equals(value) &&
+ annotation.getRange().getStart() <= range.getStart() &&
+ range.getEnd() <= annotation.getRange().getEnd())
+ return;
+ }
+
+ LOG.fine("Annotating with " + name + "=" + value);
+ doc.setAnnotation(range, name, value);
+ }
+}
View
49 src/buglinky/BugLinkAnnotator.java
@@ -0,0 +1,49 @@
+// buglinky - A robot for adding bugtracker links to a wave
+// Copyright 2009 Eric Kidd
+//
+// 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 buglinky;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.wave.api.Range;
+import com.google.wave.api.TextView;
+
+/** Add bug links to a blip. */
+class BugLinkAnnotator extends Annotator {
+ /** The URL to a bug, minus the actual bug number. */
+ private String bugUrl;
+
+ /** Create a BugLinkAnnotator for the specified URL. */
+ public BugLinkAnnotator(String bugUrl) {
+ this.bugUrl = bugUrl;
+ }
+
+ /** Return a regular expression matching the text we want to process. */
+ protected Pattern getPattern() {
+ // Regex used to find bug numbers in the text. Note that we require at
+ // least one non-numeric character after the bug number (and not a
+ // newline). This ensures that when the user is adding text at the
+ // end of a paragraph, we won't add any links until the user is safely
+ // outside the area that we need to modify. Users making modifications
+ // inside of paragraphs will have to live with minor glitches.
+ return Pattern.compile("(?:bug|issue) #(\\d+)(?!\\d|\\r|\\n)");
+ }
+
+ /** Process a regular expression match. */
+ protected void processMatch(TextView doc, Range range, Matcher match) {
+ maybeAnnotate(doc, range, "link/manual", bugUrl.concat(match.group(1)));
+ }
+}
View
67 src/buglinky/BugLinkyServlet.java
@@ -16,10 +16,12 @@
package buglinky;
import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import com.google.wave.api.*;
+import com.google.wave.api.AbstractRobotServlet;
+import com.google.wave.api.Blip;
+import com.google.wave.api.Event;
+import com.google.wave.api.RobotMessageBundle;
+import com.google.wave.api.TextView;
/** Called via JSON-RPC whenever an event occurs on one of our waves. */
@SuppressWarnings("serial")
@@ -28,24 +30,13 @@
Logger.getLogger(BugLinkyServlet.class.getName());
private static final String ME = "buglinky@appspot.com";
- private static final String LINK = "link/manual";
-
private static final String INSTRUCTIONS =
"buglinky will attempt to link \"bug #NNN\" to a bug tracker.";
+
+ /** The URL to a specific bug in our bug tracker, minus the number. */
private static final String BUG_URL =
"http://code.google.com/p/google-wave-resources/issues/detail?id=";
-
- /**
- * Regex used to find bug numbers in the text. Note that we require at least
- * one non-numeric character after the bug number (and not a newline). This
- * ensures that when the user is adding text at the end of a paragraph, we
- * won't add any links until the user is safely outside the area that we
- * need to modify. Users making modifications inside of paragraphs will have
- * to live with minor glitches.
- */
- private static final Pattern REGEX =
- Pattern.compile("(?:bug|issue) #(\\d+)(?!\\d|\\r|\\n)");
-
+
/** Called when we receive events from the Wave server. */
@Override
public void processEvents(RobotMessageBundle bundle) {
@@ -65,6 +56,7 @@ private void addInstructionsToWave(RobotMessageBundle bundle) {
/** Dispatch events to the appropriate handler method. */
private void dispatchEvents(RobotMessageBundle bundle) {
+ Annotator annotator = new BugLinkAnnotator(BUG_URL);
for (Event e : bundle.getEvents()) {
if (!e.getModifiedBy().equals(ME)) {
switch (e.getType()) {
@@ -74,7 +66,7 @@ private void dispatchEvents(RobotMessageBundle bundle) {
// BLIP_VERSION_CHANGED, we'll apply our links in real time.
case BLIP_SUBMITTED:
case BLIP_VERSION_CHANGED:
- addLinksToBlip(e.getBlip());
+ annotator.processBlip(e.getBlip());
break;
default:
@@ -83,43 +75,4 @@ private void dispatchEvents(RobotMessageBundle bundle) {
}
}
}
-
- /** Add links to the specified blip. */
- private void addLinksToBlip(Blip blip) {
- LOG.fine("Adding links to blip " + blip.getBlipId());
- // Adapted from http://senikk.com/min-f%C3%B8rste-google-wave-robot,
- // a robot which links to @names on Twitter.
- TextView doc = blip.getDocument();
- Matcher matcher = REGEX.matcher(doc.getText());
- while (matcher.find()) {
- LOG.fine("Found a link: " + matcher.group());
- Range range = new Range(matcher.start(), matcher.end());
- String url = BUG_URL.concat(matcher.group(1));
- maybeAnnotate(doc, range, LINK, url);
- }
- }
-
- /**
- * Add an annotation if it isn't already present.
- *
- * The Wave Robot API does not currently filter out duplicate annotation
- * requests, which causes extra network traffic and more possibilities for
- * nasty bot loops. So we do this screening on our end.
- */
- private void maybeAnnotate(TextView doc, Range range, String name,
- String value) {
- // If this annotation is already present, give up now. Note that
- // we allow the existing annotation to be bigger than the one we're
- // creating, because in that case, setting the new annotation won't
- // do anything useful.
- for (Annotation annotation : doc.getAnnotations(range, name)) {
- if (annotation.getValue().equals(value) &&
- annotation.getRange().getStart() <= range.getStart() &&
- range.getEnd() <= annotation.getRange().getEnd())
- return;
- }
-
- LOG.fine("Annotating with " + value);
- doc.setAnnotation(range, name, value);
- }
}

0 comments on commit 30c13d6

Please sign in to comment.
Something went wrong with that request. Please try again.