001: /********************************************************************************
002: * CruiseControl, a Continuous Integration Toolkit
003: * Copyright (c) 2001-2003, 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.labelincrementers;
037:
038: import net.sourceforge.cruisecontrol.LabelIncrementer;
039: import org.apache.log4j.Logger;
040: import org.jdom.Element;
041:
042: /**
043: * This class provides a label incrementation for creating consistent, formatted upper
044: * case labels. This class expects the label format to be either "x_y_z" or "y_z"
045: * where x is any String, y is an integer and z is one of REL, INT or BLD.
046: *
047: * * Usage:
048: *
049: * <formattedlabelincrementer prefix="false" defaultlabel="1.INT"/%gt;
050: *
051: * @author <a href="mailto:kevin.lee@buildmeister.com">Kevin Lee</a>
052: * @author Jeff Brekke (Jeff.Brekke@qg.com)
053: * @author alden almagro (alden@thoughtworks.com)
054: * @author Paul Julius (pdjulius@thoughtworks.com)
055: */
056: public class FormattedLabelIncrementer implements LabelIncrementer {
057:
058: private static final Logger LOG = Logger
059: .getLogger(DefaultLabelIncrementer.class);
060:
061: private boolean preIncrement = false;
062: private boolean includePrefix = true;
063: private String defaultPrefix = "CC";
064: private int defaultBuildNum = 1;
065: private String defaultSuffix = "INT";
066: private String separator = "_";
067:
068: public FormattedLabelIncrementer() {
069: setSeparator(separator);
070: }
071:
072: /**
073: * set the separtor to be use between parts of the build label, default is "_"
074: * @param newSeparator the character string to use as a separator
075: */
076: public void setSeparator(String newSeparator) {
077: separator = newSeparator;
078: }
079:
080: /**
081: * Set the pre/post behavior of the label incrementer
082: * @param preInc whether to increment the build before the build, default is false
083: */
084: public void setPreBuildIncrementer(boolean preInc) {
085: preIncrement = preInc;
086: }
087:
088: /**
089: * Set whether a prefix is required or no
090: * @param prefix whether to include a prefix with the label, default is true
091: */
092: public void setPrefix(boolean prefix) {
093: includePrefix = prefix;
094: }
095:
096: /**
097: * Get the default label
098: * @return string containing the default label
099: */
100: public String getDefaultLabel() {
101: if (includePrefix) {
102: return defaultPrefix + separator + defaultBuildNum
103: + separator + defaultSuffix;
104: } else {
105: return defaultBuildNum + separator + defaultSuffix;
106: }
107: }
108:
109: /**
110: * Set the default label
111: * @param label string to set the default label to
112: */
113: public void setDefaultLabel(String label) {
114: LOG.debug("Setting default label: " + label);
115: if (includePrefix) {
116: int separatorIndex = label.lastIndexOf(separator);
117: defaultSuffix = label.substring(separatorIndex + 1,
118: label.length()).toUpperCase();
119: defaultPrefix = label.substring(0, separatorIndex);
120: separatorIndex = defaultPrefix.lastIndexOf(separator);
121: defaultBuildNum = Integer.parseInt(defaultPrefix.substring(
122: separatorIndex + 1, defaultPrefix.length()));
123: defaultPrefix = defaultPrefix.substring(0, separatorIndex)
124: .toUpperCase();
125: } else {
126: defaultSuffix = label.substring(
127: label.indexOf(separator) + 1, label.length())
128: .toUpperCase();
129: defaultBuildNum = Integer.parseInt(label.substring(0, label
130: .indexOf(separator)));
131: }
132: }
133:
134: /**
135: * Checks whether the label should be incremented pre/post build
136: * @return true if the label will be incremented before the build, else false
137: */
138: public boolean isPreBuildIncrementer() {
139: return preIncrement;
140: }
141:
142: /**
143: * Increments the label when a successful build occurs.
144: * Assumes that the label will be in the format of "x_y_z" or "y_z",
145: * where x can be anything, y is an integer and z is one of REL, INT or BLD
146: * The y value will be incremented by one, the rest will remain the same.
147: * The label is converted to uppercase by default.
148: *
149: * @param oldLabel Label from previous successful build.
150: * @return Label to use for most recent successful build.
151: */
152: public String incrementLabel(String oldLabel, Element buildLog) {
153: String newLabel;
154:
155: if (includePrefix) {
156: String prefix1 = oldLabel.substring(0, oldLabel
157: .lastIndexOf(separator));
158: String prefix2 = prefix1.substring(0, prefix1
159: .lastIndexOf(separator));
160: String suffix = oldLabel.substring(oldLabel
161: .lastIndexOf(separator) + 1, oldLabel.length());
162: String buildnum = prefix1.substring(prefix1
163: .lastIndexOf(separator) + 1, prefix1.length());
164: int i = Integer.parseInt(buildnum);
165: newLabel = prefix2.toUpperCase() + separator + ++i
166: + separator + suffix.toUpperCase();
167: } else {
168: String suffix = oldLabel.substring(oldLabel
169: .lastIndexOf(separator) + 1, oldLabel.length());
170: String buildnum = oldLabel.substring(0, oldLabel
171: .indexOf(separator));
172: int i = Integer.parseInt(buildnum);
173: newLabel = ++i + separator + suffix.toUpperCase();
174: }
175: LOG
176: .debug("Incrementing label: " + oldLabel + " -> "
177: + newLabel);
178: return newLabel;
179: }
180:
181: /**
182: * Verify that the label specified is a valid label. In this case a valid
183: * label contains at least one '_' character, and an integer after the last
184: * but one occurrence of the '_' character, followed by REL, INT or BLD
185: *
186: * @param label the label to check for validity
187: * @return true if label is valid, else false
188: */
189: public boolean isValidLabel(String label) {
190:
191: // the label does not include a separator
192: if (label.indexOf(separator) < 0) {
193: return false;
194: }
195:
196: try {
197: String suffix;
198: String buildnum;
199:
200: // check for label format
201: if (includePrefix) {
202: String prefix1 = label.substring(0, label
203: .lastIndexOf(separator));
204: suffix = label.substring(
205: label.lastIndexOf(separator) + 1, label
206: .length());
207: buildnum = prefix1.substring(prefix1
208: .lastIndexOf(separator) + 1, prefix1.length());
209: } else {
210: suffix = label.substring(
211: label.lastIndexOf(separator) + 1, label
212: .length());
213: buildnum = label.substring(0, label.indexOf(separator));
214: }
215:
216: // check for consistent suffix
217: if (suffix.equals("BLD") || suffix.equals("INT")
218: || suffix.equals("REL")) {
219: Integer.parseInt(buildnum);
220: return true;
221: } else {
222: return false;
223: }
224: } catch (NumberFormatException e) {
225: return false;
226: } catch (StringIndexOutOfBoundsException e) {
227: return false;
228: }
229: }
230:
231: }
|