/**
* Copyright 2009 Google Inc.
*
* 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 org.waveprotocol.wave.client.clipboard;
import com.google.gwt.http.client.URL;
import org.waveprotocol.wave.model.document.RangedAnnotation;
import org.waveprotocol.wave.model.document.util.RangedAnnotationImpl;
import java.util.ArrayList;
import java.util.List;
/**
* Serialization/deserialization for annotations.
*
* Annotation format (There is no guarantee this will stay):
*
* Each annotation contains start, end, url escaped key, url escaped value
* separated by "," The annotations are separated by ":"
*
* Example : "23,39,fontWeight,bold:59,64,fontStyle,italics"
*
* TODO(user): Move this to a common package, as this seems generally useful.
* But first, remove the dependency on gwt.
*
*/
public class AnnotationSerializer {
/**
* Deserializes the string into a list of ranged annotations.
*
* @param serialized
*/
public static List<RangedAnnotation<String>> deserialize(String serialized) {
String[] split = serialized.split(OUTER_SEPARATOR);
List<RangedAnnotation<String>> annotations = new ArrayList<RangedAnnotation<String>>();
for (String s : split) {
if (!s.isEmpty()) {
String innerSplit[] = s.split(INNER_SEPARATOR);
if (innerSplit.length == 4) {
annotations.add(new RangedAnnotationImpl<String>(unescape(innerSplit[2]),
unescape(innerSplit[3]), Integer.parseInt(innerSplit[0]), Integer
.parseInt(innerSplit[1])));
}
}
}
return annotations;
}
/** Utility class */
private AnnotationSerializer() {}
/**
* Serializes a list of rangedAnnotations
*
* @param rangedAnnotations
*/
public static String serializeAnnotation(Iterable<RangedAnnotation<String>> rangedAnnotations) {
Builder entries = new Builder();
for (RangedAnnotation<String> ann : rangedAnnotations) {
if (ann.value() != null) {
entries.pushEntry(ann.start(), ann.end(), ann.key(), ann.value());
}
}
return entries.toString();
}
// TODO(user): Consider some other encoding format. This is ok, but is gwt
// dependent.
private static final String INNER_SEPARATOR = ",";
private static final String OUTER_SEPARATOR = ":";
private static String escape(String s) {
return URL.encodeComponent(s);
}
private static String unescape(String s) {
return URL.decodeComponent(s);
}
private static class Builder {
StringBuilder builder = new StringBuilder();
public void pushEntry(int start, int end, String key, String value) {
builder
.append(start).append(INNER_SEPARATOR)
.append(end).append(INNER_SEPARATOR)
.append(escape(key)).append(INNER_SEPARATOR)
.append(escape(value)).append(OUTER_SEPARATOR);
}
@Override
public String toString() {
return builder.toString();
}
}
}