QDox

add parser support for enumerated types

Details

  • Type: New Feature New Feature
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.6
  • Fix Version/s: 1.8
  • Component/s: Parser
  • Labels:
    None
  • Number of attachments :
    0

Description

To be truly Java 5.0 tolerant, we need support for enumerated types, e.g.

public enum Grade { A, B, C, D, F, INCOMPLETE };

Activity

Hide
Joe Walnes added a comment -

Fixed. The parser now supports enums - however it does not make them available in the model. I've created another issue for this: QDOX-79

Show
Joe Walnes added a comment - Fixed. The parser now supports enums - however it does not make them available in the model. I've created another issue for this: QDOX-79
Hide
Joe Walnes added a comment -

This is a bit more complicated than I thought.

Look at this:

/*

  • @(#)TimeUnit.java 1.6 04/02/09
    *
  • Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  • SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
    */

package java.util.concurrent;

/**

  • A <tt>TimeUnit</tt> represents time durations at a given unit of
  • granularity and provides utility methods to convert across units,
  • and to perform timing and delay operations in these units. A
  • <tt>TimeUnit</tt> does not maintain time information, but only
  • helps organize and use time representations that may be maintained
  • separately across various contexts.
    *
  • <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
  • how a given timing parameter should be interpreted. For example,
  • the following code will timeout in 50 milliseconds if the {@link * java.util.concurrent.locks.Lock lock} is not available:
    *
  • <pre> Lock lock = ...;
  • if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
  • </pre>
  • while this code will timeout in 50 seconds:
  • <pre>
  • Lock lock = ...;
  • if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
  • </pre>
    *
  • Note however, that there is no guarantee that a particular timeout
  • implementation will be able to notice the passage of time at the
  • same granularity as the given <tt>TimeUnit</tt>.
    *
  • @since 1.5
  • @author Doug Lea
    */
    public enum TimeUnit {
    NANOSECONDS(0), MICROSECONDS(1), MILLISECONDS(2), SECONDS(3);

/** the index of this unit */
private final int index;

/** Internal constructor */
TimeUnit(int index) { this.index = index; }

/** Lookup table for conversion factors */
private static final int[] multipliers = { 1, 1000, 1000 * 1000, 1000 * 1000 * 1000 };

/**

  • Lookup table to check saturation. Note that because we are
  • dividing these down, we don't have to deal with asymmetry of
  • MIN/MAX values.
    */
    private static final long[] overflows = { 0, // unused Long.MAX_VALUE / 1000, Long.MAX_VALUE / (1000 * 1000), Long.MAX_VALUE / (1000 * 1000 * 1000) };

/**

  • Perform conversion based on given delta representing the
  • difference between units
  • @param delta the difference in index values of source and target units
  • @param duration the duration
  • @return converted duration or saturated value
    */
    private static long doConvert(int delta, long duration) { if (delta == 0) return duration; if (delta < 0) return duration / multipliers[-delta]; if (duration > overflows[delta]) return Long.MAX_VALUE; if (duration < -overflows[delta]) return Long.MIN_VALUE; return duration * multipliers[delta]; }

/**

  • Convert the given time duration in the given unit to this
  • unit. Conversions from finer to coarser granularities
  • truncate, so lose precision. For example converting
  • <tt>999</tt> milliseconds to seconds results in
  • <tt>0</tt>. Conversions from coarser to finer granularities
  • with arguments that would numerically overflow saturate to
  • <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
  • if positive.
    *
  • @param duration the time duration in the given <tt>unit</tt>
  • @param unit the unit of the <tt>duration</tt> argument
  • @return the converted duration in this unit,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
    */
    public long convert(long duration, TimeUnit unit) { return doConvert(unit.index - index, duration); }

/**

  • Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert
    */
    public long toNanos(long duration) { return doConvert(index, duration); }

/**

  • Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert
    */
    public long toMicros(long duration) { return doConvert(index - MICROSECONDS.index, duration); }

/**

  • Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert
    */
    public long toMillis(long duration) { return doConvert(index - MILLISECONDS.index, duration); }

/**

  • Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration.
  • @see #convert
    */
    public long toSeconds(long duration) { return doConvert(index - SECONDS.index, duration); }

/**

  • Utility method to compute the excess-nanosecond argument to
  • wait, sleep, join.
    */
    private int excessNanos(long time, long ms) { if (this == NANOSECONDS) return (int) (time - (ms * 1000 * 1000)); if (this == MICROSECONDS) return (int) ((time * 1000) - (ms * 1000 * 1000)); return 0; }

/**

  • Perform a timed <tt>Object.wait</tt> using this time unit.
  • This is a convenience method that converts timeout arguments
  • into the form required by the <tt>Object.wait</tt> method.
    *
  • <p>For example, you could implement a blocking <tt>poll</tt>
  • method (see {@link BlockingQueue#poll BlockingQueue.poll})
  • using:
    *
  • <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
  • while (empty) { * unit.timedWait(this, timeout); * ... * }
  • }</pre>
    *
  • @param obj the object to wait on
  • @param timeout the maximum time to wait.
  • @throws InterruptedException if interrupted while waiting.
  • @see Object#wait(long, int)
    */
    public void timedWait(Object obj, long timeout)
    throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); obj.wait(ms, ns); } }

/**

  • Perform a timed <tt>Thread.join</tt> using this time unit.
  • This is a convenience method that converts time arguments into the
  • form required by the <tt>Thread.join</tt> method.
  • @param thread the thread to wait for
  • @param timeout the maximum time to wait
  • @throws InterruptedException if interrupted while waiting.
  • @see Thread#join(long, int)
    */
    public void timedJoin(Thread thread, long timeout)
    throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); thread.join(ms, ns); } }

/**

  • Perform a <tt>Thread.sleep</tt> using this unit.
  • This is a convenience method that converts time arguments into the
  • form required by the <tt>Thread.sleep</tt> method.
  • @param timeout the minimum time to sleep
  • @throws InterruptedException if interrupted while sleeping.
  • @see Thread#sleep
    */
    public void sleep(long timeout) throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); Thread.sleep(ms, ns); } }

}

Show
Joe Walnes added a comment - This is a bit more complicated than I thought. Look at this: /*
  • @(#)TimeUnit.java 1.6 04/02/09 *
  • Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  • SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */
package java.util.concurrent; /**
  • A <tt>TimeUnit</tt> represents time durations at a given unit of
  • granularity and provides utility methods to convert across units,
  • and to perform timing and delay operations in these units. A
  • <tt>TimeUnit</tt> does not maintain time information, but only
  • helps organize and use time representations that may be maintained
  • separately across various contexts. *
  • <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
  • how a given timing parameter should be interpreted. For example,
  • the following code will timeout in 50 milliseconds if the {@link * java.util.concurrent.locks.Lock lock} is not available: *
  • <pre> Lock lock = ...;
  • if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
  • </pre>
  • while this code will timeout in 50 seconds:
  • <pre>
  • Lock lock = ...;
  • if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
  • </pre> *
  • Note however, that there is no guarantee that a particular timeout
  • implementation will be able to notice the passage of time at the
  • same granularity as the given <tt>TimeUnit</tt>. *
  • @since 1.5
  • @author Doug Lea */ public enum TimeUnit { NANOSECONDS(0), MICROSECONDS(1), MILLISECONDS(2), SECONDS(3);
/** the index of this unit */ private final int index; /** Internal constructor */ TimeUnit(int index) { this.index = index; } /** Lookup table for conversion factors */ private static final int[] multipliers = { 1, 1000, 1000 * 1000, 1000 * 1000 * 1000 }; /**
  • Lookup table to check saturation. Note that because we are
  • dividing these down, we don't have to deal with asymmetry of
  • MIN/MAX values. */ private static final long[] overflows = { 0, // unused Long.MAX_VALUE / 1000, Long.MAX_VALUE / (1000 * 1000), Long.MAX_VALUE / (1000 * 1000 * 1000) };
/**
  • Perform conversion based on given delta representing the
  • difference between units
  • @param delta the difference in index values of source and target units
  • @param duration the duration
  • @return converted duration or saturated value */ private static long doConvert(int delta, long duration) { if (delta == 0) return duration; if (delta < 0) return duration / multipliers[-delta]; if (duration > overflows[delta]) return Long.MAX_VALUE; if (duration < -overflows[delta]) return Long.MIN_VALUE; return duration * multipliers[delta]; }
/**
  • Convert the given time duration in the given unit to this
  • unit. Conversions from finer to coarser granularities
  • truncate, so lose precision. For example converting
  • <tt>999</tt> milliseconds to seconds results in
  • <tt>0</tt>. Conversions from coarser to finer granularities
  • with arguments that would numerically overflow saturate to
  • <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
  • if positive. *
  • @param duration the time duration in the given <tt>unit</tt>
  • @param unit the unit of the <tt>duration</tt> argument
  • @return the converted duration in this unit,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. */ public long convert(long duration, TimeUnit unit) { return doConvert(unit.index - index, duration); }
/**
  • Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert */ public long toNanos(long duration) { return doConvert(index, duration); }
/**
  • Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert */ public long toMicros(long duration) { return doConvert(index - MICROSECONDS.index, duration); }
/**
  • Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration,
  • or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  • overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  • @see #convert */ public long toMillis(long duration) { return doConvert(index - MILLISECONDS.index, duration); }
/**
  • Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
  • @param duration the duration
  • @return the converted duration.
  • @see #convert */ public long toSeconds(long duration) { return doConvert(index - SECONDS.index, duration); }
/**
  • Utility method to compute the excess-nanosecond argument to
  • wait, sleep, join. */ private int excessNanos(long time, long ms) { if (this == NANOSECONDS) return (int) (time - (ms * 1000 * 1000)); if (this == MICROSECONDS) return (int) ((time * 1000) - (ms * 1000 * 1000)); return 0; }
/**
  • Perform a timed <tt>Object.wait</tt> using this time unit.
  • This is a convenience method that converts timeout arguments
  • into the form required by the <tt>Object.wait</tt> method. *
  • <p>For example, you could implement a blocking <tt>poll</tt>
  • method (see {@link BlockingQueue#poll BlockingQueue.poll})
  • using: *
  • <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
  • while (empty) { * unit.timedWait(this, timeout); * ... * }
  • }</pre> *
  • @param obj the object to wait on
  • @param timeout the maximum time to wait.
  • @throws InterruptedException if interrupted while waiting.
  • @see Object#wait(long, int) */ public void timedWait(Object obj, long timeout) throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); obj.wait(ms, ns); } }
/**
  • Perform a timed <tt>Thread.join</tt> using this time unit.
  • This is a convenience method that converts time arguments into the
  • form required by the <tt>Thread.join</tt> method.
  • @param thread the thread to wait for
  • @param timeout the maximum time to wait
  • @throws InterruptedException if interrupted while waiting.
  • @see Thread#join(long, int) */ public void timedJoin(Thread thread, long timeout) throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); thread.join(ms, ns); } }
/**
  • Perform a <tt>Thread.sleep</tt> using this unit.
  • This is a convenience method that converts time arguments into the
  • form required by the <tt>Thread.sleep</tt> method.
  • @param timeout the minimum time to sleep
  • @throws InterruptedException if interrupted while sleeping.
  • @see Thread#sleep */ public void sleep(long timeout) throws InterruptedException
    Unknown macro: { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); Thread.sleep(ms, ns); } }
}
Hide
Rich Rodriguez added a comment -

I've received this error:

Caused by: com.thoughtworks.qdox.parser.ParseException: syntax error @[5,27] in file:/C:/src/sam2trunk/src/com/shps/sam/model/JobStatusCode.java

parsing:

public enum JobStatusCode implements StringValuedEnum
{
IN_PROGRESS("IP"),
SUCCEEDED("S"),
FAILURE("F");

private final String value;

private JobStatusCode(String value)

{ this.value = value; }

public String getValue()

{ return null; }

}

The StringValuedEnum interface consists of the "getValue" method.

I'm using the qdox 1.6 snapshot currently bundled with XDoclet2.0.3.

Show
Rich Rodriguez added a comment - I've received this error: Caused by: com.thoughtworks.qdox.parser.ParseException: syntax error @[5,27] in file:/C:/src/sam2trunk/src/com/shps/sam/model/JobStatusCode.java parsing: public enum JobStatusCode implements StringValuedEnum { IN_PROGRESS("IP"), SUCCEEDED("S"), FAILURE("F"); private final String value; private JobStatusCode(String value) { this.value = value; } public String getValue() { return null; } } The StringValuedEnum interface consists of the "getValue" method. I'm using the qdox 1.6 snapshot currently bundled with XDoclet2.0.3.
Hide
Erko Hansar added a comment -

Same problem here. Using XDoclet2 with qdox 1.6 snapshot and parsing an enum file which starts like this

public enum AccountType {

ADMINISTRATOR (1, "Administrator"),
CUSTOMER (2, "Customer"),

throws a ParseException at location after "ADMINISTRATOR " word.

Show
Erko Hansar added a comment - Same problem here. Using XDoclet2 with qdox 1.6 snapshot and parsing an enum file which starts like this public enum AccountType { ADMINISTRATOR (1, "Administrator"), CUSTOMER (2, "Customer"), throws a ParseException at location after "ADMINISTRATOR " word.
Hide
Zohar Melamed added a comment -

com.thoughtworks.qdox.parser.ParseException: syntax error @[9,1] in file:/C:/DOCUME~1/Sarah/LOCALS~1/Temp/deck-gen-1159225625203/com/ubs/eqd/data/MyEnumType.java
at com.thoughtworks.qdox.parser.impl.Parser.yyerror(Parser.java:611)
at com.thoughtworks.qdox.parser.impl.Parser.yyparse(Parser.java:719)
at com.thoughtworks.qdox.parser.impl.Parser.parse(Parser.java:592)
at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:300)
at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:316)
at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:312)
at com.thoughtworks.qdox.JavaDocBuilder$1.visitFile(JavaDocBuilder.java:369)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:43)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34)
at com.thoughtworks.qdox.directorywalker.DirectoryScanner.scan(DirectoryScanner.java:52)
at com.thoughtworks.qdox.JavaDocBuilder.addSourceTree(JavaDocBuilder.java:366)

file is :

package moo;

/**
*
*
**/

public enum MyEnumType{
BAAA, //A baaaaa baaa
MOO, //A mooooo mooooo
}

Show
Zohar Melamed added a comment - com.thoughtworks.qdox.parser.ParseException: syntax error @[9,1] in file:/C:/DOCUME~1/Sarah/LOCALS~1/Temp/deck-gen-1159225625203/com/ubs/eqd/data/MyEnumType.java at com.thoughtworks.qdox.parser.impl.Parser.yyerror(Parser.java:611) at com.thoughtworks.qdox.parser.impl.Parser.yyparse(Parser.java:719) at com.thoughtworks.qdox.parser.impl.Parser.parse(Parser.java:592) at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:300) at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:316) at com.thoughtworks.qdox.JavaDocBuilder.addSource(JavaDocBuilder.java:312) at com.thoughtworks.qdox.JavaDocBuilder$1.visitFile(JavaDocBuilder.java:369) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:43) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.walk(DirectoryScanner.java:34) at com.thoughtworks.qdox.directorywalker.DirectoryScanner.scan(DirectoryScanner.java:52) at com.thoughtworks.qdox.JavaDocBuilder.addSourceTree(JavaDocBuilder.java:366) file is : package moo; /** * * **/ public enum MyEnumType{ BAAA, //A baaaaa baaa MOO, //A mooooo mooooo }
Hide
Guus der Kinderen added a comment -

Please note that QDox currently requires an enum declaration to end with a semicolon. The following example will result in a syntax error:

public enum Foo { "bar" }

The following, however, doesn't:

public enum Foo { "bar" };

The semicolon doesn't do much during compilation. Eclipse, with the 'unnecessary code' warnings bumped up a bit, actually reports them as not needed.

Show
Guus der Kinderen added a comment - Please note that QDox currently requires an enum declaration to end with a semicolon. The following example will result in a syntax error: public enum Foo { "bar" } The following, however, doesn't: public enum Foo { "bar" }; The semicolon doesn't do much during compilation. Eclipse, with the 'unnecessary code' warnings bumped up a bit, actually reports them as not needed.
Hide
Guus der Kinderen added a comment -

Sorry, those quotes were typed by my evil twin. The example should read:

public enum Foo { BAR };

and not:

public enum Foo {"bar"};

Show
Guus der Kinderen added a comment - Sorry, those quotes were typed by my evil twin. The example should read: public enum Foo { BAR }; and not: public enum Foo {"bar"};
Hide
Mauro Talevi added a comment -

Changed fix version to 1.7

Show
Mauro Talevi added a comment - Changed fix version to 1.7
Hide
Mauro Talevi added a comment -

Added test case to EnumsTest - now all pass.

Show
Mauro Talevi added a comment - Added test case to EnumsTest - now all pass.

People

Vote (6)
Watch (7)

Dates

  • Created:
    Updated:
    Resolved: