001: /*
002: * OraclePackageParser.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.db.oracle;
013:
014: import java.io.IOException;
015: import workbench.sql.formatter.SQLLexer;
016: import workbench.sql.formatter.SQLToken;
017:
018: /**
019: * @author support@sql-workbench.net
020: */
021: public class OraclePackageParser {
022: private String packageDeclaration;
023: private String packageBody;
024: private String packageName;
025:
026: public OraclePackageParser(String sql) {
027: try {
028: parse(sql);
029: } catch (Exception e) {
030: e.printStackTrace();
031: }
032: }
033:
034: public String getPackageDeclaration() {
035: return this .packageDeclaration;
036: }
037:
038: public String getPackageBody() {
039: return this .packageBody;
040: }
041:
042: public String getPackageName() {
043: return this .packageName;
044: }
045:
046: private void parse(String sql) throws IOException {
047: SQLLexer lexer = new SQLLexer(sql);
048: SQLToken t = lexer.getNextToken(false, false);
049:
050: int defBegin = -1;
051: int defEnd = -1;
052: int bodyBegin = -1;
053: int bodyEnd = -1;
054: int lastCreateStart = -1;
055:
056: while (t != null) {
057: String text = t.getContents();
058:
059: if (isCreate(text)) {
060: lastCreateStart = t.getCharBegin();
061: } else if (text.equals("PACKAGE")) {
062: defBegin = lastCreateStart;
063: t = lexer.getNextToken(false, false);
064: if (t == null)
065: continue;
066:
067: if (t.isIdentifier()) {
068: this .packageName = t.getContents();
069: t = findEnd(lexer, this .packageName);
070: if (t != null) {
071: defEnd = t.getCharEnd();
072: }
073: }
074: } else if (text.equals("PACKAGE BODY")) {
075: bodyBegin = lastCreateStart;
076:
077: t = lexer.getNextToken(false, false);
078: if (t == null)
079: continue;
080:
081: String name = t.getContents();
082: t = findEnd(lexer, name);
083: if (t != null) {
084: bodyEnd = t.getCharEnd();
085: break;
086: }
087: }
088: t = lexer.getNextToken(false, false);
089: }
090: if (defBegin > -1 && defEnd > defBegin) {
091: this .packageDeclaration = sql.substring(defBegin, defEnd);
092: }
093: if (bodyBegin > -1 && bodyEnd > bodyBegin) {
094: this .packageBody = sql.substring(bodyBegin, bodyEnd);
095: }
096: }
097:
098: private boolean isCreate(String text) {
099: return text.equals("CREATE")
100: || text.equals("CREATE OR REPLACE");
101: }
102:
103: private SQLToken findEnd(SQLLexer lexer, String name)
104: throws IOException {
105: SQLToken t = lexer.getNextToken(false, false);
106: boolean lastWasEnd = false;
107:
108: while (t != null) {
109: String v = t.getContents();
110: if (v.equalsIgnoreCase("END")) {
111: lastWasEnd = true;
112: } else if (lastWasEnd && name.equalsIgnoreCase(v)) {
113: SQLToken t2 = lexer.getNextToken(false, false);
114: if (t2 != null)
115: return t2;
116: else
117: return t;
118: } else {
119: lastWasEnd = false;
120: }
121: t = lexer.getNextToken(false, false);
122: }
123: return null;
124: }
125:
126: public static int findProcedurePosition(CharSequence source,
127: String procName) {
128: int procPos = -1;
129:
130: SQLLexer lexer = new SQLLexer(source);
131: SQLToken t = lexer.getNextToken(false, false);
132:
133: // Find the start of the package body
134: while (t != null) {
135: if (t.getContents().equals("PACKAGE BODY"))
136: break;
137: t = lexer.getNextToken(false, false);
138: }
139:
140: if (t == null)
141: return -1;
142:
143: // Now we have reached the package body, let's find the the actual procedure or function
144: int lastKeywordPos = -1;
145:
146: while (t != null) {
147: String text = t.getContents();
148: if (lastKeywordPos > -1 && text.equalsIgnoreCase(procName)) {
149: procPos = lastKeywordPos;
150: break;
151: }
152: if (text.equals("PROCEDURE") || text.equals("FUNCTION")) {
153: lastKeywordPos = t.getCharBegin();
154: } else {
155: lastKeywordPos = -1;
156: }
157: t = lexer.getNextToken(false, false);
158: }
159: return procPos;
160: }
161:
162: }
|