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, organization, null);
168   }
169 
170   /**
171    * The series identifier.
172    *
173    * @param identifier
174    *          the object identifier
175    * @param organization
176    *          the organization
177    */
178   public Series(String identifier, String organization, String creator) {
179     this.identifier = identifier;
180     this.organization = organization;
181     this.creator = creator;
182   }
183 
184   /**
185    * Create an unmarshaller for series
186    * @return an unmarshaller for series
187    * @throws IOException
188    */
189   public static Unmarshaller createUnmarshaller() throws IOException {
190     try {
191       if (context == null) {
192         createJAXBContext();
193       }
194       return context.createUnmarshaller();
195     } catch (JAXBException e) {
196       throw new IOException(e.getLinkedException() != null ? e.getLinkedException() : e);
197     }
198   }
199 
200   /**
201    * Returns the series identifier.
202    *
203    * @return the identifier
204    */
205   public String getIdentifier() {
206     return identifier;
207   }
208 
209   /**
210    * Sets the series title.
211    *
212    * @param title
213    *          the title
214    */
215   public void setTitle(String title) {
216     if (EqualsUtil.eq(this.title, title)) {
217       return;
218     }
219 
220     this.title = title;
221   }
222 
223   /**
224    * Returns the series title.
225    *
226    * @return the title
227    */
228   public String getTitle() {
229     return title;
230   }
231 
232   /**
233    * Sets the series description.
234    *
235    * @param description
236    *          the description
237    */
238   public void setDescription(String description) {
239     this.description = description;
240   }
241 
242   /**
243    * Returns the series description.
244    *
245    * @return the description
246    */
247   public String getDescription() {
248     return description;
249   }
250 
251   /**
252    * Sets the series subject.
253    *
254    * @param subject
255    *          the subject
256    */
257   public void setSubject(String subject) {
258     this.subject = subject;
259   }
260 
261   /**
262    * Returns the series subject.
263    *
264    * @return the subject
265    */
266   public String getSubject() {
267     return subject;
268   }
269 
270   /**
271    * Returns the series organization.
272    *
273    * @return the organization
274    */
275   public String getOrganization() {
276     return organization;
277   }
278 
279   /**
280    * Sets the series language.
281    *
282    * @param language
283    *          the language
284    */
285   public void setLanguage(String language) {
286     this.language = language;
287   }
288 
289   /**
290    * Returns the series language.
291    *
292    * @return the language
293    */
294   public String getLanguage() {
295     return language;
296   }
297 
298   /**
299    * Sets the series creator.
300    *
301    * @param creator
302    *          the creator
303    */
304   public void setCreator(String creator) {
305     this.creator = creator;
306   }
307 
308   /**
309    * Returns the series creator.
310    *
311    * @return the creator
312    */
313   public String getCreator() {
314     return creator;
315   }
316 
317   /**
318    * Sets the series license.
319    *
320    * @param license
321    *          the license
322    */
323   public void setLicense(String license) {
324     this.license = license;
325   }
326 
327   /**
328    * Returns the series license.
329    *
330    * @return the license
331    */
332   public String getLicense() {
333     return license;
334   }
335 
336   /**
337    * Sets the series access policy.
338    *
339    * @param accessPolicy
340    *          the access policy
341    */
342   public void setAccessPolicy(String accessPolicy) {
343     this.accessPolicy = accessPolicy;
344   }
345 
346   /**
347    * Returns the series access policy.
348    *
349    * @return the access policy
350    */
351   public String getAccessPolicy() {
352     return accessPolicy;
353   }
354 
355   /**
356    * Sets the name of the managed ACL used by the series.
357    *
358    * @param managedAcl
359    *          the managed ACL name
360    */
361   public void setManagedAcl(String managedAcl) {
362     this.managedAcl = managedAcl;
363   }
364 
365   /**
366    * Returns the name of the managed ACL, if the series does not have a custom ACL.
367    *
368    * @return the managed ACL name
369    */
370   public String getManagedAcl() {
371     return managedAcl;
372   }
373 
374   /**
375    * Sets the series created date and time.
376    *
377    * @param createdDateTime
378    *          the date and time the series was created.
379    */
380   public void setCreatedDateTime(Date createdDateTime) {
381     this.createdDateTime = createdDateTime;
382   }
383 
384   /**
385    * Returns the series date and time created.
386    *
387    * @return the created date and time
388    */
389   public Date getCreatedDateTime() {
390     return createdDateTime;
391   }
392 
393   /**
394    * Add an organizer
395    *
396    * @param organizer
397    *          The organizer's name.
398    */
399   public void addOrganizer(String organizer) {
400     if (organizers == null) {
401       organizers = new ArrayList<String>();
402     }
403     organizers.add(organizer);
404   }
405 
406   /**
407    * Sets the list of organizers.
408    *
409    * @param organizers
410    *          the organizers for this event
411    */
412   public void setOrganizers(List<String> organizers) {
413     this.organizers = organizers;
414   }
415 
416   /**
417    * Returns the series presenters.
418    *
419    * @return the presenters
420    */
421   public List<String> getOrganizers() {
422     return organizers;
423   }
424 
425   /**
426    * Add a contributor
427    *
428    * @param contributor
429    *          The contributor's name.
430    */
431   public void addContributor(String contributor) {
432     if (contributors == null) {
433       contributors = new ArrayList<String>();
434     }
435     contributors.add(contributor);
436   }
437 
438   /**
439    * Sets the list of contributors.
440    *
441    * @param contributors
442    *          the contributors for this event
443    */
444   public void setContributors(List<String> contributors) {
445     this.contributors = contributors;
446   }
447 
448   /**
449    * Returns the series contributors.
450    *
451    * @return the contributors
452    */
453   public List<String> getContributors() {
454     return contributors;
455   }
456 
457   /**
458    * Add a publisher
459    *
460    * @param publisher
461    *          The publisher's name.
462    */
463   public void addPublisher(String publisher) {
464     if (publishers == null) {
465       publishers = new ArrayList<String>();
466     }
467     publishers.add(publisher);
468   }
469 
470   /**
471    * Sets the list of publishers.
472    *
473    * @param publishers
474    *          the publishers for this event
475    */
476   public void setPublishers(List<String> publishers) {
477     this.publishers = publishers;
478   }
479 
480   /**
481    * Returns the series publishers.
482    *
483    * @return the publishers
484    */
485   public List<String> getPublishers() {
486     return publishers;
487   }
488 
489   /**
490    * Sets the series rights holder.
491    *
492    * @param rightsHolder
493    *          holder the rights holder
494    */
495   public void setRightsHolder(String rightsHolder) {
496     this.rightsHolder = rightsHolder;
497   }
498 
499   /**
500    * Returns the series rights holder.
501    *
502    * @return the rights holder
503    */
504   public String getRightsHolder() {
505     return rightsHolder;
506   }
507 
508   /**
509    * Sets the theme for this series
510    *
511    * @param theme
512    *          the theme
513    */
514   public void setTheme(Long theme) {
515     this.theme = theme;
516   }
517 
518   /**
519    * Returns the theme of this series
520    *
521    * @return the theme of this series
522    */
523   public Long getTheme() {
524     return theme;
525   }
526 
527   /**
528    * Sets the external metadata for a catalog type.
529    *
530    * @param type
531    *         The catalog type
532    * @param metadata
533    *         The metadata
534    */
535   public void setExtendedMetadata(String type, Map<String, List<String>> metadata) {
536     extendedMetadata.put(type, metadata);
537   }
538 
539   /**
540    * Removes the external metadata for a catalog type.
541    *
542    * @param type
543    *         The catalog type
544    */
545   public void removeExtendedMetadata(String type) {
546     extendedMetadata.remove(type);
547   }
548 
549   /**
550    * Removes all external metadata.
551    */
552   public void resetExtendedMetadata() {
553     extendedMetadata.clear();
554   }
555 
556   /**
557    * Returns the extended metadata
558    *
559    * @return the extended metadata in a map by catalog type
560    */
561   public Map<String, Map<String, List<String>>> getExtendedMetadata() {
562     return extendedMetadata;
563   }
564 
565   /**
566    * Reads the series from the input stream.
567    *
568    * @param xml
569    *          the input stream
570    * @param unmarshaller the unmarshaller to use
571    * @return the deserialized recording event
572    * @throws IOException
573    */
574   public static Series valueOf(InputStream xml, Unmarshaller unmarshaller) throws IOException {
575     try {
576       if (context == null) {
577         createJAXBContext();
578       }
579       return unmarshaller.unmarshal(XmlSafeParser.parse(xml), Series.class).getValue();
580     } catch (JAXBException e) {
581       throw new IOException(e.getLinkedException() != null ? e.getLinkedException() : e);
582     } catch (SAXException e) {
583       throw new IOException(e);
584     } finally {
585       IoSupport.closeQuietly(xml);
586     }
587   }
588 
589   /**
590    * Reads the series from the input stream.
591    *
592    * @param json
593    *          the input stream
594    * @return the deserialized recording event
595    * @throws JSONException
596    * @throws XMLStreamException
597    * @throws JAXBException
598    */
599   public static Series valueOfJson(InputStream json) throws IOException, JSONException, XMLStreamException,
600           JAXBException {
601     // TODO Get this to work, it is currently returning null properties for all properties.
602     if (context == null) {
603       createJAXBContext();
604     }
605 
606     BufferedReader streamReader = new BufferedReader(new InputStreamReader(json, "UTF-8"));
607     StringBuilder jsonStringBuilder = new StringBuilder();
608     String inputStr;
609     while ((inputStr = streamReader.readLine()) != null) {
610       jsonStringBuilder.append(inputStr);
611     }
612 
613     JSONObject obj = new JSONObject(jsonStringBuilder.toString());
614     Configuration config = new Configuration();
615     config.setSupressAtAttributes(true);
616     Map<String, String> xmlToJsonNamespaces = new HashMap<String, String>(1);
617     xmlToJsonNamespaces.put(IndexObject.INDEX_XML_NAMESPACE, "");
618     config.setXmlToJsonNamespaces(xmlToJsonNamespaces);
619     MappedNamespaceConvention con = new MappedNamespaceConvention(config);
620     Unmarshaller unmarshaller = context.createUnmarshaller();
621     // CHECKSTYLE:OFF
622     // the xml is parsed from json and should be safe
623     XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con);
624     Series event = (Series) unmarshaller.unmarshal(xmlStreamReader);
625     // CHECKSTYLE:ON
626     return event;
627   }
628 
629   /**
630    * Initialize the JAXBContext.
631    */
632   private static void createJAXBContext() throws JAXBException {
633     context = JAXBContext.newInstance(Series.class);
634   }
635 
636   /**
637    * Serializes the series.
638    *
639    * @return the serialized series
640    */
641   public String toJSON() {
642     try {
643       if (context == null) {
644         createJAXBContext();
645       }
646       Marshaller marshaller = Series.context.createMarshaller();
647 
648       Configuration config = new Configuration();
649       config.setSupressAtAttributes(true);
650       MappedNamespaceConvention con = new MappedNamespaceConvention(config);
651       StringWriter writer = new StringWriter();
652       XMLStreamWriter xmlStreamWriter = new MappedXMLStreamWriter(con, writer) {
653         @Override
654         public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
655           super.writeStartElement("", local, "");
656         }
657 
658         @Override
659         public void writeStartElement(String uri, String local) throws XMLStreamException {
660           super.writeStartElement("", local, "");
661         }
662 
663         @Override
664         public void setPrefix(String pfx, String uri) throws XMLStreamException {
665         }
666 
667         @Override
668         public void setDefaultNamespace(String uri) throws XMLStreamException {
669         }
670       };
671 
672       marshaller.marshal(this, xmlStreamWriter);
673       return writer.toString();
674     } catch (JAXBException e) {
675       throw new IllegalStateException(e.getLinkedException() != null ? e.getLinkedException() : e);
676     }
677   }
678 
679   /**
680    * Serializes the series to an XML format.
681    *
682    * @return A String with this series' content as XML.
683    */
684   public String toXML() {
685     try {
686       if (context == null) {
687         createJAXBContext();
688       }
689       StringWriter writer = new StringWriter();
690       Marshaller marshaller = Series.context.createMarshaller();
691       marshaller.marshal(this, writer);
692       return writer.toString();
693     } catch (JAXBException e) {
694       throw new IllegalStateException(e.getLinkedException() != null ? e.getLinkedException() : e);
695     }
696   }
697 
698 }