/*******************************************************************************
* Copyright (c) 2009 the CHISEL group and contributors. All rights reserved.
* This program and the accompanying materials are 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: the CHISEL group - initial API and implementation
*******************************************************************************/
package ca.uvic.chisel.javasketch.data.model.imple.internal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ca.uvic.chisel.javasketch.data.internal.DataUtils;
import ca.uvic.chisel.javasketch.data.model.IActivation;
import ca.uvic.chisel.javasketch.data.model.IThread;
import ca.uvic.chisel.javasketch.data.model.ITrace;
import ca.uvic.chisel.javasketch.data.model.ITraceClass;
import ca.uvic.chisel.javasketch.data.model.ITraceModel;
import ca.uvic.chisel.javasketch.data.model.ITraceModelProxy;
/**
* Concrete implementation of proxies. Used as a factory to proxies as well.
*
* @author Del Myers
*
*/
public class TraceModelProxy implements ITraceModelProxy {
private ITraceModel element;
private ITrace trace;
private Object key;
private int kind;
private String elementId;
private TraceModelProxy(ITrace trace, Object key, int kind, String elementId) {
assert (key instanceof MethodKey || key instanceof Long || key instanceof String);
assert (trace != null);
assert (checkKind(kind));
element = null;
this.trace = trace;
this.key = key;
this.kind = kind;
this.elementId = elementId;
}
/**
*
*/
private boolean checkKind(int kind) {
switch (kind) {
case ITraceModel.ACTIVATION:
case ITraceModel.ARRIVAL:
case ITraceModel.CALL:
case ITraceModel.CATCH:
case ITraceModel.EVENT:
case ITraceModel.REPLY:
case ITraceModel.RETURN:
case ITraceModel.THREAD:
case ITraceModel.TRACE:
case ITraceModel.TRACE_CLASS:
case ITraceModel.TRACE_CLASS_METHOD:
case ITraceModel.MESSAGE:
return true;
}
return false;
}
/*
* (non-Javadoc)
* @see ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#getElement()
*/
public ITraceModel getElement() {
if (element == null) {
try {
load();
} catch (SQLException e) {
element = null;
}
}
return element;
}
/**
*
*/
private void load() throws SQLException {
String identifier = getIdentifer();
element = trace.findElement(identifier);
if (element == null) {
DataUtils utils = ((TraceImpl) trace).getDataUtils();
if ((getKind() & ITraceModel.MESSAGE) == ITraceModel.MESSAGE) {
ResultSet results = utils.getMessage((Long) key);
if (results != null) {
long activationId = results.getLong("activation_id");
TraceModelProxy activationProxy = new TraceModelProxy(
trace, activationId, ITraceModel.ACTIVATION,
"[ACTIVATION]," + activationId);
IActivation activation = (IActivation) activationProxy
.getElement();
if (activation != null) {
IThread thread = activation.getThread();
// try and find the element again, just in case it has
// already been loaded
element = trace.findElement(identifier);
if (element == null) {
element = MessageImpl.createFromResults(
(ThreadImpl) thread, results);
}
}
}
} else {
ResultSet results = null;
switch (getKind()) {
case ITraceModel.ACTIVATION:
results = utils.getActivation((Long) key);
if (results != null) {
Long threadId = results.getLong("thread_id");
TraceModelProxy threadProxy = new TraceModelProxy(
trace, threadId, ITraceModel.THREAD, "[THREAD],"
+ threadId);
ThreadImpl thread = (ThreadImpl) threadProxy
.getElement();
if (thread != null) {
element = new ActivationImpl(thread, results);
}
}
break;
case ITraceModel.TRACE_CLASS:
element = trace.forName((String) key);
break;
case ITraceModel.TRACE_CLASS_METHOD:
MethodKey mkey = (MethodKey) key;
ITraceClass clazz = trace.forName(mkey.type);
if (clazz != null) {
element = clazz.findMethod(mkey.name, mkey.signature);
}
break;
case ITraceModel.THREAD:
for (IThread t : trace.getThreads()) {
if (((ThreadImpl) t).getModelID() == (Long) key) {
element = t;
break;
}
}
break;
case ITraceModel.TRACE:
element = trace;
break;
case ITraceModel.EVENT:
results = utils.getEvent((Long) key);
element = new TraceEventImpl((TraceImpl) trace, results);
break;
}
}
}
}
/**
* @return
*/
private String getIdentifer() {
String tableName = getTableName();
return "[" + tableName + "]," + key.toString();
}
/**
* @return
*/
private String getTableName() {
String tableName = "";
if ((getKind() & ITraceModel.MESSAGE) == ITraceModel.MESSAGE) {
tableName = "MESSAGE";
} else {
switch (getKind()) {
case ITraceModel.ACTIVATION:
tableName = "ACTIVATION";
break;
case ITraceModel.TRACE_CLASS:
tableName = "TRACECLASS";
break;
case ITraceModel.TRACE_CLASS_METHOD:
tableName = "METHOD";
break;
case ITraceModel.THREAD:
tableName = "THREAD";
break;
case ITraceModel.TRACE:
tableName = "TRACE";
break;
case ITraceModel.EVENT:
tableName = "EVENT";
break;
}
}
return tableName;
}
/*
* (non-Javadoc)
* @see ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#getKind()
*/
public int getKind() {
return kind;
}
/**
* @param traceData
* @param c
* @return
*/
public static ITraceModelProxy forClass(ITrace traceData, String c) {
return new TraceModelProxy(traceData, c, ITraceModel.TRACE_CLASS,
"[TRACECLASS]," + c);
}
/**
* @param traceData
* @param mk
* @return
*/
public static ITraceModelProxy forMethod(ITrace traceData, MethodKey mk) {
return new TraceModelProxy(traceData, mk,
ITraceModel.TRACE_CLASS_METHOD, "[METHOD]," + mk.toString());
}
/**
* @param traceData
* @param longValue
* @return
*/
public static ITraceModelProxy forActivation(ITrace traceData, long modelId) {
return new TraceModelProxy(traceData, modelId, ITraceModel.ACTIVATION,
"[ACTIVATION]," + modelId);
}
/**
* Creates a trace model proxy for the given identifier. The actual model
* object is not guaranteed to exist in the model. Null will be returned if
* the identifier is not valid.
*
* @param trace
* @param identifier
* @return
*/
public static ITraceModelProxy forIdentifier(ITrace trace, String identifier) {
Pattern p = Pattern.compile("^\\[([a-zA-Z_-]+)\\],(.*)$");
Matcher m = p.matcher(identifier);
if (m.find()) {
String table = m.group(1).toUpperCase();
String id = m.group(2);
if ("TRACECLASS".equals(table)) {
return forClass(trace, id);
} else if ("METHOD".equals(table)) {
int paren = id.indexOf('(');
if (paren > 0) {
String sig = id.substring(paren);
id = id.substring(0, paren);
int dot = id.lastIndexOf('.');
if (dot > 0) {
String cname = id.substring(0, dot);
String mname = id.substring(dot + 1);
return forMethod(trace,
new MethodKey(cname, mname, sig));
}
}
} else {
int kind = ITraceModel.ACTIVATION;
try {
long modelId = Long.parseLong(id);
if ("MESSAGE".equals(table)) {
kind = ITraceModel.MESSAGE;
} else if ("ACTIVATION".equals(table)) {
kind = ITraceModel.ACTIVATION;
} else if ("EVENT".equals(table)) {
kind = ITraceModel.EVENT;
} else if ("THREAD".equals(table)) {
kind = ITraceModel.THREAD;
} else if ("TRACE".equals(table)) {
kind = ITraceModel.TRACE;
}
return new TraceModelProxy(trace, modelId, kind, "["
+ table + "]," + modelId);
} catch (NumberFormatException e) {
}
}
}
return null;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (key instanceof Long) {
ITraceModel element = getElement();
if (element != null) {
return element.toString();
}
return "Anable to load element";
}
return key.toString();
}
/*
* (non-Javadoc)
* @see
* ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#isDynamicElement()
*/
public boolean isDynamicElement() {
return ((kind & ITraceModel.DYNAMIC_ELEMENT) == ITraceModel.DYNAMIC_ELEMENT);
}
/*
* (non-Javadoc)
* @see
* ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#isMessageElement()
*/
public boolean isMessageElement() {
return ((kind & ITraceModel.MESSAGE) == ITraceModel.MESSAGE);
}
/*
* (non-Javadoc)
* @see
* ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#isStaticElement()
*/
public boolean isStaticElement() {
return !isDynamicElement();
}
/*
* (non-Javadoc)
* @see ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#getElementId()
*/
public String getElementId() {
return elementId;
}
/* (non-Javadoc)
* @see ca.uvic.chisel.javasketch.data.model.ITraceModelProxy#getTrace()
*/
public ITrace getTrace() {
return trace;
}
}