1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package nl.toolforge.karma.core.module;
20
21 import nl.toolforge.karma.core.Version;
22 import nl.toolforge.karma.core.location.Location;
23 import nl.toolforge.karma.core.module.template.ModuleLayoutTemplate;
24 import nl.toolforge.karma.core.vc.AuthenticationException;
25 import nl.toolforge.karma.core.vc.Authenticator;
26 import nl.toolforge.karma.core.vc.DevelopmentLine;
27 import nl.toolforge.karma.core.vc.VersionControlException;
28
29 import java.io.File;
30 import java.util.Set;
31 import java.util.regex.PatternSyntaxException;
32
33
34 /***
35 * <p>A module is a collection of files, representing some block of functionality. This definition is probably highly
36 * subjective, but for Karma, that's what it is. A module is part of a container, called a
37 * <code>Manifest</code>. System's theory tells us that a system is separated into subsystems. Well, that's what we
38 * do in the Karma context as well. An application system consists of one or more (generally more) modules.</p>
39 *
40 * <p>Karma <code>Module</code>s are maintained in a version management system and grouped together in a
41 * <code>Manifest</code>. The manifest is managing the modules.</p>
42 *
43 * @author D.A. Smedes
44 * @version $Id: Module.java,v 1.1 2004/11/10 22:25:11 hippe Exp $
45 */
46 public interface Module {
47
48 /***
49 * <code>UNKNOWN</code> applies to module which have no local presence. The actual type can only be determined when
50 * the <code>module-descriptor.xml</code> file is available, which is the case after a checkout of the module.
51 */
52 public static final Type UNKNOWN = new Type("UNKNOWN");
53 /***
54 * Represents <code><type>LIBRARY_MODULE</type></code>.
55 */
56 public static final Type LIBRARY_MODULE = new Type("LIBRARY-MODULE");
57 /***
58 * Represents <code><type>JAVA_SOURCE_MODULE</type></code>.
59 */
60 public static final Type JAVA_SOURCE_MODULE = new Type("JAVA-SOURCE-MODULE");
61 /***
62 * Represents <code><type>JAVA_WEB_APPLICATION</type></code>.
63 */
64 public static final Type JAVA_WEB_APPLICATION = new Type("JAVA-WEB-APPLICATION");
65 /***
66 * Represents <code><type>OTHER-MODULE</type></code>.
67 */
68 public static final Type OTHER_MODULE = new Type("OTHER-MODULE");
69
70 /***
71 * Represents <code><type>JAVA_ENTERPRISE_APPLICATION</type></code>.
72 */
73 public static final Type JAVA_ENTERPRISE_APPLICATION = new Type("JAVA-ENTERPRISE-APPLICATION");
74
75 public static final State WORKING = new State("WORKING");
76 public static final State DYNAMIC = new State("DYNAMIC");
77 public static final State STATIC = new State("STATIC");
78
79 /***
80 * String identifying the file name for the module descriptor.
81 */
82 public static final String MODULE_DESCRIPTOR = "module-descriptor.xml";
83
84 /***
85 * Retrieves a modules' name, the <code>name</code> attribute of the module in the manifest XML file.
86 *
87 * @return The modules' name.
88 */
89 public String getName();
90
91 /***
92 * Determines the type of the module. This is only possible when the module is checked out locally.
93 *
94 * @return The type of the module (see constants defined in <code>Module</code>).
95 */
96 public Type getType() throws ModuleTypeException;
97
98 /***
99 * Returns the <code>Location</code> instance, which is derived from the <code>location</code>-attribute.
100 */
101 public Location getLocation();
102
103 /***
104 * A module has a base directory, which is relative to the manifest that requires it. When the manifest is loaded, the
105 * base directory can be set.
106 *
107 * @param baseDir The base directory of the module relative to the active manifest.
108 */
109 public void setBaseDir(File baseDir);
110
111 /***
112 * The base directory of the module relative to the active manifest.
113 *
114 * @return The base directory of the module relative to the active manifest.
115 */
116 public File getBaseDir();
117
118
119
120
121
122 /***
123 * Returns the <code>PatchLine</code> for this module, if the module matches the correct criteria as specified in
124 * {@link #markPatchLine(boolean)}.
125 *
126 * @return <code>null</code> if a PatchLine does not exist for this module, otherwise the <code>PatchLine</code>
127 * instance for this module.
128 * @see #markPatchLine(boolean)
129 */
130 public DevelopmentLine getPatchLine();
131
132 /***
133 * Marks this module as being developed in a <code>PatchLine</code>. This can only happen when the manifest in which
134 * the module is used is a <code>ReleaseManifest</code> and the module has a <code>STATIC</code> state. When the
135 * manifest is loaded, this method will be called when the module matches the criteria.
136 */
137 public void markPatchLine(boolean mark);
138
139 public boolean hasPatchLine();
140
141 /***
142 * Checks if the module - within the current manifest - has development line configuration. When the manifest is
143 * a <code>ReleaseManifest</code>, this is true when a <code>PatchLine</code> exists. When the manifest is a
144 * <code>DevelopmentManifest</code>, this method returns false, as this feature is not supported.
145 *
146 * @return
147 */
148 public boolean hasDevelopmentLine();
149
150 /***
151 * Marks this modules as being developed in a <code>DevelopmentLine</code>. This feature is NOT supported as yet.
152 */
153 public void markDevelopmentLine(boolean mark);
154
155 /***
156 * If a module has a <version>-attribute, this method returns a Version instance representing the version
157 * number of the module.
158 *
159 * @return The version of the module if it has one.
160 */
161 public Version getVersion();
162
163 /***
164 * If the module element in the manifest contains a <code>version</code> attribute, this method will return the
165 * value of that attribute.
166 *
167 * @return The module version, or <code>N/A</code>, when no version number exists.
168 */
169 public String getVersionAsString();
170
171 /***
172 * Checks if a module has a <version>-attribute.
173 *
174 * @return <ode>true</code> if the module has a <version>-attribute or <code>false</code> if it hasn't.
175 */
176 public boolean hasVersion();
177
178 /***
179 * Gets a <code>Set</code> of <code>ModuleDependency</code> objects. This method should return an empty set if no
180 * dependencies have been specified. Dependencies are not checked to be available.
181 *
182 * @return A <code>Set</code> containing all dependencies as <code>ModuleDependency</code> objects.
183 */
184 public Set getDependencies();
185
186 /***
187 * Returns the correct layout template for the module.
188 *
189 * @return A <code>ModuleLayoutTemplate</code> for the specific module type.
190 */
191 public ModuleLayoutTemplate getLayoutTemplate();
192
193 public void createRemote(Authenticator authenticator, String createComment) throws VersionControlException, AuthenticationException ;
194
195 /***
196 * Inner class representing the type of the module, which is determined at runtime by reading the
197 * <code>module-descriptor.xml</code> file from the module base directory.
198 *
199 * @author D.A. Smedes
200 */
201 final class Type {
202
203 private String type = null;
204 private String shortType = null;
205
206 public Type() {}
207
208 private Type(String type) {
209 this.type = type;
210 }
211
212
213 public void setType(String type) {
214 if ("src".equals(type) || JAVA_SOURCE_MODULE.getType().equals(type)) {
215 this.type = JAVA_SOURCE_MODULE.getType();
216 shortType = "src";
217 } else if ("lib".equals(type) || LIBRARY_MODULE.getType().equals(type)) {
218 this.type = LIBRARY_MODULE.getType();
219 shortType = "lib";
220 } else if ("webapp".equals(type) || JAVA_WEB_APPLICATION.getType().equals(type)) {
221 this.type = JAVA_WEB_APPLICATION.getType();
222 shortType = "webapp";
223 } else if ("eapp".equals(type) || JAVA_ENTERPRISE_APPLICATION.getType().equals(type)) {
224 this.type = JAVA_ENTERPRISE_APPLICATION.getType();
225 shortType = "eapp";
226 } else if ("other".equals(type) || OTHER_MODULE.getType().equals(type)) {
227 this.type = OTHER_MODULE.getType();
228 shortType = "other";
229 } else {
230 throw new IllegalArgumentException("Type must be 'src', 'lib', 'webapp', 'eapp' or 'other'.");
231 }
232 }
233
234 public String getType() {
235 return type;
236 }
237
238 public String getShortType() {
239 return shortType;
240 }
241
242 public String toString() {
243 return getType();
244 }
245
246 public int hashCode() {
247 return type.hashCode();
248 }
249
250 public boolean equals(Object o) {
251 if (o instanceof Type) {
252 if (((Type) o).type.equals(type)) {
253 return true;
254 } else {
255 return false;
256 }
257 }
258 return false;
259 }
260 }
261
262 /***
263 * <p>Inner class representing the 'state' of a module. Three states exist at the moment : <code>WORKING</code>,
264 * <code>STATIC</code> and <code>DYNAMIC</code>.
265 * <p/>
266 *
267 * <ul>
268 * <li/><code>WORKING</code> means that a developer wants to develop on the module; add code, remove code etc. The
269 * local copy of the module will be updated to the reflect the latest versions of files in a particular
270 * branch. <code>WORKING</code> state also implies that a developer can promote a module so that manifests
271 * that have the module in a <code>DYNAMIC</code> state, can choose to upgrade their manifest to the latest
272 * (stable) version of the module.
273 * <li/><code>DYNAMNIC</code> means that a developer is not interested in the HEAD of a development line, but only
274 * in stable versions of the module.
275 * <li/><code>STATIC</code> means that a developer wants to use a fixed version of the module in the manifest.
276 * </ul>
277 *
278 * @author D.A. Smedes
279 */
280 final class State {
281
282
283
284 private String state = null;
285
286 /***
287 * Constructor. Initializes the <code>State</code> instance with the correct state string.
288 *
289 * @param stateString
290 */
291 public State(String stateString) {
292
293 if (!stateString.matches("WORKING|DYNAMIC|STATIC|UNDEFINED")) {
294 throw new PatternSyntaxException(
295 "Pattern mismatch for 'state'; pattern must match 'WORKING|DYNAMIC|STATIC|UNDEFINED'", stateString, -1);
296 }
297 this.state = stateString;
298 }
299
300 /***
301 * Gets the string representation of this state object.
302 *
303 * @return A <code>String</code> representation of this state object.
304 */
305 public String toString() {
306 return state;
307 }
308
309 public int hashCode() {
310 return state.hashCode();
311 }
312
313 /***
314 * Checks equality of one <code>State</code> instance to this <code>State</code> instance. Instances are equal
315 * when their state strings are equal.
316 *
317 * @param o An object instance that must be checked for equality with this <code>State</code> instance.
318 * @return <code>true</code> if this <code>State</code> instance equals <code>o</code>, otherwise
319 * <code>false</code>.
320 */
321 public boolean equals(Object o) {
322
323 if (o instanceof State) {
324 if (o.toString().equals(this.toString())) {
325 return true;
326 } else {
327 return false;
328 }
329 }
330 return false;
331 }
332
333 /***
334 * Returns the filename for this state on disk (generally something like <code>.WORKING</code> or
335 * <code>.STATIC</code>.
336 *
337 * @return
338 */
339 public String getHiddenFileName() {
340 return "." + state;
341 }
342 }
343 }