001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package org.restlet.resource;
020:
021: import java.util.Collection;
022: import java.util.Date;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import org.restlet.data.CharacterSet;
027: import org.restlet.data.Encoding;
028: import org.restlet.data.Language;
029: import org.restlet.data.MediaType;
030: import org.restlet.data.Reference;
031: import org.restlet.data.Tag;
032: import org.restlet.util.DateUtils;
033: import org.restlet.util.WrapperList;
034:
035: /**
036: * Descriptor for available representations of a resource. It contains all the
037: * important metadata about a representation but is not able to actually serve
038: * the representation's content itself. For this, you need to use the
039: * Representation subclass.
040: *
041: * @author Jerome Louvel (contact@noelios.com)
042: */
043: public class Variant {
044: /**
045: * Indicates that the size of the representation can't be known in advance.
046: */
047: public static final long UNKNOWN_SIZE = -1L;
048:
049: /** The natural language(s) of the intended audience for this variant. */
050: private List<Language> languages;
051:
052: /** The media type. */
053: private MediaType mediaType;
054:
055: /** The character set or null if not applicable. */
056: private CharacterSet characterSet;
057:
058: /** The additional content codings applied to the entity-body. */
059: private List<Encoding> encodings;
060:
061: /**
062: * The expected size. Dynamic representations can have any size, but
063: * sometimes we can know in advance the expected size. If this expected size
064: * is specified by the user, it has a higher priority than any size that can
065: * be guessed by the representation (like a file size).
066: */
067: private long size;
068:
069: /** The expiration date. */
070: private Date expirationDate;
071:
072: /** The modification date. */
073: private Date modificationDate;
074:
075: /** The tag. */
076: private Tag tag;
077:
078: /**
079: * The identifier.
080: */
081: private Reference identifier;
082:
083: /**
084: * Default constructor.
085: */
086: public Variant() {
087: this (null);
088: }
089:
090: /**
091: * Constructor.
092: *
093: * @param mediaType
094: * The media type.
095: */
096: public Variant(MediaType mediaType) {
097: this .characterSet = null;
098: this .encodings = null;
099: this .size = UNKNOWN_SIZE;
100: this .expirationDate = null;
101: this .languages = null;
102: this .mediaType = mediaType;
103: this .modificationDate = null;
104: this .tag = null;
105: this .identifier = null;
106: }
107:
108: /**
109: * Returns the character set or null if not applicable.
110: *
111: * @return The character set or null if not applicable.
112: */
113: public CharacterSet getCharacterSet() {
114: return this .characterSet;
115: }
116:
117: /**
118: * Returns the list of encodings applied to the entity-body. An
119: * "IllegalArgumentException" exception is thrown when adding a null
120: * encoding to this list.
121: *
122: * @return The list of encodings applied to the entity-body.
123: */
124: public List<Encoding> getEncodings() {
125: if (this .encodings == null) {
126: encodings = new WrapperList<Encoding>() {
127:
128: @Override
129: public void add(int index, Encoding element) {
130: if (element == null) {
131: throw new IllegalArgumentException(
132: "Cannot add a null encoding.");
133: } else {
134: super .add(index, element);
135: }
136: }
137:
138: @Override
139: public boolean add(Encoding element) {
140: if (element == null) {
141: throw new IllegalArgumentException(
142: "Cannot add a null encoding.");
143: } else {
144: return super .add(element);
145: }
146: }
147:
148: @Override
149: public boolean addAll(
150: Collection<? extends Encoding> elements) {
151: boolean addNull = (elements == null);
152: if (!addNull) {
153: for (Iterator<? extends Encoding> iterator = elements
154: .iterator(); !addNull
155: && iterator.hasNext();) {
156: addNull = (iterator.next() == null);
157: }
158: }
159: if (addNull) {
160: throw new IllegalArgumentException(
161: "Cannot add a null encoding.");
162: } else {
163: return super .addAll(elements);
164: }
165: }
166:
167: @Override
168: public boolean addAll(int index,
169: Collection<? extends Encoding> elements) {
170: boolean addNull = (elements == null);
171: if (!addNull) {
172: for (Iterator<? extends Encoding> iterator = elements
173: .iterator(); !addNull
174: && iterator.hasNext();) {
175: addNull = (iterator.next() == null);
176: }
177: }
178: if (addNull) {
179: throw new IllegalArgumentException(
180: "Cannot add a null encoding.");
181: } else {
182: return super .addAll(index, elements);
183: }
184: }
185: };
186: }
187: return this .encodings;
188: }
189:
190: /**
191: * Returns the future date when this representation expire. If this
192: * information is not known, returns null.
193: *
194: * @return The expiration date.
195: */
196: public Date getExpirationDate() {
197: return this .expirationDate;
198: }
199:
200: /**
201: * Returns the list of languages. An "IllegalArgumentException" exception is
202: * thrown when adding a null language to this list.
203: *
204: * @return The list of languages.
205: */
206: public List<Language> getLanguages() {
207: if (languages == null)
208: languages = new WrapperList<Language>() {
209:
210: @Override
211: public void add(int index, Language element) {
212: if (element == null) {
213: throw new IllegalArgumentException(
214: "Cannot add a null language.");
215: } else {
216: super .add(index, element);
217: }
218: }
219:
220: @Override
221: public boolean add(Language element) {
222: if (element == null) {
223: throw new IllegalArgumentException(
224: "Cannot add a null language.");
225: } else {
226: return super .add(element);
227: }
228: }
229:
230: @Override
231: public boolean addAll(
232: Collection<? extends Language> elements) {
233: boolean addNull = (elements == null);
234: if (!addNull) {
235: for (Iterator<? extends Language> iterator = elements
236: .iterator(); !addNull
237: && iterator.hasNext();) {
238: addNull = (iterator.next() == null);
239: }
240: }
241: if (addNull) {
242: throw new IllegalArgumentException(
243: "Cannot add a null language.");
244: } else {
245: return super .addAll(elements);
246: }
247: }
248:
249: @Override
250: public boolean addAll(int index,
251: Collection<? extends Language> elements) {
252: boolean addNull = (elements == null);
253: if (!addNull) {
254: for (Iterator<? extends Language> iterator = elements
255: .iterator(); !addNull
256: && iterator.hasNext();) {
257: addNull = (iterator.next() == null);
258: }
259: }
260: if (addNull) {
261: throw new IllegalArgumentException(
262: "Cannot add a null language.");
263: } else {
264: return super .addAll(index, elements);
265: }
266: }
267:
268: };
269: return this .languages;
270: }
271:
272: /**
273: * Returns the media type.
274: *
275: * @return The media type.
276: */
277: public MediaType getMediaType() {
278: return this .mediaType;
279: }
280:
281: /**
282: * Returns the last date when this representation was modified. If this
283: * information is not known, returns null.
284: *
285: * @return The modification date.
286: */
287: public Date getModificationDate() {
288: return this .modificationDate;
289: }
290:
291: /**
292: * Returns the size in bytes if known, UNKNOWN_SIZE (-1) otherwise.
293: *
294: * @return The size in bytes if known, UNKNOWN_SIZE (-1) otherwise.
295: */
296: public long getSize() {
297: return this .size;
298: }
299:
300: /**
301: * Returns the tag.
302: *
303: * @return The tag.
304: */
305: public Tag getTag() {
306: return this .tag;
307: }
308:
309: /**
310: * Sets the character set or null if not applicable.
311: *
312: * @param characterSet
313: * The character set or null if not applicable.
314: */
315: public void setCharacterSet(CharacterSet characterSet) {
316: this .characterSet = characterSet;
317: }
318:
319: /**
320: * Sets the future date when this representation expire. If this information
321: * is not known, pass null.
322: *
323: * @param expirationDate
324: * The expiration date.
325: */
326: public void setExpirationDate(Date expirationDate) {
327: this .expirationDate = DateUtils.unmodifiable(expirationDate);
328: }
329:
330: /**
331: * Sets the media type.
332: *
333: * @param mediaType
334: * The media type.
335: */
336: public void setMediaType(MediaType mediaType) {
337: this .mediaType = mediaType;
338: }
339:
340: /**
341: * Sets the last date when this representation was modified. If this
342: * information is not known, pass null.
343: *
344: * @param modificationDate
345: * The modification date.
346: */
347: public void setModificationDate(Date modificationDate) {
348: this .modificationDate = DateUtils
349: .unmodifiable(modificationDate);
350: }
351:
352: /**
353: * Sets the expected size in bytes if known, -1 otherwise.
354: *
355: * @param expectedSize
356: * The expected size in bytes if known, -1 otherwise.
357: */
358: public void setSize(long expectedSize) {
359: this .size = expectedSize;
360: }
361:
362: /**
363: * Sets the tag.
364: *
365: * @param tag
366: * The tag.
367: */
368: public void setTag(Tag tag) {
369: this .tag = tag;
370: }
371:
372: /**
373: * Returns an optional identifier. This is useful when the representation is
374: * accessible from a location separate from the representation's resource
375: * URI, for example when content negotiation occurs.
376: *
377: * @return The identifier.
378: */
379: public Reference getIdentifier() {
380: return this .identifier;
381: }
382:
383: /**
384: * Sets the optional identifier. This is useful when the representation is
385: * accessible from a location separate from the representation's resource
386: * URI, for example when content negotiation occurs.
387: *
388: * @param identifier
389: * The identifier.
390: */
391: public void setIdentifier(Reference identifier) {
392: this .identifier = identifier;
393: }
394:
395: /**
396: * Sets the identifier from a URI string.
397: *
398: * @param identifierUri
399: * The identifier to parse.
400: */
401: public void setIdentifier(String identifierUri) {
402: setIdentifier(new Reference(identifierUri));
403: }
404:
405: }
|