QDox
  1. QDox
  2. QDOX-74

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

        Mike Williams made changes -
        Field Original Value New Value
        Fix Version/s 1.6 [ 10814 ]
        Component/s Java API [ 10125 ]
        Summary add support for enumerated types add parser support for enumerated types
        Fix Version/s 1.7 [ 11160 ]
        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
        Joe Walnes made changes -
        Status Open [ 1 ] Closed [ 6 ]
        Resolution Fixed [ 1 ]
        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); } } }
        Joe Walnes made changes -
        Resolution Fixed [ 1 ]
        Status Closed [ 6 ] Reopened [ 4 ]
        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
        Mauro Talevi made changes -
        Fix Version/s 1.7 [ 11160 ]
        Fix Version/s 1.6 [ 10814 ]
        Paul Hammant made changes -
        Fix Version/s 1.8 [ 14826 ]
        Fix Version/s 1.7 [ 11160 ]
        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.
        Mauro Talevi made changes -
        Status Reopened [ 4 ] Closed [ 6 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            Mike Williams
          • Votes:
            6 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: