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 }