001: /********************************************************************************
002: * CruiseControl, a Continuous Integration Toolkit
003: * Copyright (c) 2001, ThoughtWorks, Inc.
004: * 200 E. Randolph, 25th Floor
005: * Chicago, IL 60601 USA
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * + Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * + Redistributions in binary form must reproduce the above
016: * copyright notice, this list of conditions and the following
017: * disclaimer in the documentation and/or other materials provided
018: * with the distribution.
019: *
020: * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021: * names of its contributors may be used to endorse or promote
022: * products derived from this software without specific prior
023: * written permission.
024: *
025: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036: ********************************************************************************/package net.sourceforge.cruisecontrol.sourcecontrols;
037:
038: import java.text.DateFormat;
039: import java.text.ParseException;
040: import java.text.SimpleDateFormat;
041: import java.util.ArrayList;
042: import java.util.Date;
043: import java.util.Iterator;
044: import java.util.List;
045:
046: import org.apache.log4j.Logger;
047: import org.jdom.CDATA;
048: import org.jdom.Element;
049: import org.jdom.output.XMLOutputter;
050:
051: import net.sourceforge.cruisecontrol.Modification;
052:
053: /**
054: * Data structure which holds data specific to a single modification within a CM
055: * Synergy repository.
056: *
057: * @author <a href="mailto:rjmpsmith@hotmail.com">Robert J. Smith</a>
058: */
059: public class CMSynergyModification extends Modification {
060:
061: private static final Logger LOG = Logger
062: .getLogger(CMSynergyModification.class);
063:
064: private static final String MODIFICATION_TYPE = "ccmtask";
065: private static final String TAGNAME_MODIFICATION = "modification";
066: private static final String TAGNAME_OBJECT = "ccmobject";
067: private static final String TAGNAME_CHANGEREQUEST = "ccmcr";
068: private static final String TAGNAME_NAME = "name";
069: private static final String TAGNAME_TASKNUMBER = "task";
070: private static final String TAGNAME_VERSION = "version";
071: private static final String TAGNAME_TYPE = "type";
072: private static final String TAGNAME_INSTANCE = "instance";
073: private static final String TAGNAME_PROJECT = "project";
074: private static final String TAGNAME_COMMENT = "comment";
075: private static final String TAGNAME_DATE = "date";
076: private static final String TAGNAME_USER = "user";
077: private static final String TAGNAME_EMAIL = "email";
078: private static final String TAGNAME_REVISION = "revision";
079: private static final String TAGNAME_HTML_LINK = "a";
080: private static final String TAGNAME_HTML_LINK_HREF = "href";
081: private static final String TAGNAME_HTML_INS = "ins";
082:
083: /**
084: * The CM Synergy task number represented by this modification
085: */
086: public String taskNumber;
087:
088: /**
089: * A list of change requests associated with this modification
090: */
091: public List changeRequests = new ArrayList();
092:
093: /**
094: * Creates a new <code>CMSynergyModification</code> object and sets it's
095: * modification type to "ccmtask".
096: */
097: public CMSynergyModification() {
098: super (MODIFICATION_TYPE);
099: }
100:
101: /**
102: * Creates a new <code>ModifiedObject</code>, and adds it to the list of
103: * CM Synergy objects associated with the task.
104: *
105: * @return A new <code>ModifiedObject</code>
106: */
107: public final ModifiedObject createModifiedObject() {
108: ModifiedObject obj = new ModifiedObject();
109: files.add(obj);
110: return obj;
111: }
112:
113: /**
114: * Creates a new <code>ModifiedObject</code>, populates the fields, and
115: * adds it to the list of CM Synergy objects associated with the task.
116: *
117: * @param name
118: * The object's name
119: * @param version
120: * The object's version
121: * @param type
122: * The object's type within CM Synergy
123: * @param instance
124: * The object's instance
125: * @param project
126: * The project with which the object is associated
127: * @param comment
128: * The comment provided when checking in the object
129: *
130: * @return A new <code>ModifiedObject</code>
131: */
132: public final ModifiedObject createModifiedObject(String name,
133: String version, String type, String instance,
134: String project, String comment) {
135: ModifiedObject obj = createModifiedObject();
136: obj.name = name;
137: obj.version = version;
138: obj.type = type;
139: obj.instance = instance;
140: obj.project = project;
141: obj.comment = comment;
142: return obj;
143: }
144:
145: /**
146: * Creates a new <code>ChangeRequest</code>, and adds it to the list of
147: * change requests associated with the task.
148: *
149: * @param number
150: * The CR number
151: *
152: * @return A new <code>ChangeRequest</code>
153: */
154: public final ChangeRequest createChangeRequest(String number) {
155: ChangeRequest cr = new ChangeRequest();
156: cr.number = number;
157: changeRequests.add(cr);
158: return cr;
159: }
160:
161: /*
162: * (non-Javadoc)
163: *
164: * @see net.sourceforge.cruisecontrol.Modification#toElement(java.text.DateFormat)
165: */
166: public Element toElement(DateFormat formatter) {
167: Element modificationElement = new Element(TAGNAME_MODIFICATION);
168: modificationElement.setAttribute(TAGNAME_TYPE, type);
169:
170: if (modifiedTime != null) {
171: Element dateElement = new Element(TAGNAME_DATE);
172: dateElement.addContent(formatter.format(modifiedTime));
173: modificationElement.addContent(dateElement);
174: }
175:
176: if (userName != null) {
177: Element userElement = new Element(TAGNAME_USER);
178: userElement.addContent(userName);
179: modificationElement.addContent(userElement);
180: }
181:
182: if (comment != null) {
183: Element commentElement = new Element(TAGNAME_COMMENT);
184: CDATA cd;
185: try {
186: cd = new CDATA(comment);
187: } catch (org.jdom.IllegalDataException e) {
188: LOG.error(e);
189: cd = new CDATA(
190: "Unable to parse comment. It contains illegal data.");
191: }
192: commentElement.addContent(cd);
193: modificationElement.addContent(commentElement);
194: }
195:
196: if (taskNumber != null) {
197: Element taskNumberElement = new Element(TAGNAME_TASKNUMBER);
198: taskNumberElement.addContent(taskNumber);
199: modificationElement.addContent(taskNumberElement);
200: }
201:
202: if (revision != null) {
203: Element revisionElement = new Element(TAGNAME_REVISION);
204: revisionElement.addContent(revision);
205: modificationElement.addContent(revisionElement);
206: }
207:
208: if (emailAddress != null) {
209: Element emailAddressElement = new Element(TAGNAME_EMAIL);
210: emailAddressElement.addContent(emailAddress);
211: modificationElement.addContent(emailAddressElement);
212: }
213:
214: Iterator i = files.iterator();
215: while (i.hasNext()) {
216: ModifiedObject obj = (ModifiedObject) i.next();
217: modificationElement.addContent(obj.toElement(formatter));
218: }
219:
220: i = changeRequests.iterator();
221: while (i.hasNext()) {
222: ChangeRequest cr = (ChangeRequest) i.next();
223: modificationElement.addContent(cr.toElement(formatter));
224: }
225:
226: return modificationElement;
227: }
228:
229: /*
230: * (non-Javadoc)
231: *
232: * @see java.lang.Object#toString()
233: */
234: public String toString() {
235: SimpleDateFormat formatter = new SimpleDateFormat(
236: "yyyy/MM/dd HH:mm:ss");
237: StringBuffer sb = new StringBuffer();
238:
239: sb.append("Task Number: ").append(taskNumber).append('\n');
240: sb.append("Owner: ").append(userName).append('\n');
241: sb.append("Release: ").append(revision).append('\n');
242: sb.append("Completion Date: ").append(
243: formatter.format(modifiedTime)).append('\n');
244: sb.append("Synopsis: ").append(comment).append('\n');
245:
246: Iterator i = changeRequests.iterator();
247: while (i.hasNext()) {
248: ChangeRequest cr = (ChangeRequest) i.next();
249: sb.append("\tChange Request: ").append(cr.number).append(
250: '\n');
251: }
252:
253: i = files.iterator();
254: while (i.hasNext()) {
255: ModifiedObject obj = (ModifiedObject) i.next();
256: sb.append("\tAssociated Object: ").append(obj.name).append(
257: '\n');
258: sb.append("\tVersion: ").append(obj.version).append('\n');
259: sb.append("\tType: ").append(obj.type).append('\n');
260: sb.append("\tInstance: ").append(obj.instance).append('\n');
261: sb.append("\tProject: ").append(obj.project).append('\n');
262: sb.append("\tComment: ").append(obj.comment).append('\n');
263: }
264:
265: sb.append('\n');
266: return sb.toString();
267: }
268:
269: /*
270: * (non-Javadoc)
271: *
272: * @see net.sourceforge.cruisecontrol.Modification#log(java.text.DateFormat)
273: */
274: public void log(DateFormat formatter) {
275: if (LOG.isDebugEnabled()) {
276: LOG.debug("Task Number: " + taskNumber);
277: LOG.debug("Owner: " + userName);
278: LOG.debug("Release: " + revision);
279: LOG.debug("Completion Date: "
280: + formatter.format(modifiedTime));
281: LOG.debug("Synopsis: " + comment);
282:
283: Iterator i = changeRequests.iterator();
284: while (i.hasNext()) {
285: ChangeRequest cr = (ChangeRequest) i.next();
286: LOG.debug("\tChange Request: " + cr.number + "\n");
287: }
288:
289: i = files.iterator();
290: while (i.hasNext()) {
291: ModifiedObject obj = (ModifiedObject) i.next();
292: LOG.debug("\tAssociated Object: " + obj.name);
293: LOG.debug("\tVersion: " + obj.version);
294: LOG.debug("\tType: " + obj.type);
295: LOG.debug("\tInstance: " + obj.instance);
296: LOG.debug("\tProject: " + obj.project);
297: LOG.debug("\tComment: " + obj.comment);
298: }
299:
300: LOG.debug("");
301: }
302: }
303:
304: /*
305: * (non-Javadoc)
306: *
307: * @see net.sourceforge.cruisecontrol.Modification#fromElement(org.jdom.Element,
308: * java.text.DateFormat)
309: */
310: public void fromElement(Element modification, DateFormat formatter) {
311:
312: type = modification.getAttributeValue(TAGNAME_TYPE);
313:
314: try {
315: String s = modification.getChildText(TAGNAME_DATE);
316: if (s == null) {
317: XMLOutputter outputter = new XMLOutputter();
318: LOG
319: .info("XML: "
320: + outputter.outputString(modification));
321: }
322: modifiedTime = formatter.parse(s);
323: } catch (ParseException e) {
324: modifiedTime = new Date();
325: }
326:
327: taskNumber = modification.getChildText(TAGNAME_TASKNUMBER);
328: revision = modification.getChildText(TAGNAME_REVISION);
329: userName = modification.getChildText(TAGNAME_USER);
330: comment = modification.getChildText(TAGNAME_COMMENT);
331: emailAddress = modification.getChildText(TAGNAME_EMAIL);
332:
333: files.clear();
334: List modfiles = modification.getChildren(TAGNAME_OBJECT);
335: if (modfiles != null) {
336: Iterator it = modfiles.iterator();
337: while (it.hasNext()) {
338: Element modfileElement = (Element) it.next();
339: ModifiedObject modfile = new ModifiedObject();
340: modfile.fromElement(modfileElement, formatter);
341: files.add(modfile);
342: }
343: }
344:
345: changeRequests.clear();
346: List crs = modification.getChildren(TAGNAME_CHANGEREQUEST);
347: if (crs != null) {
348: Iterator it = crs.iterator();
349: while (it.hasNext()) {
350: Element crElement = (Element) it.next();
351: ChangeRequest cr = new ChangeRequest();
352: cr.fromElement(crElement, formatter);
353: changeRequests.add(cr);
354: }
355: }
356: }
357:
358: /**
359: * @see java.lang.Object#equals(java.lang.Object)
360: */
361: public boolean equals(Object o) {
362: if (o == null || !(o instanceof CMSynergyModification)) {
363: return false;
364: }
365: CMSynergyModification mod = (CMSynergyModification) o;
366: return (type.equals(mod.type) && taskNumber
367: .equals(mod.taskNumber));
368: }
369:
370: public int hashCode() {
371: final int prime = 31;
372: int result = 1;
373: result = prime * result
374: + ((type == null) ? 0 : type.hashCode())
375: + ((taskNumber == null) ? 0 : taskNumber.hashCode());
376: return result;
377: }
378:
379: /**
380: * Data structure which holds data specific to a single object included in a
381: * modification within a CM Synergy repository.
382: *
383: * @author <a href="mailto:rjmpsmith@hotmail.com">Robert J. Smith </a>
384: */
385: public class ModifiedObject {
386:
387: // Let's not deal with possible null values
388: public String name = "";
389: public String version = "";
390: public String type = "";
391: public String instance = "";
392: public String project = "";
393: public String comment = "";
394:
395: // Only the parent class should call the constructor
396: protected ModifiedObject() {
397: }
398:
399: /*
400: * (non-Javadoc)
401: *
402: * @see net.sourceforge.cruisecontrol.Modification#fromElement(org.jdom.Element,
403: * java.text.DateFormat)
404: */
405: public Element toElement(DateFormat formatter) {
406: Element element = new Element(TAGNAME_OBJECT);
407:
408: Element nameElement = new Element(TAGNAME_NAME);
409: nameElement.addContent(name);
410: element.addContent(nameElement);
411:
412: Element versionElement = new Element(TAGNAME_VERSION);
413: versionElement.addContent(version);
414: element.addContent(versionElement);
415:
416: Element typeElement = new Element(TAGNAME_TYPE);
417: typeElement.addContent(type);
418: element.addContent(typeElement);
419:
420: Element instanceElement = new Element(TAGNAME_INSTANCE);
421: instanceElement.addContent(instance);
422: element.addContent(instanceElement);
423:
424: Element projectElement = new Element(TAGNAME_PROJECT);
425: projectElement.addContent(project);
426: element.addContent(projectElement);
427:
428: Element commentElement = new Element(TAGNAME_COMMENT);
429: CDATA cd;
430: try {
431: cd = new CDATA(comment);
432: } catch (org.jdom.IllegalDataException e) {
433: LOG.error(e);
434: cd = new CDATA(
435: "Unable to parse comment. It contains illegal data.");
436: }
437: commentElement.addContent(cd);
438: element.addContent(commentElement);
439:
440: return element;
441: }
442:
443: /*
444: * (non-Javadoc)
445: *
446: * @see net.sourceforge.cruisecontrol.Modification#fromElement(org.jdom.Element,
447: * java.text.DateFormat)
448: */
449: public void fromElement(Element modification,
450: DateFormat formatter) {
451: name = modification.getChildText(TAGNAME_NAME);
452: version = modification.getChildText(TAGNAME_VERSION);
453: type = modification.getChildText(TAGNAME_TYPE);
454: instance = modification.getChildText(TAGNAME_INSTANCE);
455: project = modification.getChildText(TAGNAME_PROJECT);
456: comment = modification.getChildText(TAGNAME_COMMENT);
457: }
458:
459: }
460:
461: /**
462: * Data structure which holds data specific to a Change Request associated
463: * with a modification within a CM Synergy repository.
464: *
465: * @author <a href="mailto:rjmpsmith@hotmail.com">Robert J. Smith </a>
466: */
467: public class ChangeRequest {
468:
469: public String href = null;
470: public String number = "";
471:
472: // Only the parent class should call the constructor
473: protected ChangeRequest() {
474: }
475:
476: /*
477: * (non-Javadoc)
478: *
479: * @see net.sourceforge.cruisecontrol.Modification#fromElement(org.jdom.Element,
480: * java.text.DateFormat)
481: */
482: public Element toElement(DateFormat formatter) {
483: Element element = new Element(TAGNAME_CHANGEREQUEST);
484:
485: if (href != null) {
486: Element linkElement = new Element(TAGNAME_HTML_LINK);
487: linkElement.setAttribute(TAGNAME_HTML_LINK_HREF, href);
488: linkElement.addContent(number);
489: element.addContent(linkElement);
490: } else {
491: Element insElement = new Element(TAGNAME_HTML_INS);
492: insElement.addContent(number);
493: element.addContent(insElement);
494: }
495:
496: return element;
497: }
498:
499: /*
500: * (non-Javadoc)
501: *
502: * @see net.sourceforge.cruisecontrol.Modification#fromElement(org.jdom.Element,
503: * java.text.DateFormat)
504: */
505: public void fromElement(Element modification,
506: DateFormat formatter) {
507: Element linkElement = modification
508: .getChild(TAGNAME_HTML_LINK);
509: if (linkElement != null) {
510: href = linkElement
511: .getAttributeValue(TAGNAME_HTML_LINK_HREF);
512: number = linkElement.getText();
513: } else {
514: Element insElement = modification
515: .getChild(TAGNAME_HTML_INS);
516: if (insElement != null) {
517: number = insElement.getText();
518: }
519: }
520: }
521: }
522: }
|