View Javadoc

1   /***
2    * Copyright 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * For more information visit
11   *         http://72miles.com and
12   *         http://architecturerules.googlecode.com/svn/docs/index.html
13   */
14  
15  package com.seventytwomiles.architecturerules.domain;
16  
17  
18  import com.seventytwomiles.architecturerules.configuration.ConfigurationFactory;
19  import com.seventytwomiles.architecturerules.exceptions.SourceNotFoundException;
20  import junit.framework.Assert;
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  import java.io.File;
25  import java.text.CharacterIterator;
26  import java.text.StringCharacterIterator;
27  
28  
29  
30  /***
31   * <p>Representation of a source directory to search for packages and .class
32   * files in.</p>
33   *
34   * @author mikenereson
35   */
36  public class SourceDirectory {
37  
38  
39      protected static final Log log = LogFactory.getLog(SourceDirectory.class);
40  
41      /***
42       * <p>The value, which is set inside of the xml configuration file, which
43       * indicates that when a source directory is not found, the source directory
44       * should be ignored.</p>
45       *
46       * @parameter NOT_FOUND_IGNORE String
47       */
48      private static final String NOT_FOUND_IGNORE = "ignore";
49  
50  
51      /***
52       * <p>The value, which is set inside of the xml configuration file, which
53       * indicates that when a source directory is not found, that an exception
54       * should be thrown.</p>
55       *
56       * <p>When {@link #setNotFound(String)} is set to this value, a {@link
57       * SourceNotFoundException} will be thrown.</p>
58       *
59       * @parameter NOT_FOUND_EXCEPTION String
60       */
61      private static final String NOT_FOUND_EXCEPTION = "exception";
62  
63      /***
64       * <p>When true, if this source {@link #path} is not found a
65       * <code>SourceNotFoundException</code> will be thrown.</p>
66       *
67       * * <p>If the value is not provided in the configuration, the default value
68       * is used. {@link ConfigurationFactory#DEFAULT_CYCLICAL_DEPENDENCY_CONFIGURATION_VALUE}</p>
69       *
70       * @parameter shouldThrowExceptionWhenNotFound boolean
71       */
72      private boolean shouldThrowExceptionWhenNotFound
73              = ConfigurationFactory.DEFAULT_NO_PACKAGES_CONFIGURATION_BOOLEAN_VALUE;
74  
75      /***
76       * <p>Relative url to the path to search in for .class files.</p>
77       *
78       * @parameter path String
79       */
80      private String path;
81  
82      /***
83       * <p>Holds the value in the xml configuration for the not-found
84       * property.</p>
85       *
86       * @parameter notFound String
87       * @noinspection UnusedDeclaration
88       */
89      private String notFound;
90  
91  
92      /***
93       * <p>Instantiates a new SourceDirectory entity.</p>
94       */
95      public SourceDirectory() {
96      }
97  
98  
99      /***
100      * <p>Instantiates a new SourceDirectory with the given <tt>path</tt></p>
101      *
102      * @param path String {@link #path}
103      */
104     public SourceDirectory(final String path) {
105 
106         setPath(path);
107     }
108 
109 
110     /***
111      * <p>Instantiates a new SourceDirectory with the given <tt>path</tt> and
112      * <tt>shouldThrowExceptionWhenNotFound</tt> values</p>
113      *
114      * @param path String {@link #path}
115      * @param shouldThrowExceptionWhenNotFound boolean {@link
116      * #shouldThrowExceptionWhenNotFound}
117      */
118     public SourceDirectory(final String path,
119                            final boolean shouldThrowExceptionWhenNotFound) {
120 
121         setShouldThrowExceptionWhenNotFound(shouldThrowExceptionWhenNotFound);
122         setPath(path);
123     }
124 
125 
126     /***
127      * Setter for property {@link #shouldThrowExceptionWhenNotFound}.
128      *
129      * @param shouldThrowExceptionWhenNotFound Value to set for property
130      * <tt>shouldThrowExceptionWhenNotFound</tt>.
131      */
132     public void setShouldThrowExceptionWhenNotFound(
133             final boolean shouldThrowExceptionWhenNotFound) {
134 
135         /***
136          * Update notFound property so that the String value and boolean
137          * values coincide
138          */
139         if (shouldThrowExceptionWhenNotFound) {
140 
141             notFound = NOT_FOUND_EXCEPTION;
142 
143         } else {
144 
145             notFound = NOT_FOUND_IGNORE;
146         }
147 
148         this.shouldThrowExceptionWhenNotFound
149                 = shouldThrowExceptionWhenNotFound;
150     }
151 
152 
153     /***
154      * <p>Instantiates a new SourceDirectory with the given <tt>path</tt> and
155      * <tt>notFound</tt> values.</p>
156      *
157      * @param path String {@link #path}
158      * @param notFound boolean {@link @notFound}
159      */
160     public SourceDirectory(final String path, final String notFound) {
161 
162         setPath(path);
163         setNotFound(notFound);
164     }
165 
166 
167     /***
168      * Setter for property 'notFound'.
169      *
170      * @param notFound Value to set for property 'notFound'.
171      */
172     public void setNotFound(String notFound) {
173 
174         /***
175          * When null, set to "null" so that the exception message that is about
176          * to be thrown is meaningful.
177          */
178         if (notFound == null)
179             notFound = "null";
180 
181         /***
182          * Validate input.
183          * Expect either 'ignore' or 'exception'
184          */
185         if (!(notFound.equalsIgnoreCase(NOT_FOUND_IGNORE) ||
186                 notFound.equalsIgnoreCase(NOT_FOUND_EXCEPTION))) {
187 
188             throw new IllegalArgumentException(
189                     String.format("'not-found' property of '%s' is invalid. " +
190                             "valid values are %s and %s",
191                             notFound, NOT_FOUND_IGNORE, NOT_FOUND_EXCEPTION));
192         }
193 
194         this.notFound = notFound;
195 
196         /***
197          * Update shouldThrowExceptionWhenNotFound property so that the
198          * String value and boolean values coincide
199          */
200         final boolean shouldThrowException
201                 = getNotFound().equalsIgnoreCase(NOT_FOUND_EXCEPTION);
202 
203         setShouldThrowExceptionWhenNotFound(shouldThrowException);
204     }
205 
206 
207     private String getNotFound() {
208 
209         return this.notFound;
210     }
211 
212 
213     /***
214      * <p>Getter for property {@link #path}.</p>
215      *
216      * @return Value for property <tt>path</tt>.
217      */
218     public String getPath() {
219 
220         return this.path;
221     }
222 
223 
224     /***
225      * <p>Setter for property {@link #path}.</p>
226      *
227      * @param path Value to set for property <tt>path</tt>.
228      */
229     public void setPath(final String path) {
230 
231         try {
232 
233             Assert.assertNotNull(path);
234             Assert.assertFalse("".equals(path));
235 
236         } catch (final Throwable e) {
237 
238             throw new IllegalArgumentException(e.getMessage());
239         }
240 
241         this.path = replaceBackslashForOS(path);
242     }
243 
244 
245     /***
246      * <p>Replaces inappropriate backslash with the appropriate slash based on
247      * the operating system's requirements</p>
248      *
249      * <p>For example, on a Windows system, <tt>src/main/resources</tt> becomes
250      * <tt>src//main//resource</tt></p>
251      *
252      * <p>TODO: this may be able to be replaced with String.replaceAll, but I
253      * couldn't get the regex just right</p>
254      *
255      * <p>This todo/issue is open at <a href="http://code.google.com/p/architecturerules/issues/detail?id=29">issue
256      * 29</a></p>
257      *
258      * @param path String the path to fix
259      * @return String the fixed path
260      */
261     String replaceBackslashForOS(final String path) {
262 
263         final StringBuffer result = new StringBuffer();
264 
265         final StringCharacterIterator iterator
266                 = new StringCharacterIterator(path);
267 
268         char character = iterator.current();
269 
270         final char goal = File.separator.toCharArray()[0];
271         final char target = (goal == '//' ? '/' : '//');
272 
273         while (character != CharacterIterator.DONE) {
274 
275             result.append(character == target ? goal : character);
276             character = iterator.next();
277         }
278 
279         return result.toString();
280     }
281 
282 
283     /***
284      * @see Object#equals(Object)
285      */
286     @Override
287     public boolean equals(final Object object) {
288 
289         if (this == object)
290             return true;
291 
292         if (object == null)
293             return false;
294 
295         if (!(object instanceof SourceDirectory))
296             return false;
297 
298         final SourceDirectory that = (SourceDirectory) object;
299 
300         if (path != null
301                 ? !path.equals(that.getPath())
302                 : that.getPath() != null) {
303 
304             return false;
305         }
306 
307         return true;
308     }
309 
310 
311     /***
312      * @see Object#hashCode()
313      */
314     @Override
315     public int hashCode() {
316 
317         return (this.path != null ? this.path.hashCode() : 0);
318     }
319 
320 
321     /***
322      * @see Object#toString()
323      */
324     @Override
325     public String toString() {
326 
327         return this.path;
328     }
329 
330 
331     /***
332      * Getter for property {@link #shouldThrowExceptionWhenNotFound}.
333      *
334      * @return Value for property <tt>shouldThrowExceptionWhenNotFound</tt>.
335      */
336     public boolean shouldThrowExceptionWhenNotFound() {
337 
338         return this.shouldThrowExceptionWhenNotFound;
339     }
340 }