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.Collections;
23 import java.util.Map;
24 import java.util.Set;
25
26 /**
27 * Describes a software license.
28 */
29 public class License implements Comparable<License> {
30
31 /**
32 * Is information about source distribution required
33 * by this license?
34 */
35 private final boolean isSourceRequired;
36 /** Template for license wording. */
37 private final String baseText;
38 /** Parameters expected by the template. */
39 private final Collection<String> expectedParameters;
40 /** Identifies this license. */
41 private final String id;
42 /** Canonical locator for this license. */
43 private final String url;
44 /** Names this license */
45 private final String name;
46
47 /**
48 * Constructs meta-data for a family of licenses.
49 * @param isSourceRequired true if this license requires
50 * information about source distribution to be included
51 * within the distribution
52 * @param baseText a template for the legal text, not null
53 * @param expectedParameters not null
54 * @param id not null
55 * @param url not null
56 * @param name not null
57 */
58 public License(final boolean isSourceRequired, final String baseText,
59 final Collection<String> expectedParameters, final String id,
60 final String url, final String name) {
61 super();
62 this.isSourceRequired = isSourceRequired;
63 this.baseText = baseText;
64 this.expectedParameters = Collections
65 .unmodifiableCollection(expectedParameters);
66 this.id = id;
67 this.url = url;
68 this.name = name;
69 }
70
71 /**
72 * Is source information inclusion required by this
73 * license?
74 * @return true when information about the source
75 * should be included, false otherwise
76 */
77 public boolean isSourceRequired() {
78 return this.isSourceRequired;
79 }
80
81 /**
82 * Gets legal text expressing this license.
83 * @return not null
84 * @throws LicenseTemplateException when the text cannot
85 * be created from the template
86 */
87 public String getText() throws LicenseTemplateException {
88 return getText(null);
89 }
90
91 /**
92 * Gets legal text expressing this license,
93 *
94 * @param parameters possibly null
95 * @return not null
96 * @throws LicenseTemplateException when the text cannot
97 * be created from the template
98 */
99 public String getText(final Map<String, String> parameters)
100 throws LicenseTemplateException {
101 return substituteInto(validate(parameters), this.baseText);
102 }
103
104 /**
105 * Gets parameters required by the template
106 * to generate a instance of this license family.
107 * @return not null, possibly empty
108 */
109 public Collection<String> getExpectedParameters() {
110 return this.expectedParameters;
111 }
112
113 /**
114 * Validates that these given parameters
115 * are suitable for the template expressing the legalise.
116 * @param parameters possibly null
117 * @return parameters, not null
118 * @throws LicenseTemplateException when the parameter
119 * do not fulfill the expectations of the template
120 */
121 @SuppressWarnings("unchecked")
122 private Map<String, String> validate(final Map<String, String> parameters)
123 throws LicenseTemplateException {
124 if (parameters == null) {
125 return validate(Collections.EMPTY_MAP);
126 }
127
128 if (this.expectedParameters.isEmpty() && parameters != null
129 && !parameters.isEmpty()) {
130 throw LicenseTemplateException.notLicenseTemplate(parameters,
131 getName());
132 }
133
134 if (!parametersMatch(parameters, this.expectedParameters)) {
135 throw LicenseTemplateException.parameterMismatch(
136 this.expectedParameters, parameters.keySet(), getName());
137 }
138
139 return parameters;
140 }
141
142 /**
143 * Do the presented parameters fulfill expectations?
144 * @param parameters possibly null
145 * @param expectedParameters possibly null
146 * @return true when expected and presented parameters
147 * match, false otherwise
148 */
149 private boolean parametersMatch(final Map<String, String> parameters,
150 final Collection<String> expectedParameters) {
151 final Set<String> keySet = parameters.keySet();
152 return keySet.containsAll(expectedParameters) && expectedParameters
153 .containsAll(keySet);
154 }
155
156 /**
157 * Translates a parameter name to
158 * the variable style used by the template
159 * @param parameterName not null
160 * @return variable in template format, not null
161 */
162 private String variable(final String parameterName) {
163 return "${" + parameterName + "}";
164 }
165
166 /**
167 * Substitutes parameter values into the variable
168 * in the template legalise, parameterising
169 * an instance of the license family.
170 * @param parameters not null
171 * @param text template text
172 * @return not null
173 */
174 private String substituteInto(final Map<String, String> parameters,
175 final String text) {
176 String result = text;
177 for (final Map.Entry<String, String> entry : parameters.entrySet()) {
178 result = result.replace(variable(entry.getKey()), entry.getValue());
179 }
180 return result;
181 }
182
183 /**
184 * Stores the license by its id.
185 * @param map not null
186 * @return the license stored
187 */
188 public License storeIn(final Map<String, License> map) {
189 map.put(getId(), this);
190 return this;
191 }
192
193 /**
194 * Gets the unique identifier for this license.
195 * @return not null
196 */
197 public String getId() {
198 return this.id;
199 }
200
201 /**
202 * Gets a locator for this license.
203 * @return not null
204 */
205 public String getURL() {
206 return this.url;
207 }
208
209 /**
210 * Gets a name for this license suitable for
211 * display.
212 * @return not null
213 */
214 public String getName() {
215 return this.name;
216 }
217
218 /**
219 * @see java.lang.Object#hashCode()
220 */
221 @Override
222 public int hashCode() {
223 return getId().hashCode();
224 }
225
226 /**
227 * @see java.lang.Object#equals(java.lang.Object)
228 */
229 @Override
230 public boolean equals(final Object obj) {
231 if (this == obj) {
232 return true;
233 }
234 if (obj == null) {
235 return false;
236 }
237 if (getClass() != obj.getClass()) {
238 return false;
239 }
240 final License other = (License) obj;
241 return getId().equals(other);
242 }
243
244 /**
245 * @see java.lang.Comparable#compareTo(java.lang.Object)
246 */
247 public int compareTo(final License other) {
248 final int nameDifference = getName().compareTo(other.getName());
249 return nameDifference == 0 ? getId().compareTo(other.getId())
250 : nameDifference;
251 }
252
253 @Override
254 public String toString() {
255 return "License [id=" + this.id + ", name=" + this.name + "]";
256 }
257
258 }