http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/Annotation.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/Annotation.java b/src/com/google/wave/api/Annotation.java deleted file mode 100644 index 5b137b2..0000000 --- a/src/com/google/wave/api/Annotation.java +++ /dev/null @@ -1,145 +0,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. - */ - -package com.google.wave.api; - -import java.io.Serializable; - - -/* - * Annotation is an immutable key-value pair of metadata over a range of - * content. Annotation can be used to store data or to be interpreted by a - * client when displaying the data. - * - * Example uses of annotation include styling text, supplying spelling - * corrections, and links to refer that area of text to another document or - * web site. - */ -public class Annotation implements Serializable { - - /** Some constants for style related annotation keys. */ - public static final String BACKGROUND_COLOR = "style/backgroundColor"; - public static final String COLOR = "style/color"; - public static final String FONT_FAMILY = "style/fontFamily"; - public static final String FONT_SIZE = "style/fontSize"; - public static final String FONT_STYLE = "style/fontStyle"; - public static final String FONT_WEIGHT = "style/fontWeight"; - public static final String TEXT_DECORATION = "style/textDecoration"; - public static final String VERTICAL_ALIGN = "style/verticalAlign"; - public static final String LINK = "link/manual"; - public static final String WAVE_LINK = "link/wave"; - - /** The annotation name. */ - private final String name; - - /** The annotation value. */ - private final String value; - - /** The range of this annotation. */ - private Range range; - - /** - * Constructor. - * - * @param name the name of this annotation. - * @param value the value of this annotation. - * @param start the starting index of this annotation. - * @param end the end index of this annotation. - */ - public Annotation(String name, String value, int start, int end) { - this.name = name; - this.value = value; - this.range = new Range(start, end); - } - - /** - * Constructor. - * - * @param name the name of this annotation. - * @param value the value of this annotation. - * @param range the range of this annotation. - */ - public Annotation(String name, String value, Range range) { - this.name = name; - this.value = value; - this.range = new Range(range.getStart(), range.getEnd()); - } - - /** - * Returns the name of this annotation. - * - * @return the annotation's name. - */ - public String getName() { - return name; - } - - /** - * Returns the value of this annotation. - * - * @return the annotation's value. - */ - public String getValue() { - return value; - } - - /** - * Returns the range of this annotation. - * - * @return the annotation range. - */ - public Range getRange() { - return range; - } - - /** - * Shifts this annotation by {@code shiftAmount} if it is on a range that - * is after or covers the given position. - * - * @param position the anchor position. - * @param shiftAmount the amount to shift the annotation range. - */ - public void shift(int position, int shiftAmount) { - int start = range.getStart(); - if (start >= position) { - start += shiftAmount; - } - - int end = range.getEnd(); - if (end >= position) { - end += shiftAmount; - } - range = new Range(start, end); - } - - @Override - public String toString() { - StringBuilder res = new StringBuilder("Annotation("); - if (name != null) { - res.append(name); - res.append(','); - } - if (value != null) { - res.append(value); - res.append(','); - } - res.append(range.toString()); - return res.toString(); - } -}
http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/Annotations.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/Annotations.java b/src/com/google/wave/api/Annotations.java deleted file mode 100644 index dbecd3e..0000000 --- a/src/com/google/wave/api/Annotations.java +++ /dev/null @@ -1,265 +0,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. - */ - -package com.google.wave.api; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -/** - * A class that models a map of annotations, keyed by the annotation name. - * - * Each key maps into a list of {@link Annotation} instances, since one - * annotation name can exist in different parts (denoted by different ranges) of - * a blip, each with its own value. - * - * This class is iterable, but the iterator does not support element removal - * yet. - */ -public class Annotations implements Iterable<Annotation>, Serializable { - - /** A map of annotation name to a list of annotations instances. */ - private final Map<String, List<Annotation>> store = new HashMap<String, List<Annotation>>(); - - /** The total number of annotations. */ - private int size; - - /** - * Adds a new annotation. - * - * @param name the name of the annotation. - * @param value the value of the annotation. - * @param start the starting index of the annotation. - * @param end the end index of the annotation. - */ - void add(String name, String value, int start, int end) { - if (!store.containsKey(name)) { - store.put(name, Arrays.asList(new Annotation(name, value, start, end))); - size++; - return; - } - - int existingSize = store.get(name).size(); - List<Annotation> newList = new ArrayList<Annotation>(); - for (Annotation existing : store.get(name)) { - if (start > existing.getRange().getEnd() || end < existing.getRange().getStart()) { - // Add non-overlapping annotation to the new list as is. - newList.add(existing); - } else if (existing.getValue().equals(value)) { - // Merge the annotation. - start = Math.min(existing.getRange().getStart(), start); - end = Math.max(existing.getRange().getEnd(), end); - } else { - // Chop the bits off the existing annotation. - if (existing.getRange().getStart() < start) { - newList.add(new Annotation(existing.getName(), existing.getValue(), - existing.getRange().getStart(), start)); - } - if (existing.getRange().getEnd() > end) { - newList.add(new Annotation(existing.getName(), existing.getValue(), - end, existing.getRange().getEnd())); - } - } - } - newList.add(new Annotation(name, value, start, end)); - store.put(name, newList); - size += newList.size() - existingSize; - } - - /** - * Deletes an annotation. This is a no-op if the blip doesn't have this - * annotation. - * - * @param name the name of the annotation to be deleted. - * @param start the starting index of the annotation to be deleted. - * @param end the end index of the annotation to be deleted. - */ - void delete(String name, int start, int end) { - if (!store.containsKey(name)) { - return; - } - - int existingSize = store.get(name).size(); - List<Annotation> newList = new ArrayList<Annotation>(); - for (Annotation existing : store.get(name)) { - if (start > existing.getRange().getEnd() || end < existing.getRange().getStart()) { - newList.add(existing); - } else if (start < existing.getRange().getStart() && end > existing.getRange().getEnd()) { - continue; - } else { - // Chop the bits off the existing annotation. - if (existing.getRange().getStart() < start) { - newList.add(new Annotation(existing.getName(), existing.getValue(), - existing.getRange().getStart(), start)); - } - if (existing.getRange().getEnd() > end) { - newList.add(new Annotation(existing.getName(), existing.getValue(), - end, existing.getRange().getEnd())); - } - } - } - - if (!newList.isEmpty()) { - store.put(name, newList); - } else { - store.remove(name); - } - size -= existingSize - newList.size(); - } - - /** - * Shifts all annotations that have a range that is after or covers the given - * position. - * - * @param position the anchor position. - * @param shiftAmount the amount to shift the annotation range. - */ - void shift(int position, int shiftAmount) { - for (List<Annotation> annotations : store.values()) { - for (Annotation annotation : annotations) { - annotation.shift(position, shiftAmount); - } - } - - // Merge fragmented annotations that should be contiguous, for example: - // Annotation("foo", "bar", 1, 2) and Annotation("foo", "bar", 2, 3). - for (Entry<String, List<Annotation>> entry : store.entrySet()) { - List<Annotation> existingList = entry.getValue(); - List<Annotation> newList = new ArrayList<Annotation>(existingList.size()); - - for (int i = 0; i < existingList.size(); ++i) { - Annotation annotation = existingList.get(i); - String name = annotation.getName(); - String value = annotation.getValue(); - int start = annotation.getRange().getStart(); - int end = annotation.getRange().getEnd(); - - // Find the last end index. - for (int j = i + 1; j < existingList.size(); ++j) { - if (end < existingList.get(j).getRange().getStart()) { - break; - } - - if (end == existingList.get(j).getRange().getStart() && - value.equals(existingList.get(j).getValue())) { - end = existingList.get(j).getRange().getEnd(); - existingList.remove(j--); - } - } - newList.add(new Annotation(name, value, start, end)); - } - entry.setValue(newList); - } - } - - /** - * Returns a list of annotation instances that has the given name. - * - * @param name the annotation name. - * @return a list of {@link Annotation} instances in the owning blip that has - * the given name. - */ - public List<Annotation> get(String name) { - return store.get(name); - } - - /** - * Returns the number of distinct annotation names that the owning blip has. - * - * @return the number of distinct annotation names. - */ - public int size() { - return store.size(); - } - - /** - * Returns a set of annotation names that the owning blip has. - * - * @return a set of annotation names. - */ - public Set<String> namesSet() { - return new HashSet<String>(store.keySet()); - } - - /** - * Returns this {@link Annotations} object as a {@link List} of annotations. - * - * @return an unmodifiable list of annotations. - */ - public List<Annotation> asList() { - List<Annotation> annotations = new ArrayList<Annotation>(size); - for (Annotation annotation : this) { - annotations.add(annotation); - } - return Collections.unmodifiableList(annotations); - } - - @Override - public Iterator<Annotation> iterator() { - return new AnnotationIterator(store); - } - - /** - * An iterator over all annotations in this annotation set. Currently, it - * doesn't support {@code remove()} operation. - */ - private static class AnnotationIterator implements Iterator<Annotation> { - private Iterator<Annotation> listIterator; - private final Iterator<List<Annotation>> mapIterator; - - /** - * Constructor. - * - * @param store a map of annotation name to a list of annotations instances. - */ - private AnnotationIterator(Map<String, List<Annotation>> store) { - mapIterator = store.values().iterator(); - if (!store.isEmpty()) { - listIterator = mapIterator.next().iterator(); - } - } - - @Override - public boolean hasNext() { - return mapIterator.hasNext() || (listIterator != null && listIterator.hasNext()); - } - - @Override - public Annotation next() { - if (!listIterator.hasNext() && mapIterator.hasNext()) { - listIterator = mapIterator.next().iterator(); - } - return listIterator.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/ApiIdSerializer.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/ApiIdSerializer.java b/src/com/google/wave/api/ApiIdSerializer.java deleted file mode 100644 index b950d69..0000000 --- a/src/com/google/wave/api/ApiIdSerializer.java +++ /dev/null @@ -1,38 +0,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. - */ - -package com.google.wave.api; - -import org.waveprotocol.wave.model.id.DualIdSerialiser; -import org.waveprotocol.wave.model.id.IdSerialiser; - -/** - * Serializer for ids transmitted as part of the API. - * - * @author [email protected] (Alex North) - */ -public final class ApiIdSerializer { - - public static IdSerialiser instance() { - return DualIdSerialiser.MODERN; - } - - private ApiIdSerializer() { - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/Attachment.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/Attachment.java b/src/com/google/wave/api/Attachment.java deleted file mode 100644 index 4fb9127..0000000 --- a/src/com/google/wave/api/Attachment.java +++ /dev/null @@ -1,198 +0,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. - */ - -package com.google.wave.api; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Map; -import java.util.logging.Logger; - -/** - * Represents a wave attachment within a Wave. - */ -public class Attachment extends Element { - public static final String ATTACHMENT_ID = "attachmentId"; - public static final String CAPTION = "caption"; - public static final String MIME_TYPE = "mimeType"; - public static final String DATA = "data"; - public static final String ATTACHMENT_URL = "attachmentUrl"; - - private static final Logger LOG = Logger.getLogger(Attachment.class.getName()); - - /** Attachment data. */ - private byte[] data; - - /** - * Constructs an attachment with a given set of properties and data. - * - * @param properties the properties of the attachment. - * @param data the data of the attachment - */ - public Attachment(Map<String, String> properties, byte[] data) { - super(ElementType.ATTACHMENT, properties); - this.data = data; - } - - /** - * Constructs an attachment with data in bytes and caption. - * - * @param caption the caption of the attachment. - * @param data the attachment data as bytes. - */ - public Attachment(String caption, byte[] data) { - super(ElementType.ATTACHMENT); - setCaption(caption); - this.data = data; - } - - @Override - public void setProperty(String name, String value) { - if (name.equals(ATTACHMENT_ID) || name.equals(MIME_TYPE) || - name.equals(ATTACHMENT_URL) || name.equals(DATA)) { - throw new IllegalArgumentException(name + " can not be changed."); - } - super.setProperty(name, value); - } - - /** - * Returns the attachment id for the attachment. - * - * @return the attachment id for the attachment. - */ - public String getAttachmentId() { - return getProperty(ATTACHMENT_ID); - } - - /** - * Returns the url for the attachment. - * - * @return the url for the attachment. - */ - public String getAttachmentUrl() { - return getProperty(ATTACHMENT_URL); - } - - /** - * Sets the caption for the attachment. - * - * @param caption the caption to display for the attachment. - */ - public void setCaption(String caption) { - setProperty(CAPTION, caption); - } - - /** - * Returns the caption for the attachment. - * - * @return the caption for the attachment. - */ - public String getCaption() { - return getProperty(CAPTION); - } - - /** - * Returns the data for the attachment. Data will be fetched via HTTP if - * it's not available. - * - * @return the data for the attachment. - */ - public byte[] getData() { - if (data == null) { - try { - fetch(); - } catch (IOException e) { - LOG.info("Error fetching attachment data: " + e); - } - } - return data; - } - - public boolean hasData() { - return data != null; - } - - /** - * Returns the MIME type for the attachment. - * - * @return the MIME type for the attachment. - */ - public String getMimeType() { - return getProperty(MIME_TYPE); - } - - /** - * Creates an instance of {@link Restriction} that can be used to search for - * attachment with the given caption. - * - * @param caption the caption to filter. - * @return an instance of {@link Restriction}. - */ - public static Restriction restrictByCaption(String caption) { - return Restriction.of(CAPTION, caption); - } - - /** - * Creates an instance of {@link Restriction} that can be used to search for - * attachment with the given MIME type. - * - * @param mimeType the MIME type to filter. - * @return an instance of {@link Restriction}. - */ - public static Restriction restrictByMimeType(String mimeType) { - return Restriction.of(MIME_TYPE, mimeType); - } - - /** - * Creates an instance of {@link Restriction} that can be used to search for - * attachment with the given attachment id. - * - * @param attachmentId the id of the attachment. - * @return an instance of {@link Restriction}. - */ - public static Restriction restrictByAttachmentId(String attachmentId) { - return Restriction.of(ATTACHMENT_ID, attachmentId); - } - - private void fetch() throws IOException { - if (getAttachmentUrl() != null && (!getAttachmentUrl().isEmpty())) { - InputStream input = null; - ByteArrayOutputStream output = null; - try { - URL url = new URL(getAttachmentUrl()); - input = url.openStream(); - output = new ByteArrayOutputStream(); - int i; - while ((i = input.read()) != -1) { - output.write(i); - } - this.data = output.toByteArray(); - } finally { - if (input != null) { - input.close(); - } - if (output != null) { - output.close(); - } - } - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/Blip.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/Blip.java b/src/com/google/wave/api/Blip.java deleted file mode 100644 index 111fb20..0000000 --- a/src/com/google/wave/api/Blip.java +++ /dev/null @@ -1,804 +0,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. - */ - -package com.google.wave.api; - - -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A class that models a single blip instance. - * - * Blips are essentially the documents that make up a conversation, that contain - * annotations, content and elements. - */ -public class Blip implements Serializable { - - /** The property key for blip id in an inline blip element. */ - private static final String INLINE_BLIP_ELEMENT_ID_KEY = "id"; - - /** The {@link Pattern} object used to search markup content. */ - private static final Pattern MARKUP_PATTERN = Pattern.compile("\\<.*?\\>"); - - /** The id of this blip. */ - private final String blipId; - - /** The id of the parent blip, {@code null} for blips in the root thread. */ - private final String parentBlipId; - - /** The containing thread. */ - private final BlipThread thread; - - /** The ids of the children of this blip. */ - private final List<String> childBlipIds; - - /** The inline reply threads, sorted by location/offset. */ - private SortedMap<Integer, BlipThread> inlineReplyThreads; - - /** The reply threads. */ - private final List<BlipThread> replyThreads; - - /** The participant ids of the contributors of this blip. */ - private final List<String> contributors; - - /** The participant id of the creator of this blip. */ - private final String creator; - - /** The last modified time of this blip. */ - private final long lastModifiedTime; - - /** The version of this blip. */ - private final long version; - - /** The list of annotations for the content. */ - private final Annotations annotations; - - /** The wavelet that owns this blip. */ - @NonJsonSerializable private final Wavelet wavelet; - - /** The operation queue to queue operation to the robot proxy. */ - @NonJsonSerializable private final OperationQueue operationQueue; - - /** The blip content. */ - private String content; - - /** The element contents of this blip. */ - private SortedMap<Integer, Element> elements; - - /** - * Constructor. - * - * @param blipId the id of this blip. - * @param initialContent the initial content of the blip. - * @param parentBlipId the id of the parent. - * @param threadId the id of the containing thread. - * @param wavelet the wavelet that owns this blip. - */ - Blip(String blipId, String initialContent, String parentBlipId, String threadId, - Wavelet wavelet) { - this(blipId, new ArrayList<String>(), initialContent, new ArrayList<String>(), null, -1, -1, - parentBlipId, threadId, new ArrayList<Annotation>(), new TreeMap<Integer, Element>(), - new ArrayList<String>(), wavelet); - - // Make sure that initial content is valid, and starts with newline. - if (this.content == null || this.content.isEmpty()) { - this.content = "\n"; - } else if (!this.content.startsWith("\n")) { - this.content = "\n" + this.content; - } - } - - /** - * Constructor. - * - * @param blipId the id of this blip. - * @param childBlipIds he ids of the children of this blip. - * @param content the content of this blip. - * @param contributors the participant ids of the contributors of this blip. - * @param creator the participant id of the creator of this blip. - * @param lastModifiedTime the last modified time of this blip. - * @param version the version of this blip. - * @param parentBlipId the id of the parent of this blip. - * @param threadId the id of the parent thread of this blip. - * @param annotations the list of annotations for this blip's content. - * @param elements the element contents of this blip. - * @param replyThreadIds the ids of this blip's reply threads. - * @param wavelet the wavelet that owns this blip. - */ - Blip(String blipId, List<String> childBlipIds, String content, List<String> contributors, - String creator, long lastModifiedTime, long version, String parentBlipId, String threadId, - List<Annotation> annotations, Map<Integer, Element> elements, List<String> replyThreadIds, - Wavelet wavelet) { - this.blipId = blipId; - this.content = content; - this.childBlipIds = new ArrayList<String>(childBlipIds); - this.contributors = new ArrayList<String>(contributors); - this.creator = creator; - this.lastModifiedTime = lastModifiedTime; - this.version = version; - this.parentBlipId = parentBlipId; - this.thread = wavelet.getThread(threadId); - - this.annotations = new Annotations(); - for (Annotation annotation : annotations) { - this.annotations.add(annotation.getName(), annotation.getValue(), - annotation.getRange().getStart(), annotation.getRange().getEnd()); - } - - this.elements = new TreeMap<Integer, Element>(elements); - this.wavelet = wavelet; - this.operationQueue = wavelet.getOperationQueue(); - - // Populate reply threads. - this.inlineReplyThreads = new TreeMap<Integer, BlipThread>(); - this.replyThreads = new ArrayList<BlipThread>(); - for (String replyThreadId : replyThreadIds) { - BlipThread thread = wavelet.getThread(replyThreadId); - if (thread.getLocation() != -1) { - inlineReplyThreads.put(thread.getLocation(), thread); - } else { - replyThreads.add(thread); - } - } - } - - /** - * Shallow copy constructor. - * - * @param other the blip to copy. - * @param operationQueue the operation queue for this new blip instance. - */ - private Blip(Blip other, OperationQueue operationQueue) { - this.blipId = other.blipId; - this.childBlipIds = other.childBlipIds; - this.inlineReplyThreads = other.inlineReplyThreads; - this.replyThreads = other.replyThreads; - this.content = other.content; - this.contributors = other.contributors; - this.creator = other.creator; - this.lastModifiedTime = other.lastModifiedTime; - this.version = other.version; - this.parentBlipId = other.parentBlipId; - this.thread = other.thread; - this.annotations = other.annotations; - this.elements = other.elements; - this.wavelet = other.wavelet; - this.operationQueue = operationQueue; - } - - /** - * Returns the id of this blip. - * - * @return the blip id. - */ - public String getBlipId() { - return blipId; - } - - /** - * Returns the id of the wave that owns this blip. - * - * @return the wave id. - */ - public WaveId getWaveId() { - return wavelet.getWaveId(); - } - - /** - * Returns the id of the wavelet that owns this blip. - * - * @return the wavelet id. - */ - public WaveletId getWaveletId() { - return wavelet.getWaveletId(); - } - - /** - * Returns the list of ids of this blip children. - * - * @return the children's ids. - */ - public List<String> getChildBlipIds() { - return childBlipIds; - } - - /** - * Returns the list of child blips. - * - * @return the children of this blip. - */ - public List<Blip> getChildBlips() { - List<Blip> result = new ArrayList<Blip>(childBlipIds.size()); - for (String childId : childBlipIds) { - Blip childBlip = wavelet.getBlips().get(childId); - if (childBlip != null) { - result.add(childBlip); - } - } - return result; - } - - /** - * @return the inline reply threads of this blip, sorted by the offset. - */ - public Collection<BlipThread> getInlineReplyThreads() { - return inlineReplyThreads.values(); - } - - /** - * @return the reply threads of this blip. - */ - public Collection<BlipThread> getReplyThreads() { - return replyThreads; - } - - /** - * Returns the participant ids of the contributors of this blip. - * - * @return the blip's contributors. - */ - public List<String> getContributors() { - return contributors; - } - - /** - * Returns the participant id of the creator of this blip. - * - * @return the blip's creator. - */ - public String getCreator() { - return creator; - } - - /** - * Returns the last modified time of this blip. - * - * @return the blip's last modified time. - */ - public long getLastModifiedTime() { - return lastModifiedTime; - } - - /** - * Returns the version of this blip. - * - * @return the blip's version. - */ - public long getVersion() { - return version; - } - - /** - * Returns the id of this blip's parent, or {@code null} if this blip is in - * the root thread. - * - * @return the blip's parent's id. - */ - public String getParentBlipId() { - return parentBlipId; - } - - /** - * Returns the parent blip. - * - * @return the parent of this blip. - */ - public Blip getParentBlip() { - if (parentBlipId == null) { - return null; - } - return wavelet.getBlips().get(parentBlipId); - } - - /** - * @return the containing thread. - */ - public BlipThread getThread() { - return thread; - } - - /** - * Checks whether this is a root blip or not. - * - * @return {@code true} if this is a root blip, denoted by {@code null} parent - * id. - */ - public boolean isRoot() { - return blipId.equals(wavelet.getRootBlipId()); - } - - /** - * Returns the annotations for this blip's content. - * - * @return the blip's annotations. - */ - public Annotations getAnnotations() { - return annotations; - } - - /** - * Returns the elements content of this blip. - * - * @return the blip's elements. - */ - public SortedMap<Integer, Element> getElements() { - return elements; - } - - /** - * Returns the text content of this blip. - * - * @return blip's content. - */ - public String getContent() { - return content; - } - - /** - * Sets the content of this blip. - * - * @param content the blip's content. - */ - void setContent(String content) { - if (!content.startsWith("\n")) { - content = "\n" + content; - } - this.content = content; - } - - /** - * Returns the length/size of the blip, denoted by the length of this blip's - * text content. - * - * @return the size of the blip. - */ - public int length() { - return content.length(); - } - - /** - * Returns the wavelet that owns this Blip. - * - * @return the wavelet. - */ - public Wavelet getWavelet() { - return wavelet; - } - - /** - * Returns the operation queue for sending outgoing operations to the robot - * proxy. - * - * @return the operation queue. - */ - protected OperationQueue getOperationQueue() { - return operationQueue; - } - - /** - * Returns a reference to the entire content of the blip. - * - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs all() { - return BlipContentRefs.all(this); - } - - /** - * Returns all references to this blip's content that match {@code target}. - * - * @param target the text to search for. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs all(String target) { - return BlipContentRefs.all(this, target, -1); - } - - /** - * Returns all references to this blip's content that match {@code target}. - * This blip references object will have at most {@code maxResult} hits. - * - * @param target the text to search for. - * @param maxResult the maximum number of hits. Specify -1 for no limit. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs all(String target, int maxResult) { - return BlipContentRefs.all(this, target, maxResult); - } - - /** - * Returns all references to this blip's content that match {@code target} and - * {@code restrictions}. - * - * @param target the element type to search for. - * @param restrictions the element properties that need to be matched. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs all(ElementType target, Restriction... restrictions) { - return BlipContentRefs.all(this, target, -1, restrictions); - } - - /** - * Returns all references to this blip's content that match {@code target} and - * {@code restrictions}. This blip references object will have at most - * {@code maxResult} hits. - * - * @param target the element type to search for. - * @param maxResult the maximum number of hits. Specify -1 for no limit. - * @param restrictions the element properties that need to be matched. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs all(ElementType target, int maxResult, Restriction... restrictions) { - return BlipContentRefs.all(this, target, maxResult, restrictions); - } - - /** - * Returns the first reference to this blip's content that matches - * {@code target}. - * - * @param target the text to search for. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs first(String target) { - return all(target, 1); - } - - /** - * Returns the first reference to this blip's content that matches - * {@code target} and {@code restrictions}. - * - * @param target the type of element to search for. - * @param restrictions the list of restrictions to filter the search. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs first(ElementType target, Restriction... restrictions) { - return all(target, 1, restrictions); - } - - /** - * Returns the reference to this blip's content at the specified index. - * - * @param index the index to reference. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs at(int index) { - return BlipContentRefs.range(this, index, index + 1); - } - - /** - * Returns the reference to this blip's content at the specified range. - * - * @param start the start index of the range to reference. - * @param end the end index of the range to reference. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs range(int start, int end) { - return BlipContentRefs.range(this, start, end); - } - - /** - * Appends the given argument (element, text, or markup) to the blip. - * - * @param argument the element, text, or markup to be appended. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs append(BlipContent argument) { - return BlipContentRefs.all(this).insertAfter(argument); - } - - /** - * Appends the given string to the blip. - * - * @param argument the string to be appended. - * @return an instance of {@link BlipContentRefs}. - */ - public BlipContentRefs append(String argument) { - return BlipContentRefs.all(this).insertAfter(argument); - } - - /** - * Creates a reply to this blip. - * - * @return an instance of {@link Blip} that represents a reply to the blip. - */ - public Blip reply() { - return operationQueue.createChildOfBlip(this); - } - - /** - * Continues the containing thread of this blip.. - * - * @return an instance of {@link Blip} that represents a the new continuation - * reply blip. - */ - public Blip continueThread() { - return operationQueue.continueThreadOfBlip(this); - } - - /** - * Inserts an inline blip at the given position. - * - * @param position the index to insert the inline blip at. This has to be - * greater than 0. - * @return an instance of {@link Blip} that represents the new inline blip. - */ - public Blip insertInlineBlip(int position) { - if (position <= 0 || position > content.length()) { - throw new IllegalArgumentException("Illegal inline blip position: " + position + - ". Position has to be greater than 0 and less than or equal to length."); - } - - // Shift the elements. - shift(position, 1); - content = content.substring(0, position) + " " + content.substring(position); - - // Generate the operation. - Blip inlineBlip = operationQueue.insertInlineBlipToDocument(this, position); - - // Insert the inline blip element. - Element element = new Element(ElementType.INLINE_BLIP); - element.setProperty(INLINE_BLIP_ELEMENT_ID_KEY, inlineBlip.getBlipId()); - elements.put(position, element); - return inlineBlip; - } - - /** - * Appends markup ({@code HTML}) content. - * - * @param markup the markup content to add. - */ - public void appendMarkup(String markup) { - operationQueue.appendMarkupToDocument(this, markup); - this.content += convertToPlainText(markup); - } - - /** - * Returns a view of this blip that will proxy for the specified id. - * - * A shallow copy of the current blip is returned with the {@code proxyingFor} - * field set. Any modifications made to this copy will be done using the - * {@code proxyForId}, i.e. the {@code robot+<proxyForId>@appspot.com} address - * will be used. - * - * @param proxyForId the id to proxy. Please note that this parameter should - * be properly encoded to ensure that the resulting participant id is - * valid (see {@link Util#checkIsValidProxyForId(String)} for more - * details). - * @return a shallow copy of this blip with the proxying information set. - */ - public Blip proxyFor(String proxyForId) { - Util.checkIsValidProxyForId(proxyForId); - OperationQueue proxiedOperationQueue = operationQueue.proxyFor(proxyForId); - return new Blip(this, proxiedOperationQueue); - } - - /** - * Returns the offset of this blip if it is inline, or -1 if it's not. If the - * parent is not in the offset, this method will always return -1 since it - * can't determine the inline blip status. - * - * @return the offset of this blip if it is inline, or -1 if it's not inline - * or if the parent is not in the context. - * @deprecated please use {@code getThread().getLocation()} to get the offset - * of the inline reply thread that contains this blip. - */ - @Deprecated - public int getInlineBlipOffset() { - Blip parent = getParentBlip(); - if (parent == null) { - return -1; - } - - for (Entry<Integer, Element> entry : parent.getElements().entrySet()) { - Element element = entry.getValue(); - if (element.getType() == ElementType.INLINE_BLIP && - blipId.equals(element.getProperty(INLINE_BLIP_ELEMENT_ID_KEY))) { - return entry.getKey(); - } - } - return -1; - } - - /** - * Moves all elements and annotations after the given position by - * {@code shiftAmount}. - * - * @param position the anchor position. - * @param shiftAmount the amount to shift the annotations range and elements - * position. - */ - protected void shift(int position, int shiftAmount) { - SortedMap<Integer, Element> newElements = - new TreeMap<Integer, Element>(elements.headMap(position)); - for (Entry<Integer, Element> element : elements.tailMap(position).entrySet()) { - newElements.put(element.getKey() + shiftAmount, element.getValue()); - } - this.elements = newElements; - - SortedMap<Integer, BlipThread> newInlineReplyThreads = - new TreeMap<Integer, BlipThread>(inlineReplyThreads.headMap(position)); - for (Entry<Integer, BlipThread> entry : inlineReplyThreads.tailMap(position).entrySet()) { - BlipThread thread = entry.getValue(); - thread.setLocation(thread.getLocation() + shiftAmount); - newInlineReplyThreads.put(thread.getLocation(), thread); - } - this.inlineReplyThreads = newInlineReplyThreads; - - this.annotations.shift(position, shiftAmount); - } - - /** - * Deletes all annotations that span from {@code start} to {@code end}. - * - * @param start the start position. - * @param end the end position. - */ - protected void deleteAnnotations(int start, int end) { - for (String name : annotations.namesSet()) { - annotations.delete(name, start, end); - } - } - - /** - * Deletes the given blip id from the list of child blip ids. - * - * @param childBlipId the blip id to delete. - */ - protected void deleteChildBlipId(String childBlipId) { - this.childBlipIds.remove(childBlipId); - } - - /** - * Adds the given {@link BlipThread} as a reply or inline reply thread. - * - * @param thread the new thread to add. - */ - protected void addThread(BlipThread thread) { - if (thread.getLocation() == -1) { - this.replyThreads.add(thread); - } else { - this.inlineReplyThreads.put(thread.getLocation(), thread); - } - } - - /** - * Removes the given {@link BlipThread} from the reply or inline reply thread. - * - * @param thread the new thread to remove. - */ - protected void removeThread(BlipThread thread) { - if (thread.getLocation() == -1) { - this.replyThreads.remove(thread); - } else { - this.inlineReplyThreads.remove(thread.getLocation()); - } - } - - /** - * Converts the given {@code HTML} into robot compatible plaintext. - * - * @param html the {@code HTML} to convert. - * @return a plain text version of the given {@code HTML}. - */ - private static String convertToPlainText(String html) { - StringBuffer result = new StringBuffer(); - Matcher matcher = MARKUP_PATTERN.matcher(html); - while (matcher.find()) { - String replacement = ""; - String tag = matcher.group().substring(1, matcher.group().length() - 1).split(" ")[0]; - if ("p".equals(tag) || "br".equals(tag)) { - replacement = "\n"; - } - matcher.appendReplacement(result, replacement); - } - matcher.appendTail(result); - return result.toString(); - } - - /** - * Serializes this {@link Blip} into a {@link BlipData}. - * - * @return an instance of {@link BlipData} that represents this blip. - */ - public BlipData serialize() { - BlipData blipData = new BlipData(); - - // Add primitive properties. - blipData.setBlipId(blipId); - blipData.setWaveId(ApiIdSerializer.instance().serialiseWaveId(wavelet.getWaveId())); - blipData.setWaveletId(ApiIdSerializer.instance().serialiseWaveletId(wavelet.getWaveletId())); - blipData.setParentBlipId(parentBlipId); - blipData.setThreadId(thread.getId()); - blipData.setCreator(creator); - blipData.setLastModifiedTime(lastModifiedTime); - blipData.setVersion(version); - blipData.setContent(content); - - // Add list and map properties. - blipData.setChildBlipIds(childBlipIds); - blipData.setContributors(contributors); - blipData.setElements(elements); - - // Add annotations. - List<Annotation> annotations = new ArrayList<Annotation>(); - for (Annotation annotation : this.annotations) { - annotations.add(annotation); - } - blipData.setAnnotations(annotations); - - // Add reply threads ids. - List<String> replyThreadIds = new ArrayList<String>(inlineReplyThreads.size() + - replyThreads.size()); - for (BlipThread thread : inlineReplyThreads.values()) { - replyThreadIds.add(thread.getId()); - } - for (BlipThread thread : replyThreads) { - replyThreadIds.add(thread.getId()); - } - blipData.setReplyThreadIds(replyThreadIds); - - return blipData; - } - - /** - * Deserializes the given {@link BlipData} object into an instance of - * {@link Blip}. - * - * @param operationQueue the operation queue. - * @param wavelet the wavelet that owns this blip. - * @param blipData the blip data to be deserialized. - * @return an instance of {@link Wavelet}. - */ - public static Blip deserialize(OperationQueue operationQueue, Wavelet wavelet, - BlipData blipData) { - // Extract primitive properties. - String blipId = blipData.getBlipId(); - String parentBlipId = blipData.getParentBlipId(); - String threadId = blipData.getThreadId(); - String creator = blipData.getCreator(); - long lastModifiedTime = blipData.getLastModifiedTime(); - long version = blipData.getVersion(); - String content = blipData.getContent(); - - List<String> childBlipIds = blipData.getChildBlipIds(); - List<String> replyThreadIds = blipData.getReplyThreadIds(); - if (replyThreadIds == null) { - replyThreadIds = new ArrayList<String>(); - } - - List<String> contributors = blipData.getContributors(); - Map<Integer, Element> elements = blipData.getElements(); - - List<Annotation> annotations = blipData.getAnnotations(); - return new Blip(blipId, childBlipIds, content, contributors, creator, lastModifiedTime, - version, parentBlipId, threadId, annotations, elements, replyThreadIds, wavelet); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/BlipContent.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/BlipContent.java b/src/com/google/wave/api/BlipContent.java deleted file mode 100644 index 25ce244..0000000 --- a/src/com/google/wave/api/BlipContent.java +++ /dev/null @@ -1,65 +0,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. - */ - -package com.google.wave.api; - -import java.io.Serializable; - -/** - * An abstract class that models a blip content. - * - * @see Element - * @see Plaintext - */ -public abstract class BlipContent implements Serializable { - - /** - * Returns the textual representation of of this blip content, for example, - * if it's an element, it returns a space. - * - * @return the textual representation. - */ - public abstract String getText(); - - /** - * Returns this blip content as an element. - * - * @return an instance of {@link Element}, or {@code null} if it is not an - * {@link Element}. - */ - public Element asElement() { - if (!(this instanceof Element)) { - return null; - } - return Element.class.cast(this); - } - - /** - * Returns this blip content as a plain-text. - * - * @return an instance of {@link Plaintext}, or {@code null} if it is not a - * {@link Plaintext}. - */ - public Plaintext asPlaintext() { - if (!(this instanceof Plaintext)) { - return null; - } - return Plaintext.class.cast(this); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/com/google/wave/api/BlipContentRefs.java ---------------------------------------------------------------------- diff --git a/src/com/google/wave/api/BlipContentRefs.java b/src/com/google/wave/api/BlipContentRefs.java deleted file mode 100644 index 542c171..0000000 --- a/src/com/google/wave/api/BlipContentRefs.java +++ /dev/null @@ -1,717 +0,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. - */ - -package com.google.wave.api; - -import com.google.wave.api.Function.BlipContentFunction; -import com.google.wave.api.Function.MapFunction; -import com.google.wave.api.JsonRpcConstant.ParamsProperty; -import com.google.wave.api.OperationRequest.Parameter; -import com.google.wave.api.impl.DocumentModifyAction; -import com.google.wave.api.impl.DocumentModifyQuery; -import com.google.wave.api.impl.DocumentModifyAction.BundledAnnotation; -import com.google.wave.api.impl.DocumentModifyAction.ModifyHow; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * A class that represents a set of references to contents in a blip. - * - * A {@link BlipContentRefs} instance for example can represent the - * results of a search, an explicitly set range, a regular expression, or refer - * to the entire blip. - * - * {@link BlipContentRefs} are used to express operations on a blip in a - * consistent way that can be easily transfered to the server. - */ -public class BlipContentRefs implements Iterable<Range> { - - /** The blip that this blip references are pointing to. */ - private final Blip blip; - - /** The iterator to iterate over the blip content. */ - private final BlipIterator<?> iterator; - - /** The additional parameters that need to be supplied in the outgoing op. */ - private final List<Parameter> parameters; - - /** - * Constructs an instance representing the search for text {@code target}. - * - * @param blip the blip to find {@code target} in. - * @param target the target to search. - * @param maxResult the maximum number of results. - * @return an instance of blip references. - */ - public static BlipContentRefs all(Blip blip, String target, int maxResult) { - return new BlipContentRefs(blip, - new BlipIterator.TextIterator(blip, target, maxResult), - Parameter.of(ParamsProperty.MODIFY_QUERY, new DocumentModifyQuery(target, maxResult))); - } - - /** - * Constructs an instance representing the search for element - * {@code ElementType}, that has the properties specified in - * {@code restrictions}. - * - * @param blip the blip to find {@code target} in. - * @param target the element type to search. - * @param maxResult the maximum number of results. - * @param restrictions the additional properties filter that need to be - * matched. - * @return an instance of blip references. - */ - public static BlipContentRefs all(Blip blip, ElementType target, int maxResult, - Restriction... restrictions) { - Map<String, String> restrictionsAsMap = new HashMap<String, String>(restrictions.length); - for (Restriction restriction : restrictions) { - restrictionsAsMap.put(restriction.getKey(), restriction.getValue()); - } - - return new BlipContentRefs(blip, - new BlipIterator.ElementIterator(blip, target, restrictionsAsMap, maxResult), - Parameter.of(ParamsProperty.MODIFY_QUERY, - new DocumentModifyQuery(target, restrictionsAsMap, maxResult))); - } - - /** - * Constructs an instance representing the entire blip content. - * - * @param blip the blip to represent. - * @return an instance of blip references. - */ - public static BlipContentRefs all(Blip blip) { - return new BlipContentRefs(blip, - new BlipIterator.SingleshotIterator(blip, 0, blip.getContent().length())); - } - - /** - * Constructs an instance representing an explicitly set range. - * - * @param blip the blip to represent. - * @param start the start index of the range. - * @param end the end index of the range. - * @return an instance of blip references. - */ - public static BlipContentRefs range(Blip blip, int start, int end) { - return new BlipContentRefs(blip, - new BlipIterator.SingleshotIterator(blip, start, end), - Parameter.of(ParamsProperty.RANGE, new Range(start, end))); - } - - /** - * Private constructor. - * - * @param blip the blip to navigate. - * @param iterator the iterator to iterate over blip content. - * @param parameters the additional parameters to be passed in the outgoing - * operation. - */ - private BlipContentRefs(Blip blip, BlipIterator<?> iterator, Parameter... parameters) { - this.blip = blip; - this.iterator = iterator; - this.parameters = Arrays.asList(parameters); - } - - /** - * Executes this BlipRefs object. - * - * @param modifyHow the operation to be executed. - * @param bundledAnnotations optional list of annotations to immediately - * apply to newly added text. - * @param arguments a list of arguments for the operation. The arguments vary - * depending on the operation: - * <ul> - * <li>For DELETE: none (the supplied arguments will be ignored)</li> - * <li>For ANNOTATE: a list of {@link Annotation} objects</li> - * <li>For CLEAR_ANNOTATION: the key of the annotation to be - * cleared. Only the first argument will be used.</li> - * <li>For UPDATE_ELEMENT: a list of {@link Map}, each represents - * new element properties.</li> - * <li>For INSERT, INSERT_AFTER, or REPLACE: a list of - * {@link BlipContent}s. - * </ul> - * For operations that take a list of entities as the argument, once - * this method hits the end of the argument list, it will wrap around. - * For example, if this {@link BlipContentRefs} object has 5 hits, when - * applying an ANNOTATE operation with 4 arguments, the first argument - * will be applied to the 5th hit. - * @return this instance of blip references, for chaining. - */ - @SuppressWarnings({"unchecked", "fallthrough"}) - private BlipContentRefs execute( - ModifyHow modifyHow, List<BundledAnnotation> bundledAnnotations, Object... arguments) { - // If there is no match found, return immediately without generating op. - if (!iterator.hasNext()) { - return this; - } - - int nextIndex = 0; - Object next = null; - List<BlipContent> computed = new ArrayList<BlipContent>(); - List<Element> updatedElements = new ArrayList<Element>(); - boolean useMarkup = false; - - while (iterator.hasNext()) { - Range range = iterator.next(); - int start = range.getStart(); - int end = range.getEnd(); - - if (blip.length() == 0 && (start != 0 || end != 0)) { - throw new IndexOutOfBoundsException("Start and end have to be 0 for empty blip."); - } else if (start < 0 || end < 1) { - throw new IndexOutOfBoundsException("Position outside the blip."); - } else if ((start >= blip.length() || end > blip.length()) && - modifyHow != ModifyHow.INSERT) { - throw new IndexOutOfBoundsException("Position outside the blip."); - } else if (start > blip.length() && modifyHow == ModifyHow.INSERT) { - throw new IndexOutOfBoundsException("Position outside the blip."); - } else if (start >= end){ - throw new IndexOutOfBoundsException("Start has to be less than end."); - } - - // Get the next argument. - if (nextIndex < arguments.length) { - next = arguments[nextIndex]; - - // If the next argument is a function, call the function. - if (next instanceof Function) { - // Get the matched content. - BlipContent source; - if (end - start == 1 && blip.getElements().containsKey(start)) { - source = blip.getElements().get(start); - } else { - source = Plaintext.of(blip.getContent().substring(start, end)); - } - // Compute the new content. - next = ((Function) next).call(source); - if (next instanceof BlipContent) { - computed.add((BlipContent) next); - } - } - nextIndex = ++nextIndex % arguments.length; - } - - switch (modifyHow) { - case DELETE: - // You can't delete the first newline. - if (start == 0) { - start = 1; - } - - // Delete all elements that fall into this range. - Iterator<Integer> elementIterator = - blip.getElements().subMap(start, end).keySet().iterator(); - while(elementIterator.hasNext()) { - elementIterator.next(); - elementIterator.remove(); - } - - blip.deleteAnnotations(start, end); - blip.shift(end, start - end); - iterator.shift(-1); - blip.setContent(blip.getContent().substring(0, start) + - blip.getContent().substring(end)); - break; - case ANNOTATE: - Annotation annotation = Annotation.class.cast(next); - blip.getAnnotations().add(annotation.getName(), annotation.getValue(), start, end); - break; - case CLEAR_ANNOTATION: - String annotationName = arguments[0].toString(); - blip.getAnnotations().delete(annotationName, start, end); - break; - case UPDATE_ELEMENT: - Element existingElement = blip.getElements().get(start); - if (existingElement == null) { - throw new IllegalArgumentException("No element found at index " + start + "."); - } - Map<String, String> properties = Map.class.cast(next); - updatedElements.add(new Element(existingElement.getType(), properties)); - for (Entry<String, String> entry : properties.entrySet()) { - existingElement.setProperty(entry.getKey(), entry.getValue()); - } - break; - case INSERT: - end = start; - case INSERT_AFTER: - start = end; - case REPLACE: - // Get the plain-text version of next. - String text = BlipContent.class.cast(next).getText(); - - // Compute the shift amount for the iterator. - int iteratorShiftAmount = text.length() - 1; - if (end == start) { - iteratorShiftAmount += range.getEnd() - range.getStart(); - } - iterator.shift(iteratorShiftAmount); - - // In the case of a replace, and the replacement text is shorter, - // delete the delta. - if (start != end && text.length() < end - start) { - blip.deleteAnnotations(start + text.length(), end); - } - - blip.shift(end, text.length() + start - end); - blip.setContent(blip.getContent().substring(0, start) + text + - blip.getContent().substring(end)); - - if (next instanceof Element) { - blip.getElements().put(start, Element.class.cast(next)); - } else if (bundledAnnotations != null) { - for (BundledAnnotation bundled : bundledAnnotations) { - blip.getAnnotations().add(bundled.key, bundled.value, start, start + text.length()); - } - } - break; - } - } - - OperationRequest op = blip.getOperationQueue().modifyDocument(blip); - - for (Parameter parameter : parameters) { - op.addParameter(parameter); - } - - // Prepare the operation parameters. - List<String> values = null; - String annotationName = null; - List<Element> elements = null; - switch (modifyHow) { - case UPDATE_ELEMENT: - elements = updatedElements; - break; - case ANNOTATE: - values = new ArrayList<String>(arguments.length); - for (Object item : arguments) { - values.add(Annotation.class.cast(item).getValue()); - } - annotationName = Annotation.class.cast(arguments[0]).getName(); - break; - case CLEAR_ANNOTATION: - annotationName = arguments[0].toString(); - break; - case INSERT: - case INSERT_AFTER: - case REPLACE: - values = new ArrayList<String>(arguments.length); - elements = new ArrayList<Element>(arguments.length); - Object[] toBeAdded = arguments; - if (arguments[0] instanceof Function) { - toBeAdded = computed.toArray(); - } - for (Object argument : toBeAdded) { - if (argument instanceof Element) { - elements.add(Element.class.cast(argument)); - values.add(null); - } else if (argument instanceof Plaintext){ - values.add(BlipContent.class.cast(argument).getText()); - elements.add(null); - } - } - break; - } - - op.addParameter(Parameter.of(ParamsProperty.MODIFY_ACTION, - new DocumentModifyAction( - modifyHow, values, annotationName, elements, bundledAnnotations, useMarkup))); - - iterator.reset(); - return this; - } - - /** - * Inserts the given arguments at the matched positions. - * - * @param arguments the new contents to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert(BlipContent... arguments) { - return insert(null, arguments); - } - - /** - * Inserts computed contents at the matched positions. - * - * @param functions the functions to compute the new contents based on the - * matched contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert(BlipContentFunction... functions) { - return insert(null, functions); - } - - /** - * Inserts the given strings at the matched positions. - * - * @param arguments the new strings to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert(String... arguments) { - return insert(null, arguments); - } - - /** - * Inserts the given arguments at the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new contents to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert( - List<BundledAnnotation> bundledAnnotations, BlipContent... arguments) { - return execute(ModifyHow.INSERT, bundledAnnotations, ((Object[]) arguments)); - } - - /** - * Inserts computed contents at the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param functions the functions to compute the new contents based on the - * matched contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert( - List<BundledAnnotation> bundledAnnotations, BlipContentFunction... functions) { - return execute(ModifyHow.INSERT, bundledAnnotations, ((Object[]) functions)); - } - - /** - * Inserts the given strings at the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new strings to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insert(List<BundledAnnotation> bundledAnnotations, String... arguments) { - Object[] array = new Plaintext[arguments.length]; - for (int i = 0; i < arguments.length; ++i) { - array[i] = Plaintext.of(arguments[i]); - } - return execute(ModifyHow.INSERT, bundledAnnotations, array); - } - - /** - * Inserts the given arguments just after the matched positions. - * - * @param arguments the new contents to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter(BlipContent... arguments) { - return insertAfter(null, arguments); - } - - /** - * Inserts computed contents just after the matched positions. - * - * @param functions the functions to compute the new contents based on the - * matched contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter(BlipContentFunction... functions) { - return insertAfter(null, functions); - } - - /** - * Inserts the given strings just after the matched positions. - * - * @param arguments the new strings to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter(String... arguments) { - return insertAfter(null, arguments); - } - - /** - * Inserts the given arguments just after the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new contents to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter( - List<BundledAnnotation> bundledAnnotations, BlipContent... arguments) { - return execute(ModifyHow.INSERT_AFTER, bundledAnnotations, (Object[]) arguments); - } - - /** - * Inserts computed contents just after the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param functions the functions to compute the new contents based on the - * matched contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter( - List<BundledAnnotation> bundledAnnotations, BlipContentFunction... functions) { - return execute(ModifyHow.INSERT_AFTER, bundledAnnotations, (Object[]) functions); - } - - /** - * Inserts the given strings just after the matched positions. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new strings to be inserted. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs insertAfter( - List<BundledAnnotation> bundledAnnotations, String... arguments) { - Object[] array = new Plaintext[arguments.length]; - for (int i = 0; i < arguments.length; ++i) { - array[i] = Plaintext.of(arguments[i]); - } - return execute(ModifyHow.INSERT_AFTER, bundledAnnotations, array); - } - - /** - * Replaces the matched positions with the given arguments. - * - * @param arguments the new contents to replace the original contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace(BlipContent... arguments) { - return replace(null, arguments); - } - - /** - * Replaces the matched positions with computed contents. - * - * @param functions the functions to compute the new contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace(BlipContentFunction... functions) { - return replace(null, functions); - } - - /** - * Replaces the matched positions with the given strings. - * - * @param arguments the new strings to replace the original contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace(String... arguments) { - return replace(null, arguments); - } - - /** - * Replaces the matched positions with the given arguments. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new contents to replace the original contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace( - List<BundledAnnotation> bundledAnnotations, BlipContent... arguments) { - return execute(ModifyHow.REPLACE, bundledAnnotations, (Object[]) arguments); - } - - /** - * Replaces the matched positions with computed contents. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param functions the functions to compute the new contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace( - List<BundledAnnotation> bundledAnnotations, BlipContentFunction... functions) { - return execute(ModifyHow.REPLACE, bundledAnnotations, (Object[]) functions); - } - - /** - * Replaces the matched positions with the given strings. - * - * @param bundledAnnotations annotations to immediately apply to the inserted - * text. - * @param arguments the new strings to replace the original contents. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs replace(List<BundledAnnotation> bundledAnnotations, String... arguments) { - Object[] array = new Plaintext[arguments.length]; - for (int i = 0; i < arguments.length; ++i) { - array[i] = Plaintext.of(arguments[i]); - } - return execute(ModifyHow.REPLACE, bundledAnnotations, array); - } - - /** - * Deletes the contents at the matched positions. - * - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs delete() { - return execute(ModifyHow.DELETE, null); - } - - /** - * Annotates the contents at the matched positions. - * - * @param key the annotation key. - * @param values the annotation values. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs annotate(String key, String... values) { - if (values.length == 0) { - values = new String[]{key}; - } - - Annotation[] annotations = new Annotation[values.length]; - for (int i = 0; i < values.length; ++i) { - annotations[i] = new Annotation(key, values[i], 0, 1); - } - return execute(ModifyHow.ANNOTATE, null, (Object[]) annotations); - } - - /** - * Clears the annotations at the matched positions. - * - * @param key the annotation key to be cleared. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs clearAnnotation(String key) { - return execute(ModifyHow.CLEAR_ANNOTATION, null, key); - } - - /** - * Updates the properties of all elements at the matched positions with the - * given properties map. - * - * Note: The purpose of this overloaded version is because the version that - * takes a var-args generates compiler warning due to the way generics and - * var-args are implemented in Java. Most of the time, robot only needs to - * update one gadget at at time, and it can use this version to avoid the - * compiler warning. - * - * @param newProperties the new properties map. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs updateElement(Map<String, String> newProperties) { - return execute(ModifyHow.UPDATE_ELEMENT, null, new Object[] {newProperties}); - } - - /** - * Updates the properties of all elements at the matched positions with - * computed properties map. - * - * Note: The purpose of this overloaded version is because the version that - * takes a var-args generates compiler warning due to the way generics and - * var-args are implemented in Java. Most of the time, robot only needs to - * update one gadget at at time, and it can use this version to avoid the - * compiler warning. - * - * @param function the function to compute the new properties map. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs updateElement(MapFunction function) { - return execute(ModifyHow.UPDATE_ELEMENT, null, new Object[] {function}); - } - - /** - * Updates the properties of all elements at the matched positions with the - * given properties maps. - * - * @param newProperties an array of new properties map. - * @return an instance of this blip references, for chaining. - */ - @SuppressWarnings("unchecked") - public BlipContentRefs updateElement(Map<String, String>... newProperties) { - return execute(ModifyHow.UPDATE_ELEMENT, null, (Object[]) newProperties); - } - - /** - * Updates the properties of all elements at the matched positions with - * computed properties maps. - * - * @param functions an array of function to compute new properties maps. - * @return an instance of this blip references, for chaining. - */ - public BlipContentRefs updateElement(MapFunction... functions) { - return execute(ModifyHow.UPDATE_ELEMENT, null, (Object[]) functions); - } - - /** - * Checks whether this blip references contains any matches or not. - * - * @return {@code true} if it has any more matches. Otherwise, returns - * {@code false}. - */ - public boolean isEmpty() { - return iterator.hasNext(); - } - - /** - * Returns all matches. - * - * @return a list of {@link BlipContent} that represents the hits. - */ - public List<BlipContent> values() { - List<BlipContent> result = new ArrayList<BlipContent>(); - while (iterator.hasNext()) { - Range range = iterator.next(); - if (range.getEnd() - range.getStart() == 1 && - blip.getElements().containsKey(range.getStart())) { - result.add(blip.getElements().get(range.getStart())); - } else { - result.add(Plaintext.of(blip.getContent().substring(range.getStart(), range.getEnd()))); - } - } - iterator.reset(); - return result; - } - - /** - * Returns the first hit. - * - * @return an instance of {@link BlipContent}, that represents the first hit. - */ - public BlipContent value() { - BlipContent result = null; - if (iterator.hasNext()) { - Range range = iterator.next(); - if (range.getEnd() - range.getStart() == 1 && - blip.getElements().containsKey(range.getStart())) { - result = blip.getElements().get(range.getStart()); - } else { - result = Plaintext.of(blip.getContent().substring(range.getStart(), range.getEnd())); - } - } - iterator.reset(); - return result; - } - - @Override - public Iterator<Range> iterator() { - iterator.reset(); - return iterator; - } -}
