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  package org.opencastproject.playlists.serialization;
22  
23  import org.opencastproject.playlists.Playlist;
24  
25  import org.apache.commons.lang3.builder.EqualsBuilder;
26  import org.apache.commons.lang3.builder.HashCodeBuilder;
27  
28  import java.util.Collections;
29  import java.util.Date;
30  import java.util.List;
31  import java.util.Optional;
32  import java.util.stream.Collectors;
33  
34  import javax.xml.bind.Marshaller;
35  import javax.xml.bind.annotation.XmlAccessType;
36  import javax.xml.bind.annotation.XmlAccessorType;
37  import javax.xml.bind.annotation.XmlAttribute;
38  import javax.xml.bind.annotation.XmlElement;
39  import javax.xml.bind.annotation.XmlRootElement;
40  import javax.xml.bind.annotation.XmlType;
41  import javax.xml.bind.annotation.adapters.XmlAdapter;
42  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
43  
44  /** 1:1 serialization of a {@link Playlist}. Intended for endpoints. */
45  @XmlAccessorType(XmlAccessType.FIELD)
46  @XmlType(name = "playlist", namespace = "http://playlist.opencastproject.org")
47  @XmlRootElement(name = "playlist", namespace = "http://playlist.opencastproject.org")
48  public class JaxbPlaylist {
49  
50    static class DateAdapter extends XmlAdapter<Long, Date> {
51      /**
52       * {@inheritDoc}
53       *
54       * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
55       */
56      @Override
57      public Long marshal(Date v) throws Exception {
58        return v == null ? null : v.getTime();
59      }
60  
61      /**
62       * {@inheritDoc}
63       *
64       * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
65       */
66      @Override
67      public Date unmarshal(Long v) throws Exception {
68        return v == null ? null : new Date(v);
69      }
70    }
71  
72    @XmlAttribute()
73    private String id;
74  
75    @XmlElement(name = "organization")
76    private String organization;
77  
78    private List<JaxbPlaylistEntry> entries;
79  
80    @XmlElement(name = "title")
81    private String title;
82  
83    @XmlElement(name = "description")
84    private String description;
85  
86    @XmlElement(name = "creator")
87    private String creator;
88  
89    @XmlJavaTypeAdapter(JaxbPlaylist.DateAdapter.class)
90    @XmlElement
91    private Date updated;
92  
93    private List<JaxbPlaylistAccessControlEntry> accessControlEntries;
94  
95    void beforeMarshal(Marshaller u) {
96      // Explicitly set empty lists to `null`. This is to avoid having an empty list wrongly show up in a JSON
97      // serialization with the value of an empty string
98      if (entries != null && entries.isEmpty()) {
99        entries = null;
100     }
101     if (accessControlEntries != null && accessControlEntries.isEmpty()) {
102       accessControlEntries = null;
103     }
104   }
105 
106   /**
107    * Default no-arg constructor needed by JAXB
108    */
109   public JaxbPlaylist() {
110   }
111 
112   public JaxbPlaylist(Playlist playlist) {
113     this();
114     this.id = playlist.getId();
115     this.organization = playlist.getOrganization();
116     this.entries = playlist.getEntries()
117         .stream()
118         .map(JaxbPlaylistEntry::new)
119         .collect(Collectors.toList());
120     this.title = playlist.getTitle();
121     this.description = playlist.getDescription();
122     this.creator = playlist.getCreator();
123     this.updated = playlist.getUpdated();
124     this.accessControlEntries = playlist.getAccessControlEntries()
125         .stream()
126         .map(JaxbPlaylistAccessControlEntry::new)
127         .collect(Collectors.toList());
128   }
129 
130   public Playlist toPlaylist() {
131     return new Playlist(
132         id,
133         organization,
134         Optional.ofNullable(entries)
135             .orElseGet(Collections::emptyList)
136             .stream()
137             .map(JaxbPlaylistEntry::toPlaylistEntry)
138             .collect(Collectors.toList()),
139         title,
140         description,
141         creator,
142         updated,
143         Optional.ofNullable(accessControlEntries)
144             .orElseGet(Collections::emptyList)
145             .stream()
146             .map(JaxbPlaylistAccessControlEntry::toPlaylistAccessControlEntry)
147             .collect(Collectors.toList())
148 
149     );
150   }
151 
152   public List<JaxbPlaylistEntry> getEntries() {
153     return entries;
154   }
155 
156   public void setEntries(List<JaxbPlaylistEntry> entries) {
157     for (var entry : entries) {
158       if (!this.entries.contains(entry)) {
159         entry.setId(0L);
160       }
161     }
162 
163     this.entries = entries;
164   }
165 
166   @Override
167   public boolean equals(Object o) {
168     if (this == o) {
169       return true;
170     }
171 
172     if (o == null || getClass() != o.getClass()) {
173       return false;
174     }
175 
176     JaxbPlaylist jaxbPlaylist = (JaxbPlaylist) o;
177 
178     return new EqualsBuilder()
179         .append(id, jaxbPlaylist.id)
180         .append(organization, jaxbPlaylist.organization)
181         .append(entries, jaxbPlaylist.entries)
182         .append(title, jaxbPlaylist.title)
183         .append(description, jaxbPlaylist.description)
184         .append(creator, jaxbPlaylist.creator)
185         .append(updated, jaxbPlaylist.updated)
186         .append(accessControlEntries, jaxbPlaylist.accessControlEntries)
187         .isEquals();
188   }
189 
190   @Override
191   public int hashCode() {
192     return new HashCodeBuilder(17, 37)
193         .append(id)
194         .append(organization)
195         .append(entries)
196         .append(title)
197         .append(description)
198         .append(creator)
199         .append(updated)
200         .append(accessControlEntries)
201         .toHashCode();
202   }
203 }