View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.creadur.whisker.model;
20  
21  import java.util.Collection;
22  import java.util.Map;
23  import java.util.Set;
24  
25  /**
26   * High level description of licensing qualities.
27   */
28  public class Descriptor {
29  
30      /** Principle license for main work. */
31      private final License primaryLicense;
32      /** Optional additional primary copyright notice*/
33      private final String primaryCopyrightNotice;
34      /** Individual or group with main responsible for main work. */
35      private final String primaryOrganisationId;
36      /** A NOTICE for the main work, for inclusion alongside the LICENSE. */
37      private final String primaryNotice;
38      /** License meta-data, indexed by id. */
39      private final Map<String, License> licenses;
40      /** Organisation meta-data, indexed by id */
41      private final Map<String, Organisation> organisations;
42      /** Notice meta-data, indexed by id. */
43      private final Map<String, String> notices;
44      /** Directories expected to be contained within the release. */
45      private final Collection<WithinDirectory> contents;
46  
47  
48      /**
49       * Constructs a description of the expected licensing qualities of a
50       * distribution, with no additional primary copyright notice.
51       *
52       * @param primaryLicense
53       *            not null
54       * @param primaryOrganisationId
55       *            not null
56       * @param primaryNotice
57       *            possibly null
58       * @param licenses
59       *            not null, possibly empty
60       * @param notices
61       *            not null, possibly empty
62       * @param organisations
63       *            not null, possibly empty
64       * @param contents
65       *            not null, possibly empty
66       */
67      public Descriptor(final License primaryLicense,
68              final String primaryOrganisationId,
69              final String primaryNotice,
70              final Map<String, License> licenses,
71              final Map<String, String> notices,
72              final Map<String, Organisation> organisations,
73              final Collection<WithinDirectory> contents) {
74          this(   primaryLicense,
75                  null,
76                  primaryOrganisationId,
77                  primaryNotice,
78                  licenses,
79                  notices,
80                  organisations,
81                  contents);
82      }
83  
84      /**
85       * Constructs a description of the expected licensing qualities of a
86       * distribution, with a primary additional copyright notice.
87       *
88       * @param primaryLicense
89       *            not null
90       * @param primaryCopyrightNotice
91       *            optional primary copyright notice, possibly null
92       *
93       * @param primaryOrganisationId
94       *            not null
95       * @param primaryNotice
96       *            possibly null
97       * @param licenses
98       *            not null, possibly empty
99       * @param notices
100      *            not null, possibly empty
101      * @param organisations
102      *            not null, possibly empty
103      * @param contents
104      *            not null, possibly empty
105      */
106     public Descriptor(final License primaryLicense,
107             final String primaryCopyrightNotice,
108             final String primaryOrganisationId,
109             final String primaryNotice,
110             final Map<String, License> licenses,
111             final Map<String, String> notices,
112             final Map<String, Organisation> organisations,
113             final Collection<WithinDirectory> contents) {
114         super();
115         this.primaryLicense = primaryLicense;
116         this.primaryCopyrightNotice = primaryCopyrightNotice;
117         this.primaryOrganisationId = primaryOrganisationId;
118         this.primaryNotice = primaryNotice;
119         this.licenses = licenses;
120         this.notices = notices;
121         this.organisations = organisations;
122         this.contents = contents;
123     }
124 
125     /**
126      * Gets an additional copyright notice needed
127      * for some primary licenses.
128      * @return optional primary copyright notice,
129      * possibly null
130      */
131     public String getPrimaryCopyrightNotice() {
132         return primaryCopyrightNotice;
133     }
134 
135     /**
136      * Is there a primary copyright notice?
137      * @return true if a primary copyright notice
138      * has been set, false otherwise
139      */
140     public boolean isPrimaryCopyrightNotice() {
141         return primaryCopyrightNotice != null;
142     }
143 
144     /**
145      * Gets the principle NOTICE for the main work.
146      *
147      * @return the primaryNotice
148      */
149     public String getPrimaryNotice() {
150         return this.primaryNotice;
151     }
152 
153     /**
154      * Collates NOTICE meta-data for resources.
155      *
156      * @return not null, possibly empty
157      */
158     public Map<String, Collection<Resource>> getResourceNotices() {
159         final NoticeCollator collator = new NoticeCollator();
160         traverse(collator);
161         return collator.resourceNotices(this.notices);
162     }
163 
164     /**
165      * Gets the organisations described.
166      * @return organisations indexed by id, not null
167      */
168     public Map<String, Organisation> getOrganisations() {
169         return organisations;
170     }
171 
172     /**
173      * Collates NOTICE meta-data not linked to any resource.
174      *
175      * @return not null, possibly empty
176      */
177     public Set<String> getOtherNotices() {
178         final NoticeCollator collator = new NoticeCollator();
179         traverse(collator);
180         return collator.notices(this.notices);
181     }
182 
183     /**
184      * Gets the license with the given id.
185      *
186      * @param id
187      *            not null
188      * @return the license with the given id, or null
189      */
190     public License license(final String id) {
191         return this.licenses.get(id);
192     }
193 
194     /**
195      * Gets the principle license under which the work is licensed.
196      *
197      * @return the principle license, not null
198      */
199     public License getPrimaryLicense() {
200         return this.primaryLicense;
201     }
202 
203     /**
204      * Gets the contents expected in the distribution.
205      *
206      * @return not null, possibly null
207      */
208     public Collection<WithinDirectory> getContents() {
209         return this.contents;
210     }
211 
212     /**
213      * Is the given license the principle license for the main work?
214      *
215      * @param license
216      *            not null
217      * @return true when the given license is the primary license, not null
218      */
219     public boolean isPrimary(final License license) {
220         return this.primaryLicense.equals(license);
221     }
222 
223     /**
224      * Is the given individual or group the principle organisation with
225      * responsibility for the main work.
226      *
227      * @param byOrganisation
228      *            not null
229      * @return true when the given organisation is primary
230      */
231     public boolean isPrimary(final ByOrganisation byOrganisation) {
232         return byOrganisation.getId().equals(this.primaryOrganisationId);
233     }
234 
235     /**
236      * Is this collection of resources expected to contain only material
237      * licensed under the primary license by the
238      * primary organisation with the primary copyright notice?
239      *
240      * @param contentElement
241      *            not null
242      * @return true when the contents are all licensed under the primary license
243      *         by the primary organisation
244      */
245     public boolean isOnlyPrimary(final ContentElement contentElement) {
246         final NoCopyrightNoticeVerifier verifier = new NoCopyrightNoticeVerifier();
247         final LicenseAndOrganisationCollator collator = new LicenseAndOrganisationCollator();
248         contentElement.accept(collator);
249         contentElement.accept(verifier);
250         return collator.isOnlyLicense(getPrimaryLicense())
251                 && collator.isOnlyOrganisation(this.primaryOrganisationId)
252                 && !verifier.isCopyrightNoticePresent();
253     }
254 
255     /**
256      * Traverses the content directories.
257      *
258      * @param visitor
259      *            possibly null
260      */
261     public void traverse(final Visitor visitor) {
262         for (final WithinDirectory directory : getContents()) {
263             directory.accept(visitor);
264         }
265     }
266 
267     /**
268      * Traverses the given directory.
269      *
270      * @param visitor
271      *            possibly null
272      * @param directoryName
273      *            not null
274      */
275     public void traverseDirectory(final Visitor visitor,
276             final String directoryName) {
277         for (final WithinDirectory directory : getContents()) {
278             if (directory.isNamed(directoryName)) {
279                 directory.accept(visitor);
280             }
281         }
282     }
283 
284     /**
285      * Is a NOTICE document required?
286      *
287      * @return true when a NOTICE is required, false otherwise
288      */
289     public boolean isNoticeRequired() {
290         return primaryNoticeExists() || resourceNoticesExist();
291     }
292 
293     /**
294      * Does any resource have a required notice?
295      *
296      * @return true when at least one required third party notice exists, false
297      *         otherwise
298      */
299     public boolean resourceNoticesExist() {
300         return !getResourceNotices().isEmpty();
301     }
302 
303     /**
304      * Does the work described have a primary notice?
305      *
306      * @return true unless the primary notice is null or whitespace
307      */
308     public boolean primaryNoticeExists() {
309         return (this.primaryNotice != null)
310                 && !"".equals(this.primaryNotice.trim());
311     }
312 
313     /**
314      * Is this the work of the primary organisation only?
315      *
316      * @return true when no third party resources are contained, false when
317      *         third party resources exist. In particular, true when
318      *         contents are empty.
319      */
320     public boolean isPrimaryOnly() {
321         final boolean result;
322         if (contents.size() > 0) {
323             final LicenseAndOrganisationCollator collator = new LicenseAndOrganisationCollator();
324             for (final WithinDirectory directory : contents) {
325                 directory.accept(collator);
326             }
327             result = collator.isOnlyOrganisation(primaryOrganisationId);
328         } else {
329             result = true;
330         }
331         return result;
332     }
333 }