conor 01/02/04 02:40:07
Modified: docs propertyfile.html
src/main/org/apache/tools/ant/taskdefs/optional
PropertyFile.java
Log:
enhancement to the optional task PropertyFile.
Operations can now be applied to all types. The now and never operations
have become values for the = operation.
Submitted by: Thomas Christen <[EMAIL PROTECTED]>
Revision Changes Path
1.2 +52 -10 jakarta-ant/docs/propertyfile.html
Index: propertyfile.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/propertyfile.html,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- propertyfile.html 2000/11/06 14:10:57 1.1
+++ propertyfile.html 2001/02/04 10:40:07 1.2
@@ -10,10 +10,11 @@
<p>by</p>
<!-- Names are in alphabetical order, on last name -->
<ul>
+ <li>Thomas Christen (<a href="mailto:[EMAIL PROTECTED]">[EMAIL
PROTECTED]</a>)</li>
<li>Jeremy Mawson (<a href="mailto:[EMAIL PROTECTED]">[EMAIL
PROTECTED]/au</a>)</li>
</ul>
-<p>Version 1.0 - 2000/11/02</p>
+<p>Version 1.1 - 2001/01/28</p>
<hr>
<h2>Table of Contents</h2>
<ul>
@@ -53,7 +54,7 @@
<h3>Parameters specified as nested elements</h3>
<h4>Entry</h4>
-<p>Use nested <code><entry></code>
+<p>Use nested <code><entry></code>
elements to specify actual modifcations to the property file itself
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -68,17 +69,31 @@
</tr>
<tr>
<td valign="top">value</td>
- <td valign="top">Value to set for the key the property name/value
pair</td>
+ <td valign="top">Value to set (=), to add (+) or subtract (-)</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">type</td>
- <td valign="top">Manipulate the value as type: int, date</td>
- <td valign="top" align="center">No, but must be used if opertion
attribute used</td>
+ <td valign="top">Regard the value as : int, date or string (default)</td>
+ <td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">operation</td>
- <td valign="top">If type is date, this cane be "now" or "never". If the
type is int, only "-" and "+" may be used.</td>
+ <td valign="top">"+" or "=" (default) for all datatypes<br>"-" (for date
and int only).<br>
+ </td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">default</td>
+ <td valign="top">Initial value to set for a property if it is not
+ already defined in the property file.<br>
+ For type date, two additional keywordsw are allowed:
"now" or "never".</td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">pattern</td>
+ <td valign="top">For int and date type only. If present, Values will
+ be paresed and formated accordingly.</td>
<td valign="top" align="center">No</td>
</tr>
</table>
@@ -94,7 +109,9 @@
<ul>#Thu Nov 02 23:41:47 EST 2000<br>
akey=avalue<br>
adate=2000/11/02 23\:41<br>
-anint=1<br></ul>
+anint=1<br>
+formated.int=0014<br>
+formated.date=028 17\:34<br></ul>
</p>
The slashes conform to the expectations of the Properties class. The file
will be stored in a manner so that each character is examined and escaped if
necessary. Note that the original comment is now lost. Please keep this in
mind when running this task against heavily commented properties files. It may
be best to have a commented version in the source tree, copy it to a deployment
area, and then run the modifications on the copy. Future versions of
PropertyFile will hopefully eliminate this shortcoming.
</p>
@@ -103,10 +120,35 @@
file="my.properties"
comment"My properties" >
<entry key="akey" value="avalue" />
- <entry key="adate" type="date" operation="now"/>
+ <entry key="adate" type="date" value="now"/>
<entry key="anint" type="int" operation="+"/>
+ <entry key="formated.int" type="int" default="0013" operation="+"
pattern="0000"/>
+ <entry key="formated.date" type="date" value="now" pattern="DDD
HH:mm"/>
</propertyfile>
-</pre></blockquote>
-
+</blockquote></pre>
+<p>
+To produce dates relative from today :
+<pre><blockquote><propertyfile
+ file="my.properties"
+ comment"My properties" >
+ <entry key="formated.date-1"
+ type="date" default="now" pattern="DDD"
+ operation="-" value="1"/>
+ <entry key="formated.tomorrow"
+ type="date" default="now" pattern="DDD"
+ operation="+" value="1"/>
+</propertyfile>
+</blockquote></pre>
+</p>
+<p>
+Concatenation of strings :
+<pre><blockquote><propertyfile
+ file="my.properties"
+ comment"My properties" >
+ <entry key="progress" default="" operation="+" value="."/>
+</propertyfile>
+</blockquote></pre>
+Each time called, a "." will be appended to "progress"
+</p>
</body>
</html>
1.5 +350 -175
jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
Index: PropertyFile.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- PropertyFile.java 2001/01/03 14:18:35 1.4
+++ PropertyFile.java 2001/02/04 10:40:07 1.5
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,10 +56,12 @@
package org.apache.tools.ant.taskdefs.optional;
import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
+import java.text.*;
/**
*PropertyFile task uses java.util.Properties to modify integer, String and
@@ -69,7 +71,7 @@
*The following is an example of its usage:
* <ul><target name="setState"><br>
* <ul><property<br>
- * <ul>name="header"<br>
+ * <ul>name="header"<br>
* value="##Generated file - do not modify!"/><br>
* <propertyfile file="apropfile.properties"
comment="${header}"><br>
* <entry key="product.version.major" type="int"
value="5"/><br>
@@ -77,7 +79,7 @@
* <entry key="product.build.major" type="int" value="0"
/><br>
* <entry key="product.build.minor" type="int" operation="+"
/><br>
* <entry key="product.build.date" type="date" operation="now"
/><br>
- * <entry key="intInc" type="int" operation="="
value="681"/><br>
+ * <entry key="intSet" type="int" operation="="
value="681"/><br>
* <entry key="intDec" type="int" operation="-"/><br>
* <entry key="NeverDate" type="date" operation="never"/><br>
* <entry key="StringEquals" type="string"
value="testValue"/><br>
@@ -93,7 +95,10 @@
*The <entry> task must have:<br>
* <ul><li>key</li></ul>
*Other parameters are:<br>
- * <ul><li>key, operation, type</li></ul>
+ * <ul><li>operation</li>
+ * <li>type</li>
+ * <li>value</li>
+ * <li>offset</li></ul>
*
*If type is unspecified, it defaults to string
*
@@ -102,14 +107,25 @@
* <ul><li>"=" (set -- default)</li>
* <li>"-" (dec)</li>
* <li>"+" (inc)</li>
- * <li>"now" (date and time)</li>
- * <li>"never" (empty string)</li></ul>
*
* <li>type:</li>
* <ul><li>"int"</li>
* <li>"date"</li>
* <li>"string"</li></ul></ul>
*
+ * <li>value:</li>
+ * <ul><li>holds the default value, if the property
+ * was not found in property file</li>
+ * <li>"now" In case of type "date", the
+ * value "now" will be replaced by the current
+ * date/time and used even if a valid date was
+ * found in the property file.</li></ul>
+ *
+ * <li>offset:<br>valid for "-" or "+", the offset (default
+ * set to 1) will be added or subtracted from "int" or
+ * "date" type value.</li>
+ * </ul>
+ *
*String property types can only use the "=" operation.
*Date property types can only use the "never" or "now" operations.
*Int property types can only use the "=", "-" or "+" operations.<p>
@@ -117,9 +133,10 @@
*The message property is used for the property file header, with "\\" being
*a newline delimiter charater.
*
- * @author Jeremy Mawson <[EMAIL PROTECTED]>
+ * @author Thomas Christen <a href="mailto:[EMAIL PROTECTED]">[EMAIL
PROTECTED]</a>
+ * @author Jeremy Mawson <a href="mailto:[EMAIL PROTECTED]>[EMAIL
PROTECTED]</a>
*/
-public class PropertyFile extends Task
+public class PropertyFile extends Task
{
/*
========================================================================
@@ -140,9 +157,8 @@
private Properties m_properties;
private File m_propertyfile;
-
+
private Vector entries = new Vector();
- private Entry mainEntry = new Entry();
/*
========================================================================
*
@@ -154,7 +170,7 @@
* Methods
*/
- public void execute() throws BuildException
+ public void execute() throws BuildException
{
checkParameters();
readFile();
@@ -162,36 +178,35 @@
writeFile();
}
- public Entry createEntry()
+ public Entry createEntry()
{
Entry e = new Entry();
entries.addElement(e);
return e;
}
-
- private void executeOperation() throws BuildException
+
+ private void executeOperation() throws BuildException
{
- // mainEntry.executeOn(m_properties);
- for (Enumeration e = entries.elements(); e.hasMoreElements(); )
+ for (Enumeration e = entries.elements(); e.hasMoreElements(); )
{
Entry entry = (Entry)e.nextElement();
entry.executeOn(m_properties);
}
}
- private void readFile() throws BuildException
+ private void readFile() throws BuildException
{
// Create the PropertyFile
m_properties = new Properties();
- try
+ try
{
- if (m_propertyfile.exists())
+ if (m_propertyfile.exists())
{
log("Updating property file:
"+m_propertyfile.getAbsolutePath());
m_properties.load(new BufferedInputStream(
new FileInputStream(m_propertyfile)));
}
- else
+ else
{
log("Creating new property file: "+
m_propertyfile.getAbsolutePath());
@@ -200,85 +215,40 @@
out.close();
}
}
- catch(IOException ioe)
+ catch(IOException ioe)
{
throw new BuildException(ioe.toString());
}
}
-
- private void checkParameters() throws BuildException
+
+ private void checkParameters() throws BuildException
{
- if (!checkParam(m_propertyfile))
+ if (!checkParam(m_propertyfile))
{
throw new BuildException("file token must not be null.",
location);
}
}
-
- public void setOperation(String op)
- {
- mainEntry.setOperation(op);
- }
-
- public void setType(String type)
- {
- mainEntry.setType(type);
- }
-
- public void setValue(String value)
- {
- mainEntry.setValue(value);
- }
-
- public void setKey(String key)
- {
- mainEntry.setKey(key);
- }
- public void setFile(String file)
+ public void setFile(File file)
{
- m_propertyfile = new File(file);
+ m_propertyfile = file;
}
- public void setComment(String hdr)
+ public void setComment(String hdr)
{
m_comment = hdr;
}
- private void writeFile() throws BuildException
+ private void writeFile() throws BuildException
{
BufferedOutputStream bos = null;
- try
+ try
{
bos = new BufferedOutputStream(new
FileOutputStream(m_propertyfile));
-// Write the message if we have one.
-// if (m_comment != null)
-// {
-// // FIXME: would like to use \n as the newline rather than
\\.
-// StringTokenizer tok = new StringTokenizer(m_comment, "\\");
-// while (tok.hasMoreTokens())
-// {
-// bos.write("# ".getBytes());
-// bos.write(((String)tok.nextToken()).getBytes());
-// bos.write(NEWLINE.getBytes());
-// }
-// bos.write(NEWLINE.getBytes());
-// bos.flush();
-// }
-// Enumeration enumValues = m_properties.elements();
-// Enumeration enumKeys = m_properties.keys();
-// while (enumKeys.hasMoreElements())
-// {
-// bos.write(((String)enumKeys.nextElement()).getBytes());
-// bos.write("=".getBytes());
-// bos.write(((String)enumValues.nextElement()).getBytes());
-// bos.write(NEWLINE.getBytes());
-// bos.flush();
-// }
-
// Properties.store is not available in JDK 1.1
- Method m =
- Properties.class.getMethod("store",
+ Method m =
+ Properties.class.getMethod("store",
new Class[] {
OutputStream.class,
String.class}
@@ -294,7 +264,7 @@
// impossible
throw new BuildException(iae, location);
}
- catch (IOException ioe)
+ catch (IOException ioe)
{
throw new BuildException(ioe, location);
}
@@ -310,155 +280,360 @@
/*
* Returns whether the given parameter has been defined.
*/
- private boolean checkParam(String param)
+ private boolean checkParam(String param)
{
return !((param == null) || (param.equals("null")));
}
- private boolean checkParam(File param)
+ private boolean checkParam(File param)
{
return !(param == null);
}
-
- public static class Entry
+
+ /**
+ * Instance of this class represents nested elements of
+ * a task propertyfile.
+ */
+ public static class Entry
{
- // Property types
- private static final String INTEGER_TYPE = "int";
- private static final String DATE_TYPE = "date";
- private static final String STRING_TYPE = "string";
-
- // Property type operations
- private static final String INCREMENT_OPER = "+";
- private static final String DECREMENT_OPER = "-";
- private static final String EQUALS_OPER = "=";
-
- // Special values
- private static final String NOW_VALUE = "now";
- private static final String NULL_VALUE = "never";
+
+ static final String NOW_VALUE_ = "now";
+ static final String NULL_VALUE_ = "never";
+
private static final int DEFAULT_INT_VALUE = 1;
private static final GregorianCalendar
DEFAULT_DATE_VALUE = new GregorianCalendar();
+
+ private String m_key = null;
+ private int m_type = Type.STRING_TYPE;
+ private int m_operation = Operation.EQUALS_OPER;
+ private String m_value ="1";
+ private String m_default = null;
+ private String m_pattern = null;
- private String m_key;
- private String m_type = null;
- private String m_operation = null;
- private String m_value;
- private int m_intValue = DEFAULT_INT_VALUE;
- private GregorianCalendar m_dateValue = DEFAULT_DATE_VALUE;
-
- public void setKey(String value)
+ public void setKey(String value)
{
this.m_key = value;
}
- public void setValue(String value)
+ public void setValue(String value)
{
this.m_value = value;
- this.setOperation(EQUALS_OPER);
}
- public void setOperation(String value)
+ public void setOperation(Operation value)
{
- this.m_operation = value;
+ int newOperation = Operation.toOperation(value.getValue());
+ if (newOperation == Operation.NOW_VALUE) {
+ this.m_operation = Operation.EQUALS_OPER;
+ this.setValue(this.NOW_VALUE_);
+ }
+ else if (newOperation == Operation.NULL_VALUE) {
+ this.m_operation = Operation.EQUALS_OPER;
+ this.setValue(this.NULL_VALUE_);
+ }
+ else {
+ this.m_operation = newOperation;
+ }
}
- public void setType(String value)
+ public void setType(Type value)
{
-
- this.m_type = value;
+ this.m_type = Type.toType(value.getValue());
+ }
+ public void setDefault(String value)
+ {
+ this.m_default = value;
+ }
+ public void setPattern(String value)
+ {
+ this.m_pattern = value;
}
- protected void executeOn(Properties props) throws BuildException
+ protected void executeOn(Properties props) throws BuildException
{
- // Fork off process per the operation type requested
+ checkParameters();
// m_type may be null because it wasn't set
try {
- if (m_type.equals(INTEGER_TYPE))
- {
- executeInteger((String)props.get(m_key));
- }
- else if (m_type.equals(DATE_TYPE))
- {
- executeDate((String)props.get(m_key));
- }
- else if (m_type.equals(STRING_TYPE))
- {
- }
- else
- {
- throw new BuildException("Unknown operation type:
"+m_type+"");
- }
-
+ if (m_type == Type.INTEGER_TYPE)
+ {
+ executeInteger((String)props.get(m_key));
+ }
+ else if (m_type == Type.DATE_TYPE)
+ {
+ executeDate((String)props.get(m_key));
+ }
+ else if (m_type == Type.STRING_TYPE)
+ {
+ executeString((String)props.get(m_key));
+ }
+ else
+ {
+ throw new BuildException("Unknown operation type:
"+m_type+"");
+ }
} catch (NullPointerException npe) {
// Default to string type
// which means do nothing
+ npe.printStackTrace();
}
// Insert as a string by default
props.put(m_key, m_value);
}
- /*
- * Continue execution for Date values
- * TODO: Modify for different locales and formats
+
+ /**
+ * Handle operations for type <code>date</code>.
+ *
+ * @param oldValue the current value read from the property file or
+ * <code>null</code> if the <code>key</code> was
+ * not contained in the property file.
*/
- private void executeDate(String oldValue) throws BuildException
+ private void executeDate(String oldValue) throws BuildException
{
- StringBuffer dateString = new StringBuffer();
+ GregorianCalendar value = new GregorianCalendar();
+ GregorianCalendar newValue = new GregorianCalendar();
- // If value is defined then interpret what's given
- if (m_operation.equals(NULL_VALUE))
- {
- m_dateValue = null;
- }
- else
- {
- Date now = new Date();
- m_dateValue.setTime(now);
- dateString.append(m_dateValue.get(Calendar.YEAR));
- dateString.append("/");
- dateString.append((m_dateValue.get(Calendar.MONTH)+1 < 10) ?
"0" : "");
- dateString.append(m_dateValue.get(Calendar.MONTH)+1);
- dateString.append("/");
- dateString.append((m_dateValue.get(Calendar.DATE) < 10) ?
"0" : "");
- dateString.append(m_dateValue.get(Calendar.DATE));
- dateString.append(" ");
- dateString.append((m_dateValue.get(Calendar.HOUR_OF_DAY) <
10) ? "0" : "");
- dateString.append(m_dateValue.get(Calendar.HOUR_OF_DAY));
- dateString.append(":");
- dateString.append((m_dateValue.get(Calendar.MINUTE) < 10) ?
"0" : "");
- dateString.append(m_dateValue.get(Calendar.MINUTE));
- m_value = dateString.toString();
+ if (m_pattern == null) m_pattern = "yyyy/MM/dd HH:mm";
+ DateFormat fmt = new SimpleDateFormat(m_pattern);
+
+ if (m_value != null) {
+ if (NOW_VALUE_.equals(m_value.toLowerCase())) {
+ value.setTime(new Date());
+ }
+ else if (NULL_VALUE_.equals(m_value.toLowerCase())) {
+ value = null;
+ }
+ else {
+ try {
+ value.setTime(fmt.parse(m_value));
+ }
+ catch (Exception ex) {
+ // obviously not a date, try a simple int
+ try {
+ int offset = Integer.parseInt(m_value);
+ value.clear();
+ value.set(Calendar.DAY_OF_YEAR, offset);
+ }
+ catch (Exception ex_) {
+ value.clear();
+ value.set(Calendar.DAY_OF_YEAR, 1);
+ }
+ }
+
+ }
+ }
+
+ // special case
+ if (m_default != null &&
+ NOW_VALUE_.equals(m_default.toLowerCase()) &&
+ (m_operation == Operation.INCREMENT_OPER ||
+ m_operation == Operation.DECREMENT_OPER) ) {
+ oldValue = null;
}
- m_value = dateString.toString();
+ if (oldValue != null) {
+ try {
+ newValue.setTime(fmt.parse(oldValue));
+ }
+ catch (ParseException pe) { /* swollow */ }
+ }
+ else {
+ if (m_default != null) {
+ if (NOW_VALUE_.equals(m_default.toLowerCase())) {
+ newValue.setTime(new Date());
+ }
+ else if (NULL_VALUE_.equals(m_default.toLowerCase())) {
+ newValue = null;
+ }
+ else {
+ try {
+ newValue.setTime(fmt.parse(m_default));
+ }
+ catch (ParseException pe) { /* swollow */ }
+ }
+ }
+ }
+
+ if (m_operation == Operation.EQUALS_OPER) {
+ newValue = value;
+ }
+ else if (m_operation == Operation.INCREMENT_OPER) {
+ newValue.add(Calendar.SECOND, value.get(Calendar.SECOND));
+ newValue.add(Calendar.MINUTE, value.get(Calendar.MINUTE));
+ newValue.add(Calendar.HOUR_OF_DAY,
value.get(Calendar.HOUR_OF_DAY));
+ newValue.add(Calendar.DAY_OF_YEAR,
value.get(Calendar.DAY_OF_YEAR));
+ }
+ else if (m_operation == Operation.DECREMENT_OPER) {
+ newValue.add(Calendar.SECOND, -1 *
value.get(Calendar.SECOND));
+ newValue.add(Calendar.MINUTE, -1 *
value.get(Calendar.MINUTE));
+ newValue.add(Calendar.HOUR_OF_DAY, -1 *
value.get(Calendar.HOUR_OF_DAY));
+ newValue.add(Calendar.DAY_OF_YEAR, -1 *
value.get(Calendar.DAY_OF_YEAR));
+ }
+ if (newValue != null) {
+ m_value = fmt.format(newValue.getTime());
+ }
+ else {
+ m_value = "";
+ }
}
- /*
- * Continue execution for int values
+ /**
+ * Handle operations for type <code>int</code>.
+ *
+ * @param oldValue the current value read from the property file or
+ * <code>null</code> if the <code>key</code> was
+ * not contained in the property file.
*/
- private void executeInteger(String oldValue) throws BuildException
+ private void executeInteger(String oldValue) throws BuildException
{
- String newValue = "";
- int currentValue = 0;
- try
- {
- currentValue = new Integer(oldValue).intValue();
+ int value = 0;
+ int newValue = 0;
+
+ DecimalFormat fmt = (m_pattern != null) ? new
DecimalFormat(m_pattern)
+ : new DecimalFormat();
+
+ if (m_value != null) {
+ try {
+ value = fmt.parse(m_value).intValue();
+ }
+ catch (NumberFormatException nfe) { /* swollow */ }
+ catch (ParseException pe) { /* swollow */ }
}
- catch (NumberFormatException nfe)
- {
- // Do nothing
+ if (oldValue != null) {
+ try {
+ newValue = fmt.parse(oldValue).intValue();
+ }
+ catch (NumberFormatException nfe) { /* swollow */ }
+ catch (ParseException pe) { /* swollow */ }
}
+ else if (m_default != null) {
+ try {
+ newValue = fmt.parse(m_default).intValue();
+ }
+ catch (NumberFormatException nfe) { /* swollow */ }
+ catch (ParseException pe) { /* swollow */ }
+ }
- if (m_operation.equals(INCREMENT_OPER))
- {
- currentValue++;
- m_value = new String(""+currentValue);
+ if (m_operation == Operation.EQUALS_OPER) {
+ newValue = value;
}
- else if (m_operation.equals(DECREMENT_OPER))
- {
- currentValue--;
- m_value = new String(""+currentValue);
+ else if (m_operation == Operation.INCREMENT_OPER) {
+ newValue += value;
+ }
+ else if (m_operation == Operation.DECREMENT_OPER) {
+ newValue -= value;
+ }
+ m_value = fmt.format(newValue);
+ }
+
+ /**
+ * Handle operations for type <code>string</code>.
+ *
+ * @param oldValue the current value read from the property file or
+ * <code>null</code> if the <code>key</code> was
+ * not contained in the property file.
+ */
+ private void executeString(String oldValue) throws BuildException
+ {
+ String value = "";
+ String newValue = "";
+
+ if (m_value != null) {
+ value = m_value;
+ }
+ if (oldValue != null) {
+ newValue = oldValue;
+ }
+ else if (m_default != null) {
+ newValue = m_default;
+ }
+
+ if (m_operation == Operation.EQUALS_OPER) {
+ newValue = value;
}
+ else if (m_operation == Operation.INCREMENT_OPER) {
+ newValue += value;
+ }
+ m_value = newValue;
}
+ /**
+ * Check if parameter combinations can be supported
+ */
+ private void checkParameters() throws BuildException {
+ if (m_type == Type.STRING_TYPE &&
+ m_operation == Operation.DECREMENT_OPER) {
+ throw new BuildException("- is not suported for string
properties (key:" + m_key + ")");
+ }
+ if (m_value == null) {
+ throw new BuildException("value is mandatory (key:" + m_key
+ ")");
+ }
+ if (m_key == null) {
+ throw new BuildException("key is mandatory");
+ }
+ if (m_type == Type.STRING_TYPE &&
+ m_pattern != null) {
+ throw new BuildException("pattern is not suported for string
properties (key:" + m_key + ")");
+ }
+ }
+
+ /**
+ * Enumerated attribute with the values "+", "-", "=", "now" and
"never".
+ */
+ public static class Operation extends EnumeratedAttribute {
+
+ // Property type operations
+ public static final int INCREMENT_OPER = 0;
+ public static final int DECREMENT_OPER = 1;
+ public static final int EQUALS_OPER = 2;
+
+ // Special values
+ public static final int NOW_VALUE = 3;
+ public static final int NULL_VALUE = 4;
+
+ public String[] getValues() {
+ return new String[] {"+", "-", "=", NOW_VALUE_, NULL_VALUE_};
+ }
+
+ public static int toOperation(String oper) {
+ if ("+".equals(oper)) {
+ return INCREMENT_OPER;
+ }
+ else if ("-".equals(oper)) {
+ return DECREMENT_OPER;
+ }
+ else if (NOW_VALUE_.equals(oper)) {
+ return NOW_VALUE;
+ }
+ else if (NULL_VALUE_.equals(oper)) {
+ return NULL_VALUE;
+ }
+ return EQUALS_OPER;
+ }
+ }
+
+ /**
+ * Enumerated attribute with the values "int", "date" and "string".
+ */
+ public static class Type extends EnumeratedAttribute {
+
+ // Property types
+ public static final int INTEGER_TYPE = 0;
+ public static final int DATE_TYPE = 1;
+ public static final int STRING_TYPE = 2;
+
+ public String[] getValues() {
+ return new String[] {"int", "date", "string"};
+ }
+
+ public static int toType(String type) {
+ if ("int".equals(type)) {
+ return INTEGER_TYPE;
+ }
+ else if ("date".equals(type)) {
+ return DATE_TYPE;
+ }
+ return STRING_TYPE;
+ }
+ }
}
}