Fix for bug 454937
- DBWS DDLParser: type parsing fails if a member function/procedure is encountered
- DDLParser.jjt : add MEMBER and STATIC keywords, make parseType()/columnDeclarations(), aware that a member function/procedure may be found, added memberFunctionOrProcedureDeclaration() to skip member functions/procedures, added memberFunctionOrProcedure() token handler, line ending/tab fixes
- TypeDDLTestSuite.java : add testTypeWithMemberFunctions() and testTypeWithMemberFunctionsAndConstructors() (dependency on previous fix to DDLParser) to test member functions and procedures, static/non-static.
- Testing: 100%

Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/oracleddlparser/src/main/jjtree/org/eclipse/persistence/tools/oracleddl/parser/DDLParser.jjt b/oracleddlparser/src/main/jjtree/org/eclipse/persistence/tools/oracleddl/parser/DDLParser.jjt
index 417b93c..c529099 100644
--- a/oracleddlparser/src/main/jjtree/org/eclipse/persistence/tools/oracleddl/parser/DDLParser.jjt
+++ b/oracleddlparser/src/main/jjtree/org/eclipse/persistence/tools/oracleddl/parser/DDLParser.jjt
@@ -253,6 +253,7 @@
     | <R_IS: "IS">
     | <R_LIKE: "LIKE">
     | <R_LOCK: "LOCK">
+    | <R_MEMBER: "MEMBER">
     | <R_MINUS: "MINUS">
     | <R_MODE: "MODE">
     | <R_NOCOMPRESS: "NOCOMPRESS">
@@ -275,6 +276,7 @@
     | <R_SIZE: "SIZE">
     | <R_SQL: "SQL">
     | <R_START: "START">
+    | <R_STATIC: "STATIC">
     | <R_SUBTYPE: "SUBTYPE">
     | <R_TABAUTH: "TABAUTH">
     | <R_TABLE: "TABLE">
@@ -665,7 +667,7 @@
                 if (schema != null) {
                     ((ObjectType)databaseType).setSchema(schema);
                 }
-            } columnDeclarations(databaseType) constructorDeclaration() <O_CLOSEPAREN>
+            } columnDeclarations(databaseType) constructorDeclaration() memberFunctionOrProcedureDeclaration() <O_CLOSEPAREN>
           | <K_VARRAY> <O_OPENPAREN> vsize=<S_NUMBER> <O_CLOSEPAREN> <R_OF>
             {
                 databaseType = new VArrayType(typeName);
@@ -699,7 +701,7 @@
 void columnDeclarations(CompositeDatabaseType enclosingType):
 {}
 {
-    (LOOKAHEAD(2) constructor() | columnDeclaration(enclosingType) | constraintDeclaration(enclosingType) )
+    (LOOKAHEAD(2) constructor() | columnDeclaration(enclosingType) | constraintDeclaration(enclosingType) | memberFunctionOrProcedure() )
     [ <O_COMMA> columnDeclarations(enclosingType) ]
 }
 
@@ -1641,6 +1643,15 @@
    argument(procedureType) ( <O_COMMA> argument(procedureType) )*
 }
 
+// Member Function/Procedure Specification - ignore both
+void memberFunctionOrProcedureDeclaration() :
+{}
+{
+    [ <R_STATIC> ] [ <R_MEMBER> ]
+    [ ( <R_PROCEDURE> skipToClosingParen() <O_CLOSEPAREN> | <R_FUNCTION> skipToReturn() datatype() ) ]
+    [ <O_COMMA> memberFunctionOrProcedureDeclaration() ]
+}
+
 // Function Specification
 void functionSpec(PLSQLPackageType packageType) :
 {String functionName= null;
@@ -1920,4 +1931,13 @@
       
     token = t;
   }
+}
+
+void memberFunctionOrProcedure():
+{    Token t = token;
+}
+{
+    [ <R_STATIC> ] <R_MEMBER> ( <R_FUNCTION> | <R_PROCEDURE> ) {
+        token = t;
+    }
 }
\ No newline at end of file
diff --git a/oracleddlparser/src/test/java/org/eclipse/persistence/tools/oracleddl/test/ddlparser/TypeDDLTestSuite.java b/oracleddlparser/src/test/java/org/eclipse/persistence/tools/oracleddl/test/ddlparser/TypeDDLTestSuite.java
index 2095fcc..97c6212 100644
--- a/oracleddlparser/src/test/java/org/eclipse/persistence/tools/oracleddl/test/ddlparser/TypeDDLTestSuite.java
+++ b/oracleddlparser/src/test/java/org/eclipse/persistence/tools/oracleddl/test/ddlparser/TypeDDLTestSuite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2011 Oracle. All rights reserved.

+ * Copyright (c) 2011-2014 Oracle. All rights reserved.

  * This program and the accompanying materials are made available under the

  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0

  * which accompanies this distribution.

@@ -25,6 +25,7 @@
 import org.junit.Test;

 import static org.junit.Assert.assertEquals;

 import static org.junit.Assert.assertFalse;

+import static org.junit.Assert.assertNotNull;

 import static org.junit.Assert.assertTrue;

 

 //DDL imports

@@ -287,5 +288,90 @@
         assertTrue("type with multiple constructors did not parse:\n" + message, worked);

         assertEquals("incorrect type name " + TYPE_NAME, TYPE_NAME, typeWithMultipleConstructors.getTypeName());

     }

+    

+    static final String MEMBER_FUNCTION_TYPE_NAME = "MEMBER_FUNCTION_TYPE";

+    static final String CREATE_MEMBER_FUNCTION_TYPE = CREATE_TYPE_PREFIX + MEMBER_FUNCTION_TYPE_NAME + " AS OBJECT(" +

+            "\n    status1 varchar2(5)," +

+            "\n    status2 varchar2(5)," +

+            "\n    status3 varchar2(5)," +

+            "\n    member function my_function1 return varchar2," +

+            "\n    member function my_function2 return varchar2," +

+            "\n    static member function my_function3 return varchar2," +

+            "\n    member function my_function4 return varchar2," +

+            "\n    static member function my_function5 return varchar2," +

+            "\n    MEMBER PROCEDURE display1 (SELF IN OUT NOCOPY solid_typ)," +

+            "\n    MEMBER PROCEDURE display2 (SELF IN OUT NOCOPY solid_typ)," +

+            "\n    static MEMBER PROCEDURE display3 (SELF IN OUT NOCOPY solid_typ)," +

+            "\n    static MEMBER PROCEDURE display4 (SELF IN OUT NOCOPY solid_typ)," +

+            "\n    member function my_function6 return varchar2," +

+            "\n    static member function my_function7 return varchar2" +

+            "\n)";

+    

+    @Test

+    public void testTypeWithMemberFunctions() {

+        parser.ReInit(new StringReader(CREATE_MEMBER_FUNCTION_TYPE));

+        boolean worked = true;

+        String message = "";

+        ObjectType typeWithMemberFunctions = null;

+        try {

+            typeWithMemberFunctions = (ObjectType)parser.parseType();

+        } catch (ParseException pe) {

+            pe.printStackTrace();

+            message = pe.getMessage();

+            worked = false;

+        }

+        assertTrue("Parse error:\n" + message, worked);

+        assertNotNull("Type should not be null", typeWithMemberFunctions);

+        assertEquals("Incorrect type name: " + MEMBER_FUNCTION_TYPE_NAME, MEMBER_FUNCTION_TYPE_NAME, typeWithMemberFunctions.getTypeName());

+        assertEquals("Type should have three fields", 3, typeWithMemberFunctions.getFields().size());

+    }

+    

+    static final String MEMBER_FUNCTION_CONS_TYPE_NAME = "MEMBER_FUNCTION_CONS_TYPE";

+    static final String CREATE_MEMBER_FUNCTION_CONS_TYPE = 

+        "CREATE OR REPLACE TYPE " + MEMBER_FUNCTION_CONS_TYPE_NAME + " AS OBJECT(" +

+        "\n    status1 varchar2(5)," +

+        "\n    status2 varchar2(5)," +

+        "\n    status3 varchar2(5)," +

+        "\n    constructor function my_type (" +

+        "\n       i_status        in varchar2," +

+        "\n       i_comments      in varchar2 := null" +

+        "\n    ) return self as result," +

+        "\n    constructor function my_type (" +

+        "\n       i_status        in boolean," +

+        "\n       i_orauser       in varchar2," +

+        "\n       i_comments      in varchar2" +

+        "\n    ) return self as result," +

+        "\n    member function my_function1 return varchar2," +

+        "\n    member function my_function2 return varchar2," +

+        "\n    static member function my_function3 return varchar2," +

+        "\n    member function my_function4 return varchar2," +

+        "\n    static member function my_function5 return varchar2," +

+        "\n    MEMBER PROCEDURE display1 (SELF IN OUT NOCOPY solid_typ)," +

+        "\n    MEMBER PROCEDURE display2 (SELF IN OUT NOCOPY solid_typ)," +

+        "\n    static MEMBER PROCEDURE display3 (SELF IN OUT NOCOPY solid_typ)," +

+        "\n    static MEMBER PROCEDURE display4 (SELF IN OUT NOCOPY solid_typ)," +

+        "\n    member function my_function6 return varchar2," +

+        "\n    static member function my_function7 return varchar2" +

+        "\n)";

+    

+    @Test

+    public void testTypeWithMemberFunctionsAndConstructors() {

+        parser.ReInit(new StringReader(CREATE_MEMBER_FUNCTION_CONS_TYPE));

+        boolean worked = true;

+        String message = "";

+        ObjectType typeWithMemberFunctions = null;

+        try {

+            typeWithMemberFunctions = (ObjectType)parser.parseType();

+        } catch (ParseException pe) {

+            pe.printStackTrace();

+            message = pe.getMessage();

+            worked = false;

+        }

+        assertTrue("Parse error:\n" + message, worked);

+        assertNotNull("Type should not be null", typeWithMemberFunctions);

+        assertEquals("incorrect type name: " + MEMBER_FUNCTION_CONS_TYPE_NAME, MEMBER_FUNCTION_CONS_TYPE_NAME, 

+                typeWithMemberFunctions.getTypeName());

+        assertEquals("Type should have three fields", 3, typeWithMemberFunctions.getFields().size());

+    }

 

 }
\ No newline at end of file