/** * Copyright 2013 OpenSocial Foundation * Copyright 2013 International Business Machines Corporation * * 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. * * Utility library for working with Activity Streams Actions * Requires underscorejs. * * @author James M Snell (jasnell@us.ibm.com) */ package com.ibm.common.activitystreams; import static com.google.common.base.Preconditions.checkArgument; import java.io.Serializable; import java.util.Iterator; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.ibm.common.activitystreams.util.AbstractWritable; /** * An Activity Streams 2.0 Link Value. * * <p>In Actvity Streams 2.0, Link Values can take one of three possible * forms:</p> * * <ul> * <li>A String containing an absolute IRI</li> * <li>An Activity String object</li> * <li>An Array containing a mix of Strings or Objects</li> * </ul> * * <p>For instance, the following are all valid examples of Link Values:</p> * * <pre> * { * "actor": "acct:joe@example.org" * } * * { * "actor": { * "objectType": "person", * "id": "acct:sally@example.org" * } * } * * { * "actor": [ * "acct:joe@example.org", * { * "objectType": "person", * "id": "acct:sally@example.org" * } * ] * } * </pre> * * <p>The LinkValue interface provides a minimal abstraction over these * value options. Developers will have to check the ValueType of the LinkValue * (or do an instanceof check) in order to determine which kind of value * they are working with.</p> * * <pre> * Activity activity = ...; * Iterable<LinkValue> actors = activity.actor(); * for (LinkValue actor : actors) { * switch(actor.valueType()) { * case SIMPLE: * SimpleLinkValue s = (SimpleLinkValue)actor; * //... * break; * case OBJECT: * ASObject obj = (ASObject)actor; * //... * break; * } * } * </pre> * * <p>Methods that return Iterable<LinkValue> will never include an instance * of ArrayLinkValue as one of the Iterable values</p> * * @author james * @version $Revision: 1.0 $ */ public interface LinkValue extends Writable, Serializable { /** * Returns the LinkValue type * @return ValueType */ ValueType valueType(); /** * A "Simple Link Value" is a string with a relative or absolute * URI or IRI value. */ public static final class SimpleLinkValue extends AbstractWritable implements LinkValue, Serializable { /** * Creates a new builder * @return Builder **/ public static Builder make() { return new Builder(); } /** * Creates a new instance * @param url String * @return LinkValue **/ public static LinkValue make(String url) { return new SimpleLinkValue.Builder().url(url).get(); } public static final class Builder extends AbstractWritable.AbstractWritableBuilder<SimpleLinkValue,Builder> { private String iri; /** * Set the url * @param iri String * @return Builder **/ public Builder url(String iri) { this.iri = iri; return this; } /** * Method get. * @return SimpleLinkValue * @see com.google.common.base.Supplier#get() **/ public SimpleLinkValue get() { return new SimpleLinkValue(this); } } private final String iri; SimpleLinkValue(SimpleLinkValue.Builder builder) { super(builder); this.iri = builder.iri; } /** * Return the url * @return String */ public String url() { return iri; } public String toString() { return iri; } public ValueType valueType() { return ValueType.SIMPLE; } // Java Serialization Support Object writeReplace() throws java.io.ObjectStreamException { return new SerializedForm(this); } private static class SerializedForm implements Serializable { private static final long serialVersionUID = -1975376657749952999L; private String iri; SerializedForm(SimpleLinkValue obj) { this.iri = obj.iri; } Object readResolve() throws java.io.ObjectStreamException { return Makers.linkValue(iri); } } } /** * An Array Link value is a JSON Array of one or more Simple or Object * Link Values. Array Link Values MUST NOT contain nested arrays. */ public static final class ArrayLinkValue extends AbstractWritable implements Iterable<LinkValue>, LinkValue, Serializable { /** * Create a new builder * @return ArrayLinkValue.Builder **/ public static ArrayLinkValue.Builder make() { return new ArrayLinkValue.Builder(); } public static class Builder extends AbstractWritable.AbstractWritableBuilder<ArrayLinkValue, Builder> { private final ImmutableList.Builder<LinkValue> links = ImmutableList.builder(); /** * Add one or more items * @param value String * @param values String[] * @return Builder */ public Builder add(String value, String... values) { if (value != null) add(SimpleLinkValue.make(value)); if (values != null) for (String v : values) add(SimpleLinkValue.make(v)); return this; } /** * Add one or more link values * @param links Iterable<LinkValue> * @return Builder */ public Builder add(Iterable<LinkValue> links) { for (LinkValue l : links) add(l); return this; } /** * Add one or more link values * @param values LinkValue[] * @return Builder */ public Builder add(LinkValue value, LinkValue... values) { if (value != null) { checkArgument(value.valueType() != ValueType.ARRAY); links.add(value); } if (values != null) for (LinkValue v : values) { checkArgument(v.valueType() != ValueType.ARRAY); links.add(v); } return this; } /** * Add a link value * @param value Supplier<? extends LinkValue> * @return Builder */ public Builder add(Supplier<? extends LinkValue> value) { LinkValue val = value.get(); checkArgument(val.valueType() != ValueType.ARRAY); links.add(val); return this; } /** * Method get. * @return ArrayLinkValue * @see com.google.common.base.Supplier#get() **/ public ArrayLinkValue get() { return new ArrayLinkValue(this); } } private final ImmutableList<LinkValue> links; ArrayLinkValue(ArrayLinkValue.Builder builder) { super(builder); this.links = builder.links.build(); } /** * Method iterator. * @return Iterator<LinkValue> * @see java.lang.Iterable#iterator() **/ public Iterator<LinkValue> iterator() { return links.iterator(); } public String toString() { return links.toString(); } public ValueType valueType() { return ValueType.ARRAY; } // Java Serialization Support Object writeReplace() throws java.io.ObjectStreamException { return new SerializedForm(this); } private static class SerializedForm implements Serializable { private static final long serialVersionUID = -1975376657749952999L; private ImmutableList<LinkValue> list; SerializedForm(ArrayLinkValue obj) { this.list = obj.links; } Object readResolve() throws java.io.ObjectStreamException { return Makers.linkValues().add(list); } } } }