/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.util;
import java.util.*;
import org.jboss.tools.common.meta.action.*;
import org.jboss.tools.common.model.*;
public class FindObjectHelper implements SpecialWizard {
public static int EVERY_WHERE = 0;
public static int IN_EDITOR_ONLY = 1;
public static int IN_NAVIGATOR_ONLY = 2;
public static int IN_NAVIGATOR_AND_IN_EDITOR_IF_OPEN = 3;
static SpecialWizard select = createSelectWizard();
private XModel model = null;
private String command = null;
private int off = -1;
private FileInfo file = new FileInfo();
private SegmentInfo segment = new SegmentInfo();
private int line = -1;
public static SpecialWizard createSelectWizard() {
return SpecialWizardFactory.createSpecialWizard("org.jboss.tools.common.model.ui.select.SelectObjectWizard"); //$NON-NLS-1$
}
public static int findModelObject(XModelObject o, int where) {
if(o == null) return 1;
SpecialWizard wizard = createSelectWizard();
wizard.setObject(Integer.valueOf(where));
wizard.setObject(o);
return wizard.execute();
}
public static int findModelObject(XModelObject o, int where, String preferredPage) {
if(o == null) return 1;
SpecialWizard wizard = createSelectWizard();
wizard.setObject(Integer.valueOf(where));
wizard.setObject(o);
wizard.setObject(preferredPage);
return wizard.execute();
}
public static String makeRef(XModelObject o) {
return "" + o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE) + " " + makeRef(o.getPath(), o.getPresentationString()); //$NON-NLS-1$ //$NON-NLS-2$
}
public static String makeRef(XModelObject o, int line) {
return "" + o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE) + " " + makeRef(o.getPath() + ":" + line, o.getPresentationString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public static String makeRef(String hidden, String visible) {
return "@" + hidden + "@" + visible + "@"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public FindObjectHelper() {}
public void setObject(Object object) {
Object[] os = (Object[])object;
model = (XModel)os[0];
command = (String)os[1];
off = ((Integer)os[2]).intValue();
}
public int execute() {
XModelObject o = findRef();
if(o == null) o = findJava();
if(o != null) {
o.set("_error_line_", "" + line); //$NON-NLS-1$ //$NON-NLS-2$
select.setObject(o);
select.execute();
o.set("_error_line_", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
return 0;
}
private XModelObject findRef() {
int i = 0;
while(i < command.length()) {
int i1 = command.indexOf("@", i); //$NON-NLS-1$
if(i1 < 0 || i1 > off) return null;
int i2 = command.indexOf("@", i1 + 1); //$NON-NLS-1$
if(i2 < 0) return null;
String p = command.substring(i1 + 1, i2);
int i3 = command.indexOf("@", i2 + 1); //$NON-NLS-1$
if(i3 < 0) return null;
if(i3 >= off) {
int q = p.indexOf(":"); //$NON-NLS-1$
if(q >= 0) {
try {
line = Integer.parseInt(p.substring(q + 1));
} catch (NumberFormatException e) {
//ignore
}
p = p.substring(0, q);
}
return model.getByPath(p);
}
i = i3 + 1;
}
return null;
}
private XModelObject findJava() {
JavacErrorHeadLine h = new JavacErrorHeadLine(model, command);
if(h.jf() != null) file.setData(h.jf(), h.line(), model);
else if(h.cls() != null) file.setData(h.cls(), h.line(), model);
else return null;
XModelObject o = model.getByPath(file.getJPath());
line = file.getLine() - 1;
if (o != null) return o;
if(file.getText().length() == 0) return null;
segment.setData(file);
segment.parse();
String path = segment.getPath();
if(path == null) return null;
o = model.getByPath(path);
line = segment.getLine();
return o;
}
public static String enhanceStackTraceEntry(XModel model, String st) {
StackTraceLine q = new StackTraceLine(st);
if(q.cls() == null) return st;
FileInfo f = new FileInfo();
f.setData(q.cls(), q.line() + 1, model);
XModelObject o = model.getByPath(f.getJPath());
if(o != null) {
return q.getLineStart() + makeRef(o.getPath() + ":" + q.line(), q.toString()); //$NON-NLS-1$
} else if(q.line() < 0) {
return st;
}
SegmentInfo s = new SegmentInfo();
s.setData(f);
s.parse();
String path = s.getPath();
o = (path == null) ? null : model.getByPath(path);
if(o == null) return st;
return q.getLineStart() + makeRef(o.getPath() + ":" + s.getLine(), q.toString()); //$NON-NLS-1$
}
}
class FileInfo {
private String text = ""; //$NON-NLS-1$
private int line;
private String jpath = ""; //$NON-NLS-1$
public void setData(String cls, int ln, XModel model) {
jpath = XModelObjectConstants.SEPARATOR + cls.replace('.', '/') + ".java"; //$NON-NLS-1$
line = ln;
String fn = "" + XModelObjectUtil.getExpandedValue(model.getByPath("Engines/generator"), "directory", null) + "/src" + jpath; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
text = XModelObjectLoaderUtil.readFile(fn);
}
public void setData(XModelObject cls, int ln, XModel model) {
jpath = cls.getPath();
line = ln;
text = cls.getAttributeValue(XModelObjectConstants.ATTR_NAME_BODY);
}
public String getJPath() {
return jpath;
}
public String getText() {
return text;
}
public int getLine() {
return line;
}
}
class SegmentInfo {
private FileInfo file;
private String path = null;
private String attr = null;
int line = -1;
public SegmentInfo() {}
public void setData(FileInfo file) {
this.file = file;
}
public void parse() {
path = null;
String text = file.getText();
line = file.getLine();
int off = getOffset(text, line);
int b = 0, e = 0;
while(true) {
b = text.indexOf("//<!--", e); //$NON-NLS-1$
if(b < 0) return;
e = text.indexOf("//--", b); //$NON-NLS-1$
if(e < 0) return;
if(e > off) break;
}
b = text.indexOf("//", b + 2); //$NON-NLS-1$
if(b < 0) return;
int b2 = text.indexOf("\n", b); //$NON-NLS-1$
if(b2 < 0) return;
path = text.substring(b + 2, b2);
int q = path.lastIndexOf('.');
attr = path.substring(q + 1);
if(q >= 0) path = path.substring(0, q);
reduceLine(text, b2 + 1);
}
private int getOffset(String text, int ln) {
StringTokenizer st = new StringTokenizer(text, "\n", true); //$NON-NLS-1$
int r = 0;
while(ln > 1 && st.hasMoreTokens()) {
String s = st.nextToken();
if("\n".equals(s)) --ln; //$NON-NLS-1$
r += s.length();
}
return r;
}
private void reduceLine(String text, int b) {
StringTokenizer st = new StringTokenizer(text, "\n", true); //$NON-NLS-1$
int r = 0;
while(r < b && st.hasMoreTokens()) {
String s = st.nextToken();
if("\n".equals(s)) --line; //$NON-NLS-1$
r += s.length();
}
--line;
}
public String getPath() {
return path;
}
public String getAttr() {
return attr;
}
public int getLine() {
return line;
}
}
class StackTraceLine {
public static String PREFIX = "\tat "; //$NON-NLS-1$
private String beg = null;
private String cls = null;
private String mtd = null;
private int ln = -1;
public StackTraceLine(String text) {
int i = text.indexOf(PREFIX);
if(i < 0) return;
beg = text.substring(0, i);
text = text.substring(i + PREFIX.length()).trim();
int ob = text.indexOf('(');
if(ob < 0) return;
int cb = text.indexOf(')', ob);
if(cb < 0) return;
int ld = text.lastIndexOf('.', ob);
if(ld < 0) return;
cls = text.substring(0, ld);
mtd = text.substring(ld + 1, ob);
int sc = text.indexOf(':', ob);
if(sc < 0) sc = ob;
String sln = text.substring(sc + 1, cb);
try {
ln = Integer.parseInt(sln) - 1;
} catch (NumberFormatException e) {
//ignore
}
}
public String toString() {
return cls + "." + mtd + "(" + (ln + 1) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public String getLineStart() {
return beg + PREFIX;
}
public String cls() {
return cls;
}
public int line() {
return ln;
}
public void setLine(int line) {
ln = line;
}
}
class JavacErrorHeadLine {
private String cls = null;
private int ln = -1;
private XModelObject jf = null;
public JavacErrorHeadLine(XModel model, String command) {
int i = command.indexOf(".java:"); //$NON-NLS-1$
if(i < 0) return;
int j = command.indexOf(':', i + 6);
try {
ln = Integer.parseInt(command.substring(i + 6, j));
} catch (NumberFormatException e) {
//ignore
}
String fn = command.substring(0, i);
fn = fn.substring(fn.indexOf(']') + 1).trim(); // Cut off ant task prefix.
XModelObject g = model.getByPath("Engines/generator"); //$NON-NLS-1$
if(g != null) {
String p = "" + XModelObjectUtil.getExpandedValue(g, "directory", null) + "/src/"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
cls = fn.substring(p.length()).replace('/', '.').replace('\\', '.');
}
findJFile(model, XModelObjectConstants.SEPARATOR + fn.replace('\\', '/') + ".java"); //$NON-NLS-1$
}
private void findJFile(XModel model, String fn) {
jf = model.getByPath(fn);
if(isOverlapped(jf)) jf = null;
if(jf != null) return;
int i = fn.indexOf('/', 1);
if(i >= 0) findJFile(model, fn.substring(i));
}
private boolean isOverlapped(XModelObject o) {
while(o != null) {
if(XModelObjectConstants.TRUE.equals(o.get("overlapped"))) return true; //$NON-NLS-1$
o = o.getParent();
}
return false;
}
public String cls() {
return cls;
}
public XModelObject jf() {
return jf;
}
public int line() {
return ln;
}
}