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.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 }