View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.elasticsearch.index.objects.series;
23  
24  import org.opencastproject.elasticsearch.index.objects.IndexObject;
25  import org.opencastproject.util.DateTimeSupport.UtcTimestampAdapter;
26  import org.opencastproject.util.EqualsUtil;
27  import org.opencastproject.util.IoSupport;
28  import org.opencastproject.util.XmlSafeParser;
29  import org.opencastproject.util.jaxb.ExtendedMetadataAdapter;
30  
31  import org.codehaus.jettison.json.JSONException;
32  import org.codehaus.jettison.json.JSONObject;
33  import org.codehaus.jettison.mapped.Configuration;
34  import org.codehaus.jettison.mapped.MappedNamespaceConvention;
35  import org.codehaus.jettison.mapped.MappedXMLStreamReader;
36  import org.codehaus.jettison.mapped.MappedXMLStreamWriter;
37  import org.xml.sax.SAXException;
38  
39  import java.io.BufferedReader;
40  import java.io.IOException;
41  import java.io.InputStream;
42  import java.io.InputStreamReader;
43  import java.io.StringWriter;
44  import java.util.ArrayList;
45  import java.util.Date;
46  import java.util.HashMap;
47  import java.util.List;
48  import java.util.Map;
49  
50  import javax.xml.bind.JAXBContext;
51  import javax.xml.bind.JAXBException;
52  import javax.xml.bind.Marshaller;
53  import javax.xml.bind.Unmarshaller;
54  import javax.xml.bind.annotation.XmlAccessType;
55  import javax.xml.bind.annotation.XmlAccessorType;
56  import javax.xml.bind.annotation.XmlElement;
57  import javax.xml.bind.annotation.XmlElementWrapper;
58  import javax.xml.bind.annotation.XmlRootElement;
59  import javax.xml.bind.annotation.XmlType;
60  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
61  import javax.xml.stream.XMLStreamException;
62  import javax.xml.stream.XMLStreamReader;
63  import javax.xml.stream.XMLStreamWriter;
64  
65  /**
66   * Object wrapper for a series.
67   */
68  @XmlType(name = "series", namespace = IndexObject.INDEX_XML_NAMESPACE, propOrder = { "identifier", "title",
69          "description", "subject", "organization", "language", "creator", "license", "extendedMetadata", "accessPolicy",
70          "managedAcl", "createdDateTime", "organizers", "contributors", "publishers", "rightsHolder", "theme" })
71  @XmlRootElement(name = "series", namespace = IndexObject.INDEX_XML_NAMESPACE)
72  @XmlAccessorType(XmlAccessType.NONE)
73  public class Series implements IndexObject {
74  
75    /** The document type */
76    public static final String DOCUMENT_TYPE = "series";
77  
78    /** The name of the surrounding XML tag to wrap a result of multiple series */
79    public static final String XML_SURROUNDING_TAG = "series-list";
80  
81    /** The identifier */
82    @XmlElement(name = "identifier")
83    private String identifier = null;
84  
85    /** The title */
86    @XmlElement(name = "title")
87    private String title = null;
88  
89    /** The description */
90    @XmlElement(name = "description")
91    private String description = null;
92  
93    /** The subject */
94    @XmlElement(name = "subject")
95    private String subject = null;
96  
97    /** The organization for the series */
98    @XmlElement(name = "organization")
99    private String organization = null;
100 
101   /** The language for the series */
102   @XmlElement(name = "language")
103   private String language = null;
104 
105   /** The creator of the series */
106   @XmlElement(name = "creator")
107   private String creator = null;
108 
109   /** The license of the series */
110   @XmlElement(name = "license")
111   private String license = null;
112 
113   @XmlElement(name = "extendedMetadata")
114   @XmlJavaTypeAdapter(ExtendedMetadataAdapter.class)
115   private Map<String, Map<String, List<String>>> extendedMetadata = new HashMap();
116 
117   /** The access policy of the series */
118   @XmlElement(name = "access_policy")
119   private String accessPolicy = null;
120 
121   /** The name of the managed ACL used by the series (if set) */
122   @XmlElement(name = "managed_acl")
123   private String managedAcl = null;
124 
125   /** The date and time the series was created in UTC format e.g. 2011-07-16T20:39:05Z */
126   @XmlElement(name = "createdDateTime")
127   @XmlJavaTypeAdapter(UtcTimestampAdapter.class)
128   private Date createdDateTime;
129 
130   @XmlElementWrapper(name = "organizers")
131   @XmlElement(name = "organizer")
132   private List<String> organizers = null;
133 
134   @XmlElementWrapper(name = "contributors")
135   @XmlElement(name = "contributor")
136   private List<String> contributors = null;
137 
138   @XmlElementWrapper(name = "publishers")
139   @XmlElement(name = "publisher")
140   private List<String> publishers = null;
141 
142   @XmlElement(name = "rights_holder")
143   private String rightsHolder = null;
144 
145   @XmlElement(name = "theme")
146   private Long theme = null;
147 
148   /** Context for serializing and deserializing */
149   private static JAXBContext context = null;
150 
151   /**
152    * Required default no arg constructor for JAXB.
153    */
154   public Series() {
155 
156   }
157 
158   /**
159    * The series identifier.
160    *
161    * @param identifier
162    *          the object identifier
163    * @param organization
164    *          the organization
165    */
166   public Series(String identifier, String organization) {
167     this.identifier = identifier;
168     this.organization = organization;
169   }
170 
171   /**
172    * Create an unmarshaller for series
173    * @return an unmarshaller for series
174    * @throws IOException
175    */
176   public static Unmarshaller createUnmarshaller() throws IOException {
177     try {
178       if (context == null) {
179         createJAXBContext();
180       }
181       return context.createUnmarshaller();
182     } catch (JAXBException e) {
183       throw new IOException(e.getLinkedException() != null ? e.getLinkedException() : e);
184     }
185   }
186 
187   /**
188    * Returns the series identifier.
189    *
190    * @return the identifier
191    */
192   public String getIdentifier() {
193     return identifier;
194   }
195 
196   /**
197    * Sets the series title.
198    *
199    * @param title
200    *          the title
201    */
202   public void setTitle(String title) {
203     if (EqualsUtil.eq(this.title, title)) {
204       return;
205     }
206 
207     this.title = title;
208   }
209 
210   /**
211    * Returns the series title.
212    *
213    * @return the title
214    */
215   public String getTitle() {
216     return title;
217   }
218 
219   /**
220    * Sets the series description.
221    *
222    * @param description
223    *          the description
224    */
225   public void setDescription(String description) {
226     this.description = description;
227   }
228 
229   /**
230    * Returns the series description.
231    *
232    * @return the description
233    */
234   public String getDescription() {
235     return description;
236   }
237 
238   /**
239    * Sets the series subject.
240    *
241    * @param subject
242    *          the subject
243    */
244   public void setSubject(String subject) {
245     this.subject = subject;
246   }
247 
248   /**
249    * Returns the series subject.
250    *
251    * @return the subject
252    */
253   public String getSubject() {
254     return subject;
255   }
256 
257   /**
258    * Returns the series organization.
259    *
260    * @return the organization
261    */
262   public String getOrganization() {
263     return organization;
264   }
265 
266   /**
267    * Sets the series language.
268    *
269    * @param language
270    *          the language
271    */
272   public void setLanguage(String language) {
273     this.language = language;
274   }
275 
276   /**
277    * Returns the series language.
278    *
279    * @return the language
280    */
281   public String getLanguage() {
282     return language;
283   }
284 
285   /**
286    * Sets the series creator.
287    *
288    * @param creator
289    *          the creator
290    */
291   public void setCreator(String creator) {
292     this.creator = creator;
293   }
294 
295   /**
296    * Returns the series creator.
297    *
298    * @return the creator
299    */
300   public String getCreator() {
301     return creator;
302   }
303 
304   /**
305    * Sets the series license.
306    *
307    * @param license
308    *          the license
309    */
310   public void setLicense(String license) {
311     this.license = license;
312   }
313 
314   /**
315    * Returns the series license.
316    *
317    * @return the license
318    */
319   public String getLicense() {
320     return license;
321   }
322 
323   /**
324    * Sets the series access policy.
325    *
326    * @param accessPolicy
327    *          the access policy
328    */
329   public void setAccessPolicy(String accessPolicy) {
330     this.accessPolicy = accessPolicy;
331   }
332 
333   /**
334    * Returns the series access policy.
335    *
336    * @return the access policy
337    */
338   public String getAccessPolicy() {
339     return accessPolicy;
340   }
341 
342   /**
343    * Sets the name of the managed ACL used by the series.
344    *
345    * @param managedAcl
346    *          the managed ACL name
347    */
348   public void setManagedAcl(String managedAcl) {
349     this.managedAcl = managedAcl;
350   }
351 
352   /**
353    * Returns the name of the managed ACL, if the series does not have a custom ACL.
354    *
355    * @return the managed ACL name
356    */
357   public String getManagedAcl() {
358     return managedAcl;
359   }
360 
361   /**
362    * Sets the series created date and time.
363    *
364    * @param createdDateTime
365    *          the date and time the series was created.
366    */
367   public void setCreatedDateTime(Date createdDateTime) {
368     this.createdDateTime = createdDateTime;
369   }
370 
371   /**
372    * Returns the series date and time created.
373    *
374    * @return the created date and time
375    */
376   public Date getCreatedDateTime() {
377     return createdDateTime;
378   }
379 
380   /**
381    * Add an organizer
382    *
383    * @param organizer
384    *          The organizer's name.
385    */
386   public void addOrganizer(String organizer) {
387     if (organizers == null) {
388       organizers = new ArrayList<String>();
389     }
390     organizers.add(organizer);
391   }
392 
393   /**
394    * Sets the list of organizers.
395    *
396    * @param organizers
397    *          the organizers for this event
398    */
399   public void setOrganizers(List<String> organizers) {
400     this.organizers = organizers;
401   }
402 
403   /**
404    * Returns the series presenters.
405    *
406    * @return the presenters
407    */
408   public List<String> getOrganizers() {
409     return organizers;
410   }
411 
412   /**
413    * Add a contributor
414    *
415    * @param contributor
416    *          The contributor's name.
417    */
418   public void addContributor(String contributor) {
419     if (contributors == null) {
420       contributors = new ArrayList<String>();
421     }
422     contributors.add(contributor);
423   }
424 
425   /**
426    * Sets the list of contributors.
427    *
428    * @param contributors
429    *          the contributors for this event
430    */
431   public void setContributors(List<String> contributors) {
432     this.contributors = contributors;
433   }
434 
435   /**
436    * Returns the series contributors.
437    *
438    * @return the contributors
439    */
440   public List<String> getContributors() {
441     return contributors;
442   }
443 
444   /**
445    * Add a publisher
446    *
447    * @param publisher
448    *          The publisher's name.
449    */
450   public void addPublisher(String publisher) {
451     if (publishers == null) {
452       publishers = new ArrayList<String>();
453     }
454     publishers.add(publisher);
455   }
456 
457   /**
458    * Sets the list of publishers.
459    *
460    * @param publishers
461    *          the publishers for this event
462    */
463   public void setPublishers(List<String> publishers) {
464     this.publishers = publishers;
465   }
466 
467   /**
468    * Returns the series publishers.
469    *
470    * @return the publishers
471    */
472   public List<String> getPublishers() {
473     return publishers;
474   }
475 
476   /**
477    * Sets the series rights holder.
478    *
479    * @param rightsHolder
480    *          holder the rights holder
481    */
482   public void setRightsHolder(String rightsHolder) {
483     this.rightsHolder = rightsHolder;
484   }
485 
486   /**
487    * Returns the series rights holder.
488    *
489    * @return the rights holder
490    */
491   public String getRightsHolder() {
492     return rightsHolder;
493   }
494 
495   /**
496    * Sets the theme for this series
497    *
498    * @param theme
499    *          the theme
500    */
501   public void setTheme(Long theme) {
502     this.theme = theme;
503   }
504 
505   /**
506    * Returns the theme of this series
507    *
508    * @return the theme of this series
509    */
510   public Long getTheme() {
511     return theme;
512   }
513 
514   /**
515    * Sets the external metadata for a catalog type.
516    *
517    * @param type
518    *         The catalog type
519    * @param metadata
520    *         The metadata
521    */
522   public void setExtendedMetadata(String type, Map<String, List<String>> metadata) {
523     extendedMetadata.put(type, metadata);
524   }
525 
526   /**
527    * Removes the external metadata for a catalog type.
528    *
529    * @param type
530    *         The catalog type
531    */
532   public void removeExtendedMetadata(String type) {
533     extendedMetadata.remove(type);
534   }
535 
536   /**
537    * Removes all external metadata.
538    */
539   public void resetExtendedMetadata() {
540     extendedMetadata.clear();
541   }
542 
543   /**
544    * Returns the extended metadata
545    *
546    * @return the extended metadata in a map by catalog type
547    */
548   public Map<String, Map<String, List<String>>> getExtendedMetadata() {
549     return extendedMetadata;
550   }
551 
552   /**
553    * Reads the series from the input stream.
554    *
555    * @param xml
556    *          the input stream
557    * @param unmarshaller the unmarshaller to use
558    * @return the deserialized recording event
559    * @throws IOException
560    */
561   public static Series valueOf(InputStream xml, Unmarshaller unmarshaller) throws IOException {
562     try {
563       if (context == null) {
564         createJAXBContext();
565       }
566       return unmarshaller.unmarshal(XmlSafeParser.parse(xml), Series.class).getValue();
567     } catch (JAXBException e) {
568       throw new IOException(e.getLinkedException() != null ? e.getLinkedException() : e);
569     } catch (SAXException e) {
570       throw new IOException(e);
571     } finally {
572       IoSupport.closeQuietly(xml);
573     }
574   }
575 
576   /**
577    * Reads the series from the input stream.
578    *
579    * @param json
580    *          the input stream
581    * @return the deserialized recording event
582    * @throws JSONException
583    * @throws XMLStreamException
584    * @throws JAXBException
585    */
586   public static Series valueOfJson(InputStream json) throws IOException, JSONException, XMLStreamException,
587           JAXBException {
588     // TODO Get this to work, it is currently returning null properties for all properties.
589     if (context == null) {
590       createJAXBContext();
591     }
592 
593     BufferedReader streamReader = new BufferedReader(new InputStreamReader(json, "UTF-8"));
594     StringBuilder jsonStringBuilder = new StringBuilder();
595     String inputStr;
596     while ((inputStr = streamReader.readLine()) != null) {
597       jsonStringBuilder.append(inputStr);
598     }
599 
600     JSONObject obj = new JSONObject(jsonStringBuilder.toString());
601     Configuration config = new Configuration();
602     config.setSupressAtAttributes(true);
603     Map<String, String> xmlToJsonNamespaces = new HashMap<String, String>(1);
604     xmlToJsonNamespaces.put(IndexObject.INDEX_XML_NAMESPACE, "");
605     config.setXmlToJsonNamespaces(xmlToJsonNamespaces);
606     MappedNamespaceConvention con = new MappedNamespaceConvention(config);
607     Unmarshaller unmarshaller = context.createUnmarshaller();
608     // CHECKSTYLE:OFF
609     // the xml is parsed from json and should be safe
610     XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con);
611     Series event = (Series) unmarshaller.unmarshal(xmlStreamReader);
612     // CHECKSTYLE:ON
613     return event;
614   }
615 
616   /**
617    * Initialize the JAXBContext.
618    */
619   private static void createJAXBContext() throws JAXBException {
620     context = JAXBContext.newInstance(Series.class);
621   }
622 
623   /**
624    * Serializes the series.
625    *
626    * @return the serialized series
627    */
628   public String toJSON() {
629     try {
630       if (context == null) {
631         createJAXBContext();
632       }
633       Marshaller marshaller = Series.context.createMarshaller();
634 
635       Configuration config = new Configuration();
636       config.setSupressAtAttributes(true);
637       MappedNamespaceConvention con = new MappedNamespaceConvention(config);
638       StringWriter writer = new StringWriter();
639       XMLStreamWriter xmlStreamWriter = new MappedXMLStreamWriter(con, writer) {
640         @Override
641         public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
642           super.writeStartElement("", local, "");
643         }
644 
645         @Override
646         public void writeStartElement(String uri, String local) throws XMLStreamException {
647           super.writeStartElement("", local, "");
648         }
649 
650         @Override
651         public void setPrefix(String pfx, String uri) throws XMLStreamException {
652         }
653 
654         @Override
655         public void setDefaultNamespace(String uri) throws XMLStreamException {
656         }
657       };
658 
659       marshaller.marshal(this, xmlStreamWriter);
660       return writer.toString();
661     } catch (JAXBException e) {
662       throw new IllegalStateException(e.getLinkedException() != null ? e.getLinkedException() : e);
663     }
664   }
665 
666   /**
667    * Serializes the series to an XML format.
668    *
669    * @return A String with this series' content as XML.
670    */
671   public String toXML() {
672     try {
673       if (context == null) {
674         createJAXBContext();
675       }
676       StringWriter writer = new StringWriter();
677       Marshaller marshaller = Series.context.createMarshaller();
678       marshaller.marshal(this, writer);
679       return writer.toString();
680     } catch (JAXBException e) {
681       throw new IllegalStateException(e.getLinkedException() != null ? e.getLinkedException() : e);
682     }
683   }
684 
685 }