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.configuration;
16
17
18 import com.seventytwomiles.architecturerules.domain.JPackage;
19 import com.seventytwomiles.architecturerules.domain.Rule;
20 import com.seventytwomiles.architecturerules.domain.SourceDirectory;
21 import junit.framework.Assert;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 import java.util.Collection;
26 import java.util.HashSet;
27
28
29
30 /***
31 * <p>An instance of <code>Configuration</code> allows the application to
32 * specifiy where the source directories are, what rules to test against and
33 * under what conditions should an <code>Exception</code> be thrown.</p>
34 *
35 * <p>This <code>Configuration</code> may be loaded by configuration from an XML
36 * file in the classpath, through programmatic configuration, or both.</p>
37 *
38 * @author mikenereson
39 * @see ConfigurationFactory
40 * @see UnmodifiableConfiguration
41 */
42 public class Configuration {
43
44
45 protected static final Log log = LogFactory.getLog(Configuration.class);
46
47 /***
48 * <p><code>Rules</code> that are read from the configuration file or added
49 * programatically.</p>
50 *
51 * @parameter rules Set
52 */
53 private final Collection<Rule> rules = new HashSet<Rule>();
54
55 /***
56 * <p>List of <code>SourceDirectory</code> that are read from the
57 * configuration file and or added programatically.</p>
58 *
59 * @parameter sources List
60 */
61 private final Collection<SourceDirectory> sources
62 = new HashSet<SourceDirectory>();
63
64 /***
65 * <p>sets to true when <samp><sources no-packages="exception"></samp>,
66 * false when <samp><sources no-packages="ignore"></samp></p>
67 *
68 * @parameter throwExceptionWhenNoPackages boolean
69 */
70 private boolean throwExceptionWhenNoPackages;
71
72 /***
73 * <p>sets to true when <samp><cyclicalDependency test="true"/> </samp>,
74 * false when <samp><cyclicalDependency test="false"/> </samp></p>
75 *
76 * @parameter doCyclicDependencyTest boolean
77 */
78 private boolean doCyclicDependencyTest;
79
80
81 /***
82 * <p>Getter for property {@link #rules}.</p>
83 *
84 * @return Value for property <tt>rules</tt>.
85 */
86 public Collection<Rule> getRules() {
87 return this.rules;
88 }
89
90
91 /***
92 * <p>Getter for property {@link #sources}.</p>
93 *
94 * @return Value for property <tt>sources</tt>.
95 */
96 public Collection<SourceDirectory> getSources() {
97 return this.sources;
98 }
99
100
101 /***
102 * <p>Setter for property {@link #doCyclicDependencyTest}.</p>
103 *
104 * @param doCyclicDependencyTest Value to set for property
105 * <tt>doCyclicDependencyTest</tt>.
106 * @return Configuration this <code>Configuration</code> which allows for
107 * method chaining
108 */
109 public Configuration setDoCyclicDependencyTest(
110 final boolean doCyclicDependencyTest) {
111
112 this.doCyclicDependencyTest = doCyclicDependencyTest;
113
114 return this;
115 }
116
117
118 /***
119 * <p>Setter for property {@link #throwExceptionWhenNoPackages}.</p>
120 *
121 * @param throwExceptionWhenNoPackages Value to set for property
122 * <tt>throwExceptionWhenNoPackages</tt>.
123 * @return Configuration this <code>Configuration</code> which allows for
124 * method chaining
125 */
126 public Configuration setThrowExceptionWhenNoPackages(
127 final boolean throwExceptionWhenNoPackages) {
128
129 this.throwExceptionWhenNoPackages = throwExceptionWhenNoPackages;
130
131 return this;
132 }
133
134
135 /***
136 * <p>Add a new <code>Rule</code> to {@link #rules}</p>
137 *
138 * @param rule Rule to add
139 * @return Configuration this <code>Configuration</code> to allow for method
140 * chaining.
141 */
142 public Configuration addRule(final Rule rule) {
143
144
145 Assert.assertNotNull("rule can not be null", rule);
146
147 Assert.assertNotNull("rule id can not be null", rule.getId());
148
149 final String id = rule.getId();
150 Assert.assertFalse("rule id must not be empty", id.equals(""));
151
152 final Collection<JPackage> packages = rule.getPackages();
153 Assert.assertNotNull("rule packages can not be null", packages);
154
155 Assert.assertFalse("rule packages must not be empty",
156 rule.getPackages().isEmpty());
157
158 Assert.assertFalse("rule violations must not be empty",
159 rule.getViolations().isEmpty());
160
161 final boolean added = rules.add(rule);
162
163 if (added) {
164
165 log.debug(String.format("added Rule %s to Configuration", id));
166
167 } else {
168
169 log.debug(String.format("failed to add Rule %s to Configuration",
170 id));
171 }
172
173 return this;
174 }
175
176
177 /***
178 * <p>Add a new <code>SourceDirectory</code> to {@link #sources}</p>
179 *
180 * @param sourceDirectory SourceDirectory to add
181 * @return Configuration this <code>Configuration</code> to allow for method
182 * chaining.
183 */
184 public Configuration addSource(final SourceDirectory sourceDirectory) {
185
186 if (sourceDirectory == null)
187 throw new IllegalArgumentException(
188 "sourceDirectory can not be null");
189
190 final String path = sourceDirectory.getPath();
191
192 if (path == null || path.equals(""))
193 throw new IllegalArgumentException(
194 "sourceDirectory.path can not be empty or null");
195
196 final boolean added = sources.add(sourceDirectory);
197
198 if (added) {
199
200 log.debug(String.format("added source %s to Configuration", path));
201
202 } else {
203
204 log.debug(String.format("failed to add source %s to Configuration",
205 path));
206 }
207
208 return this;
209 }
210
211
212 /***
213 * <p>Getter for property {@link #doCyclicDependencyTest}.</p>
214 *
215 * @return Value for property <tt>doCyclicDependencyTest</tt>.
216 */
217 public boolean shouldDoCyclicDependencyTest() {
218 return doCyclicDependencyTest;
219 }
220
221
222 /***
223 * <p> Getter for property {@link #throwExceptionWhenNoPackages}.</p>
224 *
225 * @return Value for property <tt>throwExceptionWhenNoPackages</tt>.
226 */
227 public boolean shouldThrowExceptionWhenNoPackages() {
228 return throwExceptionWhenNoPackages;
229 }
230 }