diff --git a/sqldev/pom.xml b/sqldev/pom.xml
index 4be8a609..41261000 100644
--- a/sqldev/pom.xml
+++ b/sqldev/pom.xml
@@ -5,7 +5,7 @@
 	
 	org.utplsql
 	org.utplsql.sqldev
-	0.7.0-SNAPSHOT
+	0.7.0
 	bundle
 	
 		UTF-8
diff --git a/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend b/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend
index 87e7c5e6..e7a12a50 100644
--- a/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend
+++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend
@@ -20,6 +20,7 @@ import java.sql.Connection
 import java.sql.SQLException
 import java.sql.Types
 import java.util.List
+import java.util.regex.Pattern
 import org.oddgen.sqldev.generators.model.Node
 import org.springframework.dao.DataAccessException
 import org.springframework.dao.EmptyResultDataAccessException
@@ -31,19 +32,81 @@ import org.utplsql.sqldev.model.ut.Annotation
 import org.utplsql.sqldev.model.ut.OutputLines
 
 class UtplsqlDao {
-	public static val UTPLSQL_PACKAGE_NAME = "UT" 
+	public static val UTPLSQL_PACKAGE_NAME = "UT"
+	public static val FIRST_VERSION_WITH_INTERNAL_ANNOTATION_API = 3000004
+	public static val FIRST_VERSION_WITH_ANNOTATION_API = 3001003
 	var Connection conn
 	var JdbcTemplate jdbcTemplate
 	// cache fields
 	Boolean cachedDbaViewAccessible
 	String cachedUtplsqlSchema
-	Boolean cachedUtAnnotationManagerInstalled
+	String cachedUtPlsqlVersion
 
 	new(Connection connection) {
 		conn = connection
 		jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true))
 	}
 	
+	/**
+	 * used for testing purposes only
+	 */
+	def setUtPlsqlVersion(String utPlsqlVersion) {
+		cachedUtPlsqlVersion = utPlsqlVersion
+	}
+	
+	/**
+	 * returns a normalized utPLSQL version in format 9.9.9
+	 */
+	def String normalizedUtPlsqlVersion() {
+		val p = Pattern.compile("(\\d+\\.\\d+\\.\\d+)")
+		val version = getUtPlsqlVersion()
+		val m = p.matcher(version)
+		if (m.find) {
+			return m.group(0)
+		} else {
+			return "0.0.0"
+		}
+	}
+	
+	/**
+	 * get version as number, e.g. 3001004
+	 */
+	def int normalizedUtPlsqlVersionNumber() {
+	 	val p = Pattern.compile("(\\d+)")
+	 	val version = normalizedUtPlsqlVersion() 
+		val m = p.matcher(version)
+		m.find
+		val major = m.group
+		m.find
+		val minor = m.group
+		m.find
+		val bugfix = m.group
+		val versionNumber = Integer.valueOf(major)*1000000 + Integer.valueOf(minor)*1000 + Integer.valueOf(bugfix)
+	 	return versionNumber
+	 }
+	
+	/**
+	 * gets version of installed utPLSQL
+	 */
+	def String getUtPlsqlVersion() {
+		if (cachedUtPlsqlVersion === null) {
+			val sql = '''
+				BEGIN
+					? := ut.version;
+				END;
+			'''
+			cachedUtPlsqlVersion = jdbcTemplate.execute(sql, new CallableStatementCallback() {
+				override String doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
+					cs.registerOutParameter(1, Types.VARCHAR);
+					cs.execute
+					val version = cs.getString(1)
+					return version
+				}
+			})
+		}
+		return cachedUtPlsqlVersion
+	}
+	
 	def boolean isDbaViewAccessible() {
 		if (cachedDbaViewAccessible === null) {
 			try {
@@ -96,21 +159,7 @@ class UtplsqlDao {
 	 * @throws DataAccessException if there is a problem
 	 */
 	def boolean isUtAnnotationManagerInstalled() {
-		if (cachedUtAnnotationManagerInstalled === null) {
-			cachedUtAnnotationManagerInstalled = false
-			if (utplsqlSchema !== null) {
-				val sql = '''
-					SELECT count(*)
-					  FROM «IF dbaViewAccessible»dba«ELSE»all«ENDIF»_objects
-					 WHERE owner = '«utplsqlSchema»'
-					   AND object_type = 'PACKAGE'
-					   AND object_name = 'UT_ANNOTATION_MANAGER'
-				'''
-				val found = jdbcTemplate.queryForObject(sql, Integer)
-				cachedUtAnnotationManagerInstalled = found == 1
-			}
-		}
-		return cachedUtAnnotationManagerInstalled
+		return normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_INTERNAL_ANNOTATION_API
 	}
 	
 	/**
@@ -124,31 +173,44 @@ class UtplsqlDao {
 	 */
 	def boolean containsUtplsqlTest(String owner, String objectName, String subobjectName) {
 		try {
-			val sql = '''
-				SELECT count(
-				          CASE 
-				             WHEN a.name = 'test' 
-				                  AND (upper(a.subobject_name) = upper(?) OR ? IS NULL) 
-				             THEN 
-				               1 
-				             ELSE 
-				               NULL 
-				          END
-				       )
-				  FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o
-				 CROSS JOIN TABLE(o.annotations) a
-				 WHERE (o.object_name = upper(?) OR ? IS NULL)
-				   AND a.name IN ('test', 'suite')
-				HAVING count(
-				          CASE 
-				             WHEN a.name = 'suite' THEN 
-				                1 
-				             ELSE 
-				                NULL 
-				          END
-				       ) > 0
-			'''
-			val found = jdbcTemplate.queryForObject(sql, Integer, #[subobjectName, subobjectName, owner, objectName, objectName])
+			var Integer found
+			if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) {
+				// using API available since 3.1.3
+				val sql = '''
+					SELECT count(*)
+					  FROM TABLE(ut_runner.get_suites_info(upper(?), upper(?)))
+					 WHERE item_type = 'UT_TEST'
+					   AND (item_name = upper(?) or ? IS NULL)
+				'''
+				found = jdbcTemplate.queryForObject(sql, Integer, #[owner, objectName, subobjectName, subobjectName])
+			} else {
+				// using internal API (deprecated)
+				val sql = '''
+					SELECT count(
+					          CASE 
+					             WHEN a.name = 'test' 
+					                  AND (upper(a.subobject_name) = upper(?) OR ? IS NULL) 
+					             THEN 
+					               1 
+					             ELSE 
+					               NULL 
+					          END
+					       )
+					  FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o
+					 CROSS JOIN TABLE(o.annotations) a
+					 WHERE (o.object_name = upper(?) OR ? IS NULL)
+					   AND a.name IN ('test', 'suite')
+					HAVING count(
+					          CASE 
+					             WHEN a.name = 'suite' THEN 
+					                1 
+					             ELSE 
+					                NULL 
+					          END
+					       ) > 0
+				'''
+				found = jdbcTemplate.queryForObject(sql, Integer, #[subobjectName, subobjectName, owner, objectName, objectName])
+			}
 			return found > 0
 		} catch (EmptyResultDataAccessException e) {
 			return false	
@@ -172,12 +234,30 @@ class UtplsqlDao {
 	 * @throws DataAccessException if a utPLSQL version less than 3.0.4 is installed or if there are other problems
 	 */
 	def List annotations(String owner, String objectName) {
-		val sql = '''
-			SELECT o.object_owner, o.object_type, o.object_name, a.name, a.text, a.subobject_name
-			  FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o
-			 CROSS JOIN TABLE(o.annotations) a
-			 WHERE o.object_name = upper(?)
-		'''
+		var String sql
+		if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) {
+			// using API available since 3.1.3
+			sql = '''
+				SELECT object_owner, 
+				       object_name, 
+				       lower(substr(item_type, 4)) AS name, 
+				       item_name as subobject_name 
+				  FROM TABLE(ut_runner.get_suites_info(upper(?), upper(?)))
+			'''
+			
+		} else {
+			// using internal API (deprecated)
+			sql = '''
+				SELECT o.object_owner, 
+				       o.object_name, 
+				       a.name, 
+				       a.text, 
+				       coalesce(upper(a.subobject_name), o.object_name) AS subobject_name
+				  FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o
+				 CROSS JOIN TABLE(o.annotations) a
+				 WHERE o.object_name = upper(?)
+			'''
+		}
 		val result = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Annotation), #[owner, objectName])
 		return result
 	}
@@ -222,21 +302,42 @@ class UtplsqlDao {
 	def List testables(String objectType) {
 		var String sql;
 		if (objectType == "PACKAGE") {
-			sql = '''
-				SELECT DISTINCT 
-				       object_type || '.' || object_name AS id,
-				       object_type AS parent_id,
-				       1 AS leaf,
-				       1 AS generatable,
-				       1 AS multiselectable
-				  FROM user_procedures
-				 WHERE object_type = ?
-				   AND procedure_name IS NOT NULL
-				   AND object_name NOT IN (
-				          SELECT object_name
-					        FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(USER, 'PACKAGE'))
-				       )
-			'''
+			if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) {
+				// using API available since 3.1.3
+				sql = '''
+					SELECT DISTINCT 
+					       object_type || '.' || object_name AS id,
+					       object_type AS parent_id,
+					       1 AS leaf,
+					       1 AS generatable,
+					       1 AS multiselectable
+					  FROM user_procedures
+					 WHERE object_type = ?
+					   AND procedure_name IS NOT NULL
+					   AND object_name NOT IN (
+					          SELECT object_name
+						        FROM TABLE(ut_runner.get_suites_info(USER))
+					           WHERE item_type = 'UT_SUITE'
+					       )
+				'''
+			} else {
+				// using internal API (deprecated)
+				sql = '''
+					SELECT DISTINCT 
+					       object_type || '.' || object_name AS id,
+					       object_type AS parent_id,
+					       1 AS leaf,
+					       1 AS generatable,
+					       1 AS multiselectable
+					  FROM user_procedures
+					 WHERE object_type = ?
+					   AND procedure_name IS NOT NULL
+					   AND object_name NOT IN (
+					          SELECT object_name
+						        FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(USER, 'PACKAGE'))
+					       )
+				'''
+			}
 		}
 		else if (objectType == "TYPE") {
 			sql = '''
@@ -278,202 +379,306 @@ class UtplsqlDao {
 	 * @throws DataAccessException if there is a problem
 	 */
 	def List runnables() {
-		var sql = '''
-			WITH 
-			   base AS (
-			      SELECT rownum AS an_id,
-			             o.object_owner,
-			             o.object_type,
-			             o.object_name,
-			             lower(a.name) AS name,
-			             a.text,
-			             a.subobject_name
-			        FROM table(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(user, 'PACKAGE')) o
-			       CROSS JOIN table(o.annotations) a
-			       WHERE lower(a.name) in ('suite', 'suitepath', 'endcontext', 'test')
-			          OR lower(a.name) = 'context' AND regexp_like(text, '(\w+)(\.\w+)*')
-			   ),
-			   suite AS (
-			      SELECT object_owner, object_type, object_name, text AS suite_description
-			        FROM base
-			       WHERE name = 'suite'
-			   ),
-			   suitepath as (
-			      SELECT object_owner, object_type, object_name, lower(text) AS suitepath 
-			        FROM base
-			       WHERE name = 'suitepath'
-			   ),
-			   context_base AS (
-			      SELECT an_id,
-			             lead(an_id) over (partition by object_owner, object_type, object_name order by an_id) AS an_id_end,
-			             object_owner,
-			             object_type,
-			             object_name,
-			             name,
-			             lead(name) over (partition by object_owner, object_type, object_name order by an_id) AS name_end,
-			             text as context
-			        FROM base
-			       WHERE name IN ('context', 'endcontext')
-			   ),
-			   context as (
-			      SELECT an_id, an_id_end, object_owner, object_type, object_name, context
-			        FROM context_base
-			       WHERE name = 'context' 
-			         AND name_end = 'endcontext'
-			   ),
-			   test AS (
-			      SELECT b.an_id,
-			             b.object_owner,
-			             b.object_type,
-			             b.object_name,
-			             p.suitepath,
-			             c.context,
-			             b.subobject_name,
-			             b.text AS test_description
-			        FROM base b
-			        LEFT JOIN suitepath p
-			          ON p.object_owner = b.object_owner
-			             AND p.object_type = b.object_type
-			             AND p.object_name = b.object_name
-			        LEFT JOIN context c
-			          ON c.object_owner = b.object_owner
-			             AND c.object_type = b.object_type
-			             AND c.object_name = b.object_name
-			             AND b.an_id BETWEEN c.an_id AND c.an_id_end
-			       WHERE name = 'test'
-			         AND (b.object_owner, b.object_type, b.object_name) IN (
-			                SELECT object_owner, object_type, object_name
-			                  FROM suite
-			             )
-			   ),
-			   suite_tree AS (
-			      SELECT null AS parent_id,
-			             'SUITE' AS id,
-			             'All Suites' AS name,
-			             'All utPLSQL test suites' AS description,
-			             'PACKAGE_FOLDER_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM dual
-			      UNION ALL
-			      SELECT DISTINCT 
-			             'SUITE' AS parent_id,
-			             object_owner || '.' || object_name AS id,
-			             object_name AS name,
-			             null AS description,
-			             'PACKAGE_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM test
-			      UNION ALL
-			      SELECT object_owner || '.' || object_name AS parent_id,
-			             object_owner || '.' || object_name || '.' || subobject_name AS id,
-			             subobject_name AS name,
-			             null AS description,
-			             'PROCEDURE_ICON' AS iconName,
-			             'Yes' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM test
-			   ),
-			   suitepath_base AS (
-			      SELECT DISTINCT 
-			             suitepath 
-			        FROM suitepath
-			   ),
-			   gen AS (
-			      SELECT rownum AS pos
-			        FROM xmltable('1 to 100')
-			   ),
-			   suitepath_part AS (
-			      SELECT DISTINCT
-			             substr(suitepath, 1, instr(suitepath || '.', '.', 1, g.pos) -1) AS suitepath
-			        FROM suitepath_base b
-			        JOIN gen g
-			          ON g.pos <= regexp_count(suitepath, '\w+')
-			   ),
-			   suitepath_tree AS (
-			      SELECT NULL AS parent_id,
-			             'SUITEPATH' AS id,
-			             'All Suitepaths' AS name,
-			             'All utPLSQL test suitepathes' AS description,
-			             'FOLDER_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM dual
-			      UNION ALL
-			      SELECT CASE
-			                WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN
-			                   'SUITEPATH'
-			                ELSE 
-			                   USER || ':' || regexp_replace(suitepath,'\.?\w+$','')
-			             END AS parent_id,
-			             USER || ':' || suitepath AS id,
-			             regexp_substr(suitepath, '\.?(\w+$)', 1, 1, NULL, 1) AS name,
-			             null AS description,
-			             'FOLDER_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM suitepath_part
-			      UNION ALL
-			      SELECT DISTINCT 
-			             object_owner || ':' || suitepath AS parent_id,
-			             object_owner || ':' || suitepath || '.' || object_name AS id,
-			             object_name AS name,
-			             null AS description,
-			             'PACKAGE_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM test
-			       WHERE suitepath IS NOT NULL
-			      UNION ALL
-			      SELECT DISTINCT 
-			             object_owner || ':' || suitepath || '.' || object_name AS parent_id,
-			             object_owner || ':' || suitepath || '.' || object_name || '.' || context AS id,
-			             context AS name,
-			             null AS description,
-			             'FOLDER_ICON' AS iconName,
-			             'No' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM test
-			       WHERE suitepath IS NOT NULL
-			         AND context IS NOT NULL
-			      UNION ALL
-			      SELECT object_owner || ':' || suitepath || '.' || object_name || CASE WHEN context IS NOT NULL THEN '.' || context END AS parent_id,
-			             object_owner || ':' || suitepath || '.' || object_name || CASE WHEN context IS NOT NULL THEN '.' || context END || '.' || subobject_name AS id,
-			             subobject_name AS name,
-			             null AS description,
-			             'PROCEDURE_ICON' AS iconName,
-			             'Yes' AS leaf,
-			             'Yes' AS generatable,
-			             'Yes' AS multiselectable,
-			             'Yes' AS relevant
-			        FROM test
-			       WHERE suitepath IS NOT NULL
-			   ),
-			   tree AS (
-			      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
-			       FROM suite_tree
-			      UNION ALL
-			      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
-			       FROM suitepath_tree
-			   )
-			SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
-			  FROM tree
-		'''
+		var String sql
+		if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) {
+			// using API available since 3.1.3
+			sql = '''
+				WITH 
+				   test AS (
+				      SELECT object_owner,
+				             object_name,
+				             path AS suitepath,
+				             item_type,
+				             item_name,
+				             item_description
+				        FROM TABLE(ut_runner.get_suites_info(user))
+				   ),
+				   suite_tree AS (
+				      SELECT null AS parent_id,
+				             'SUITE' AS id,
+				             'All Suites' AS name,
+				             'All utPLSQL test suites' AS description,
+				             'PACKAGE_FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM dual
+				      UNION ALL
+				      SELECT DISTINCT 
+				             'SUITE' AS parent_id,
+				             object_owner || '.' || object_name AS id,
+				             object_name AS name,
+				             null AS description,
+				             'PACKAGE_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				       WHERE item_type = 'UT_TEST'
+				      UNION ALL
+				      SELECT object_owner || '.' || object_name AS parent_id,
+				             object_owner || '.' || object_name || '.' || item_name AS id,
+				             item_name AS name,
+				             item_description AS description,
+				             'PROCEDURE_ICON' AS iconName,
+				             'Yes' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				       WHERE item_type = 'UT_TEST'
+				   ),
+				   suitepath_tree AS (
+				      SELECT NULL AS parent_id,
+				             'SUITEPATH' AS id,
+				             'All Suitepaths' AS name,
+				             'All utPLSQL test suitepathes' AS description,
+				             'FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM dual
+				      UNION ALL
+				      SELECT CASE
+				                WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN
+				                   'SUITEPATH'
+				                ELSE 
+				                   object_owner || ':' || regexp_replace(suitepath,'\.?\w+$','')
+				             END AS parent_id,
+				             object_owner || ':' || suitepath AS id,
+				             item_name AS name,
+				             item_description AS description,
+				             CASE item_type
+				                WHEN 'UT_SUITE' THEN
+				                   'PACKAGE_ICON'
+				                WHEN 'UT_TEST' THEN
+				                   'PROCEDURE_ICON'
+				               ELSE
+				                   'FOLDER_ICON'
+				             END AS iconName,
+				             CASE item_type 
+				                WHEN 'UT_TEST' THEN
+				                   'Yes'
+				                ELSE
+				                   'No'
+				             END AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				   ),
+				   tree AS (
+				      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
+				       FROM suite_tree
+				      UNION ALL
+				      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
+				       FROM suitepath_tree
+				   )
+				SELECT parent_id, id, initcap(name) AS name, description, iconName, leaf, generatable, multiselectable, relevant
+				  FROM tree
+			'''
+		} else {
+			// using internal API (deprecated)
+			sql = '''
+				WITH 
+				   base AS (
+				      SELECT rownum AS an_id,
+				             o.object_owner,
+				             o.object_type,
+				             o.object_name,
+				             lower(a.name) AS name,
+				             a.text,
+				             a.subobject_name
+				        FROM table(ut3.ut_annotation_manager.get_annotated_objects(user, 'PACKAGE')) o
+				       CROSS JOIN table(o.annotations) a
+				       WHERE lower(a.name) in ('suite', 'suitepath', 'endcontext', 'test')
+				          OR lower(a.name) = 'context' AND regexp_like(text, '(\w+)(\.\w+)*')
+				   ),
+				   suite AS (
+				      SELECT object_owner, object_type, object_name, text AS suite_description
+				        FROM base
+				       WHERE name = 'suite'
+				   ),
+				   suitepath as (
+				      SELECT object_owner, object_type, object_name, lower(text) AS suitepath 
+				        FROM base
+				       WHERE name = 'suitepath'
+				   ),
+				   context_base AS (
+				      SELECT an_id,
+				             lead(an_id) over (partition by object_owner, object_type, object_name order by an_id) AS an_id_end,
+				             object_owner,
+				             object_type,
+				             object_name,
+				             name,
+				             lead(name) over (partition by object_owner, object_type, object_name order by an_id) AS name_end,
+				             text as context
+				        FROM base
+				       WHERE name IN ('context', 'endcontext')
+				   ),
+				   context as (
+				      SELECT an_id, an_id_end, object_owner, object_type, object_name, context
+				        FROM context_base
+				       WHERE name = 'context' 
+				         AND name_end = 'endcontext'
+				   ),
+				   test AS (
+				      SELECT b.an_id,
+				             b.object_owner,
+				             b.object_type,
+				             b.object_name,
+				             p.suitepath,
+				             c.context,
+				             b.subobject_name,
+				             b.text AS test_description
+				        FROM base b
+				        LEFT JOIN suitepath p
+				          ON p.object_owner = b.object_owner
+				             AND p.object_type = b.object_type
+				             AND p.object_name = b.object_name
+				        LEFT JOIN context c
+				          ON c.object_owner = b.object_owner
+				             AND c.object_type = b.object_type
+				             AND c.object_name = b.object_name
+				             AND b.an_id BETWEEN c.an_id AND c.an_id_end
+				       WHERE name = 'test'
+				         AND (b.object_owner, b.object_type, b.object_name) IN (
+				                SELECT object_owner, object_type, object_name
+				                  FROM suite
+				             )
+				   ),
+				   suite_tree AS (
+				      SELECT null AS parent_id,
+				             'SUITE' AS id,
+				             'All Suites' AS name,
+				             'All utPLSQL test suites' AS description,
+				             'PACKAGE_FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM dual
+				      UNION ALL
+				      SELECT DISTINCT 
+				             'SUITE' AS parent_id,
+				             object_owner || '.' || object_name AS id,
+				             object_name AS name,
+				             null AS description,
+				             'PACKAGE_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				      UNION ALL
+				      SELECT object_owner || '.' || object_name AS parent_id,
+				             object_owner || '.' || object_name || '.' || upper(subobject_name) AS id,
+				             subobject_name AS name,
+				             null AS description,
+				             'PROCEDURE_ICON' AS iconName,
+				             'Yes' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				   ),
+				   suitepath_base AS (
+				      SELECT DISTINCT 
+				             suitepath 
+				        FROM suitepath
+				   ),
+				   gen AS (
+				      SELECT rownum AS pos
+				        FROM xmltable('1 to 100')
+				   ),
+				   suitepath_part AS (
+				      SELECT DISTINCT
+				             lower(substr(suitepath, 1, instr(suitepath || '.', '.', 1, g.pos) -1)) AS suitepath
+				        FROM suitepath_base b
+				        JOIN gen g
+				          ON g.pos <= regexp_count(suitepath, '\w+')
+				   ),
+				   suitepath_tree AS (
+				      SELECT NULL AS parent_id,
+				             'SUITEPATH' AS id,
+				             'All Suitepaths' AS name,
+				             'All utPLSQL test suitepathes' AS description,
+				             'FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM dual
+				      UNION ALL
+				      SELECT CASE
+				                WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN
+				                   'SUITEPATH'
+				                ELSE 
+				                   USER || ':' || regexp_replace(suitepath,'\.?\w+$','')
+				             END AS parent_id,
+				             USER || ':' || suitepath AS id,
+				             regexp_substr(suitepath, '\.?(\w+$)', 1, 1, NULL, 1) AS name,
+				             null AS description,
+				             'FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM suitepath_part
+				      UNION ALL
+				      SELECT DISTINCT 
+				             object_owner || ':' || suitepath AS parent_id,
+				             object_owner || ':' || suitepath || '.' || lower(object_name) AS id,
+				             object_name AS name,
+				             null AS description,
+				             'PACKAGE_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				       WHERE suitepath IS NOT NULL
+				      UNION ALL
+				      SELECT DISTINCT 
+				             object_owner || ':' || suitepath || '.' || lower(object_name) AS parent_id,
+				             object_owner || ':' || suitepath || '.' || lower(object_name) || '.' || context AS id,
+				             context AS name,
+				             null AS description,
+				             'FOLDER_ICON' AS iconName,
+				             'No' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				       WHERE suitepath IS NOT NULL
+				         AND context IS NOT NULL
+				      UNION ALL
+				      SELECT object_owner || ':' || suitepath || '.' || lower(object_name) || CASE WHEN context IS NOT NULL THEN '.' || context END AS parent_id,
+				             object_owner || ':' || suitepath || '.' || lower(object_name) || CASE WHEN context IS NOT NULL THEN '.' || context END || '.' || lower(subobject_name) AS id,
+				             subobject_name AS name,
+				             null AS description,
+				             'PROCEDURE_ICON' AS iconName,
+				             'Yes' AS leaf,
+				             'Yes' AS generatable,
+				             'Yes' AS multiselectable,
+				             'Yes' AS relevant
+				        FROM test
+				       WHERE suitepath IS NOT NULL
+				   ),
+				   tree AS (
+				      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
+				       FROM suite_tree
+				      UNION ALL
+				      SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant
+				       FROM suitepath_tree
+				   )
+				SELECT parent_id, id, initcap(name) AS name, description, iconName, leaf, generatable, multiselectable, relevant
+				  FROM tree
+			'''
+		}
 		val jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true))
 		val nodes = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Node))
 		return nodes		
@@ -638,8 +843,9 @@ class UtplsqlDao {
 			           'MDSYS', 'OLAPSYS', 'ORDDATA', 'XDB', 'WMSYS', 'ORDSYS', 'GSMCATUSER', 
 			           'MDDATA', 'REMOTE_SCHEDULER_AGENT', 'SYSBACKUP', 'GSMUSER', 'APEX_PUBLIC_USER', 
 			           'SYSRAC', 'AUDSYS', 'DIP', 'SYSKM', 'ORACLE_OCM', 'APEX_INSTANCE_ADMIN_USER', 
-			           'SYSDG', 'FLOWS_FILES', 'ORDS_METADATA', 'ORDS_PUBLIC_USER', 'APEX_180100'
+			           'SYSDG', 'FLOWS_FILES', 'ORDS_METADATA', 'ORDS_PUBLIC_USER'
 			        )
+			    AND referenced_owner NOT LIKE 'APEX\_______'
 			    AND referenced_type IN ('PACKAGE', 'TYPE', 'PROCEDURE', 'FUNCTION', 'TRIGGER')
 		'''
 		val jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true))
diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend b/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend
index 087f2330..ee658e91 100644
--- a/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend
+++ b/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend
@@ -21,7 +21,6 @@ import org.utplsql.sqldev.model.AbstractModel
 @Accessors
 class Annotation extends AbstractModel {
 	String objectOwner
-	String objectType
 	String objectName
 	String name
 	String text
diff --git a/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend
index 6ceb7544..9dbad90b 100644
--- a/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend
+++ b/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend
@@ -86,9 +86,9 @@ class DalTest extends AbstractJdbcTest {
 		Assert.assertTrue(dao.utAnnotationManagerInstalled)
 	}
 	
-	@Test
-	def void containsUtplsqlTest() {
+	def void containsUtplsqlTest(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS
 			   -- %suite
@@ -125,10 +125,20 @@ class DalTest extends AbstractJdbcTest {
 		Assert.assertFalse(dao.containsUtplsqlTest("scott", "junit_utplsql_test_pkg", "t3"))
 		jdbcTemplate.execute("DROP PACKAGE junit_utplsql_test_pkg")
 	}
-	
+
+	@Test
+	def void containsUtplsqlTest304() {
+		containsUtplsqlTest("3.0.4")
+	}
+
 	@Test
-	def void annotations() {
+	def void containsUtplsqlTest313() {
+		containsUtplsqlTest("3.1.3")
+	}
+	
+	def void annotations(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS
 			   -- %suite
@@ -146,31 +156,39 @@ class DalTest extends AbstractJdbcTest {
 		val expected = new ArrayList
 		val suite = new Annotation
 		suite.objectOwner = "SCOTT"
-		suite.objectType = "PACKAGE"
 		suite.objectName = "JUNIT_UTPLSQL_TEST_PKG"
 		suite.name = 'suite'
+		suite.subobjectName = suite.objectName
 		expected.add(suite)
 		val t1 = new Annotation
 		t1.objectOwner = "SCOTT"
-		t1.objectType = "PACKAGE"
 		t1.objectName = "JUNIT_UTPLSQL_TEST_PKG"
 		t1.name = 'test'
-		t1.subobjectName = 't1'
+		t1.subobjectName = 'T1'
 		expected.add(t1)
 		val t2 = new Annotation
 		t2.objectOwner = "SCOTT"
-		t2.objectType = "PACKAGE"
 		t2.objectName = "JUNIT_UTPLSQL_TEST_PKG"
 		t2.name = 'test'
-		t2.subobjectName = 't2'
+		t2.subobjectName = 'T2'
 		expected.add(t2)
 		Assert.assertEquals(expected.toString, actual.toString)
 		jdbcTemplate.execute("DROP PACKAGE junit_utplsql_test_pkg")
 	}
-	
+
+	@Test
+	def void annotations304() {
+		annotations("3.0.4")
+	}
+
 	@Test
-	def void testablesPackages() {
+	def void annotations313() {
+		annotations("3.1.3")
+	}
+	
+	def void testablesPackages(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion		
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS
 			   -- %suite
@@ -197,8 +215,18 @@ class DalTest extends AbstractJdbcTest {
 	}
 
 	@Test
-	def void testablesTypes() {
+	def void testablesPackages304() {
+		testablesPackages("3.0.4")
+	}
+
+	@Test
+	def void testablesPackages313() {
+		testablesPackages("3.1.3")
+	}
+
+	def void testablesTypes(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion		
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE TYPE junit_tab1_ot IS object (a integer, b integer);
 		''')
@@ -218,8 +246,18 @@ class DalTest extends AbstractJdbcTest {
 	}
 
 	@Test
-	def void testablesFunctions() {
+	def void testablesTypes304() {
+		testablesTypes("3.0.4")
+	}
+
+	@Test
+	def void testablesTypes313() {
+		testablesTypes("3.1.3")
+	}
+
+	def void testablesFunctions(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE FUNCTION junit_f RETURN INTEGER IS 
 			BEGIN
@@ -232,8 +270,18 @@ class DalTest extends AbstractJdbcTest {
 	}
 
 	@Test
-	def void testablesProcedures() {
+	def void testablesFunctions304() {
+		testablesFunctions("3.0.4")
+	}
+
+	@Test
+	def void testablesFunctions313() {
+		testablesFunctions("3.1.3")
+	}
+
+	def void testablesProcedures(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE PROCEDURE junit_p RETURN INTEGER IS 
 			BEGIN
@@ -246,22 +294,32 @@ class DalTest extends AbstractJdbcTest {
 	}
 
 	@Test
-	def void runnables() {
+	def void testablesProcedures304() {
+		testablesProcedures("3.0.4")
+	}
+
+	@Test
+	def void testablesProcedures313() {
+		testablesProcedures("3.1.3")
+	}
+
+	def void runnables(String utPlsqlVersion) {
 		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = utPlsqlVersion
 		jdbcTemplate.execute('''
 			CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS
 			   -- %suite
 			   -- %suitepath(a.B.c)
 
 			   -- %test
-			   PROCEDURE t0;
+			   PROCEDURE T0;
 
-			   -- %context(mycontext)
+			   -- %context(myContext)
 
-			   -- %test
+			   -- %test(t1: test One)
 			   PROCEDURE t1;
 
-			   -- %test
+			   -- %test(t2: test Two)
 			   PROCEDURE t2;
 
 			   -- %endcontext
@@ -278,20 +336,30 @@ class DalTest extends AbstractJdbcTest {
 		}
 		Assert.assertEquals(null, actual.get("SUITE"))
 		Assert.assertEquals("SUITE", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG"))
-		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t0"))
-		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t1"))
-		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t2"))
-		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t3"))
+		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T0"))
+		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T1"))
+		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T2"))
+		Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T3"))
 		Assert.assertEquals(null, actual.get("SUITEPATH"))
 		Assert.assertEquals("SUITEPATH", actual.get("SCOTT:a"))
 		Assert.assertEquals("SCOTT:a", actual.get("SCOTT:a.b"))
 		Assert.assertEquals("SCOTT:a.b", actual.get("SCOTT:a.b.c"))
-		Assert.assertEquals("SCOTT:a.b.c", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG"))
-		Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext"))
-		Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.t0"))
-		Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.t3"))
-		Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext.t1"))
-		Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext.t2"))
+		Assert.assertEquals("SCOTT:a.b.c", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg"))
+		Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext"))
+		Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.t0"))
+		Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.t3"))
+		Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext.t1"))
+		Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext.t2"))
+	}
+
+	@Test
+	def void runnables304() {
+		runnables("3.0.4")
+	}
+
+	@Test
+	def void runnables313() {
+		runnables("3.1.3")
 	}
 
 	@Test
@@ -361,5 +429,47 @@ class DalTest extends AbstractJdbcTest {
 		val actual = dao.includes('junit_utplsql_test_pkg')
 		Assert.assertEquals(#['JUNIT_UTPLSQL_TEST_PKG','JUNIT_F','UT_EXPECTATION'].sort, actual.sort)
 	}
+	
+	@Test
+	def void normalizedPlsqlVersionOkRelease() {
+		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = "v3.1.10.1234"
+		val actual = dao.normalizedUtPlsqlVersion()
+		Assert.assertEquals("3.1.10", actual)
+	}
+
+	@Test
+	def void normalizedPlsqlVersionOkDevelop() {
+		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = "v3.1.10.1234-develop"
+		val actual = dao.normalizedUtPlsqlVersion()
+		Assert.assertEquals("3.1.10", actual)
+	}
+
+	@Test
+	def void normalizedPlsqlVersionNok() {
+		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = "bla bla 1.2"
+		val actual = dao.normalizedUtPlsqlVersion()
+		Assert.assertEquals("0.0.0", actual)
+	}
+	
+	@Test
+	def void normaliedPlsqlVersionNumber() {
+		val dao = new UtplsqlDao(dataSource.connection)
+		dao.utPlsqlVersion = "3.14.37"
+		val actual = dao.normalizedUtPlsqlVersionNumber()
+		Assert.assertEquals(3014037, actual)		
+	}
+	
+	@Test
+	def void utPlsqlVersion() {
+		val dao = new UtplsqlDao(dataSource.connection)
+		val actual = dao.utPlsqlVersion
+		val sql = "SELECT ut.version FROM DUAL"
+		val expected = jdbcTemplate.queryForObject(sql, String)
+		Assert.assertEquals(expected, actual)
+		
+	}
 
 }
\ No newline at end of file
diff --git a/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend
index 131a9d4e..93be55f4 100644
--- a/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend
+++ b/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend
@@ -35,6 +35,7 @@ class UtplsqlParserTest extends AbstractJdbcTest {
 		CREATE OR REPLACE PACKAGE pkg IS
 		   -- %suite
 		   -- %rollback(manual)
+
 		   -- %test
 		   PROCEDURE p (in_p1 INTEGER);
 		   FUNCTION f (in_p1 INTEGER) RETURN INTEGER;
@@ -90,7 +91,7 @@ class UtplsqlParserTest extends AbstractJdbcTest {
 		Assert.assertEquals("pkg", parser.getPathAt(parser.toPosition(4,1)))
 		Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(10,33)))
 		Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1)))
-		Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1)))
+		Assert.assertEquals("SCOTT.PKG.p", parser.getPathAt(parser.toPosition(19,1)))
 		Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,9)))
 		Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,10)))
 		Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(29,1)))
@@ -125,7 +126,7 @@ class UtplsqlParserTest extends AbstractJdbcTest {
 		Assert.assertEquals(2, parser.getObjects.size)
 		Assert.assertEquals(2, parser.getUnits.size)
 		Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1)))
-		Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1)))
+		Assert.assertEquals("SCOTT.PKG.p", parser.getPathAt(parser.toPosition(19,1)))
 		setupAndTeardown
 	}