//
// This file is part of the prose package.
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is prose.
//
// The Initial Developer of the Original Code is Andrei Popovici. Portions
// created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
// All Rights Reserved.
//
// Contributor(s):
// $Id: WorksheetSingleClientModel.java,v 1.3 2008/11/18 11:43:39 anicoara Exp $
// ================================================================
//
package ch.ethz.prose.tools;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.HashSet;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import ch.ethz.prose.Aspect;
import ch.ethz.prose.query.QueryManager;
import ch.ethz.prose.query.JoinPointRequestSurrogate;
import ch.ethz.prose.query.AspectSurrogate;
import ch.ethz.prose.query.Tuple;
/**
* @author pschoch
*/
public class WorksheetSingleClientModel extends DefaultTableModel {
private static final long serialVersionUID = 3257566222009905465L;
public static final int BY_ASPECT = QueryManager.GROUP_BY_ASPECT;
public static final int BY_CROSSCUT = QueryManager.GROUP_BY_CROSSCUT;
public static final int BY_JOINPOINT = QueryManager.GROUP_BY_JOINPOINT;
public static final int SELECT_ASPECT = QueryManager.SELECT_ASPECT;
public static final int SELECT_CROSSCUT = QueryManager.SELECT_CROSSCUT;
public static final int SELECT_JOINPOINT = QueryManager.SELECT_JOINPOINT;
public static final int SELECT_ALL = QueryManager.SELECT_ALL;
private static final int NR_OF_ROWS = 40; // minimum number of rows displayed
private static Vector nullVector = new Vector();
protected List table = new Vector(); // query result of prose
protected Vector data = new Vector(); // the query result in a form so it is readable for a swing table
protected int select = SELECT_ALL;
protected int groupBy = BY_ASPECT;
protected int[] selectedCells = null;
protected int selectedColumn = -1;
protected int[] pastedCells = null; // used for storing the cells that get colored
protected RemoteAspectManager exMngr;
protected String address;
protected boolean isReal;
protected MultipleClientModel parentModel;
protected String name;
protected String host;
protected String port;
private boolean addedFlag = false; // so the extra empty cell at the bottom of the table is inserted only when required
{ nullVector.add(null); nullVector.add(null); nullVector.add(null); }
private void checkIsConnected() throws IllegalUserInputException {
if (exMngr == null)
throw new IllegalUserInputException("Please select an active worksheet");
}
/**
* Creates a new instance of WorksheetSingleClientModel
*/
public WorksheetSingleClientModel(MultipleClientModel ownerModel, Object[][] initData, String[] initColumnNames, String name, String host,String port, boolean isReal) {
super(initData, initColumnNames);
this.parentModel = ownerModel;
this.isReal = isReal;
this.host = host;
this.port = port;
this.address = host + ":" + port;
this.name = name;
selectedCells = new int[0];
int i=0;
for (i=0; i < initData.length; i++) {
Vector dataElement = new Vector();
dataElement.add(initData[i][1]);
dataElement.add(initData[i][2]);
dataElement.add(initData[i][3]);
}
updateTable(data);
}
public String getName() {
return name;
}
public String getHost() {
return host;
}
public String getPort() {
return port;
}
public String getAddress() {
return address;
}
public boolean isReal() {
return isReal;
}
public void setDisplayAspect() {
select ^= SELECT_ASPECT;
}
public void setDisplayCrosscut() {
select ^= SELECT_CROSSCUT;
}
public void setDisplayJoinpoint() {
select ^= SELECT_JOINPOINT;
}
public void setGroupByAspect() {
groupBy = BY_ASPECT;
}
public void setGroupByCrosscut() {
groupBy = BY_CROSSCUT;
}
public void setGroupByJoinpoint() {
groupBy = BY_JOINPOINT;
}
public void setSelectedCells(int[] indices) {
selectedCells = indices;
}
public int getSelectedColumn() {
return selectedColumn;
}
public void setSelectedColumn(int ind) {
selectedColumn = ind;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
public synchronized void allAspects() throws RemoteException,IllegalUserInputException {
checkIsConnected();
table = new Vector();
Iterator i = exMngr.allAspects().iterator();
while (i.hasNext()) {
table.add(new Tuple((AspectSurrogate)i.next(), null, null));
}
convertDataForGUI();
updateTable(data);
}
// NOTE: it will be better to have a function in the Aspect Manager Interface e.g. 'getAllJoinpoints'
// that provides all joinpoints as JoinPointRequestSurrogate's. But this will not been implemented
// at the moment as discussed with Andrei. So it is choosed another way to come to a solution...
public synchronized void allJoinpoints() throws RemoteException,IllegalUserInputException {
checkIsConnected();
table = new Vector();
Iterator i = ((RemoteAspectManager)exMngr).allJoinpoints().iterator();
while(i.hasNext())
table.add(new Tuple(null, null, (JoinPointRequestSurrogate)i.next()));
// table = exMngr.queryAspects(exMngr.getAllAspects(), SELECT_JOINPOINT, BY_JOINPOINT);
convertDataForGUI();
updateTable(data);
}
public synchronized void query() throws RemoteException, IllegalUserInputException {
checkIsConnected();
try {
if (selectedColumn == -1) {
throw new RuntimeException("BUG: multiple selection over columns not allowed");
}
List inputList = new Vector();
if (selectedColumn == 0) {
for (int j=0; j < selectedCells.length; j++)
inputList.add(((Tuple)table.get(selectedCells[j])).getAspectSurrogate());
table = exMngr.queryAspects(inputList, select, groupBy);
}
else if (selectedColumn == 1) {
for (int j=0; j < selectedCells.length; j++)
inputList.add(((Tuple)table.get(selectedCells[j])).getCrosscutSurrogate());
table = exMngr.queryCrosscuts(inputList, select, groupBy);
}
else if (selectedColumn == 2) {
for (int j=0; j < selectedCells.length; j++)
inputList.add(((Tuple)table.get(selectedCells[j])).getRequestSurrogate());
table = exMngr.queryJoinpoints(inputList, select, groupBy);
}
else throw new RuntimeException("Row selection failed! [rowNumber: " + selectedColumn + "]");
convertDataForGUI();
updateTable(data);
}
catch (RemoteException e) {
throw e;
}
}
public int getSelect() {
return select;
}
public int getGroupBy() {
return groupBy;
}
public boolean isMixedSelection() {
if (pastedCells == null)
return false;
int mixdex = 0;
for (int j=0; j < selectedCells.length; j++)
if ((selectedCells[j] >= pastedCells[0]) && (selectedCells[j] <= pastedCells[pastedCells.length-1]))
mixdex++;
else
mixdex--;
if (Math.abs(mixdex) != selectedCells.length)
return true;
else
return false;
}
protected void pasteJoinpoints(List pasteList) {
int pastedCellsTmp[];
if (pastedCells == null)
pastedCellsTmp = new int[pasteList.size()];
else {
pastedCellsTmp = new int[pasteList.size() + pastedCells.length];
for (int i=0; i < pastedCells.length; i++)
pastedCellsTmp[i] = pastedCells[i];
}
int basicIndex = table.size();
for (int i=0; i < pasteList.size(); i++) {
Vector dataElement = new Vector();
dataElement.add(null);
dataElement.add(null);
dataElement.add(pasteList.get(i));
if (basicIndex + i == data.size() -1) {
addedFlag = true;
data.set(basicIndex + i, dataElement);
}
else if (basicIndex + i > data.size() -1) {
addedFlag = true;
data.add(dataElement);
}
else // basicIndex + i < data.size() -1
data.set(basicIndex + i, dataElement);
Tuple tup = new Tuple(null, null, (JoinPointRequestSurrogate)pasteList.get(i));
table.add(tup);
if (pastedCells == null)
pastedCellsTmp[i] = basicIndex +i;
else
pastedCellsTmp[pastedCells.length + i] = basicIndex +i;
}
pastedCells = pastedCellsTmp;
Arrays.sort(pastedCells); // actually not needed anymore since it is sorted already
updateTable(data);
}
// this is a list of aspect surrogates
protected synchronized void pasteAspects(List pasteList) throws RemoteException, IllegalUserInputException, PasteAspectsException,TableSelectionException {
checkIsConnected();
PasteAspectsException pae = new PasteAspectsException();
if (pasteList == null)
throw new TableSelectionException("Nothing to paste!");
if (parentModel.getClasspath() == null ||
parentModel.getClasspath().trim().equals(""))
throw new IllegalUserInputException("Missing classpath information");
parentModel.addVMToActiveTransaction(this);
int j=0;
int basicIndex = table.size();
List errorList = new Vector();
List alreadyContained = exMngr.allAspects();
for (int i=0; i < pasteList.size(); i++) {
AspectSurrogate aspectSur = (AspectSurrogate)pasteList.get(i);
if (alreadyContained.contains(aspectSur))
continue;
Aspect realAsp = null;
try {
String[] execArgs = CommandlineProseClient.insertScriptCommandline(parentModel.getClasspath(),
aspectSur.getAspectClassName(),
aspectSur.getAssociatedObject(),
address,
parentModel.getActiveTransactionID(),
isReal);
for (int k = 0; k < execArgs.length; k++)
parentModel.getConsole().append(execArgs[k] + " ");
parentModel.getConsole().append("\n");
Process p = Runtime.getRuntime().exec(execArgs);
parentModel.getConsole().useProcessOutput(p);
try { p.waitFor();} catch (InterruptedException e){}
if (p.exitValue() != 0)
throw new RuntimeException("Cannot insert aspect");
}
catch (Exception e) {
e.printStackTrace();
pae.add(e);
continue;
}
Tuple tup = new Tuple(aspectSur, null, null);
table.add(tup);
Vector dataElement = new Vector();
dataElement.add(aspectSur);
dataElement.add(null);
dataElement.add(null);
if (basicIndex + j == data.size() -1) {
addedFlag = true;
data.set(basicIndex + j, dataElement);
}
else if (basicIndex + j > data.size() -1) {
addedFlag = true;
data.add(dataElement);
}
else // basicIndex + j < data.size() -1
data.set(basicIndex + j, dataElement);
j++;
}
updateTable(data);
if (pae.containsExceptions()) {
pae.fillInStackTrace();
throw pae;
}
}
protected synchronized void cutAspects() throws RemoteException,TableSelectionException,WithdrawAspectsException {
if (getSelectedColumn() == -1)
throw new TableSelectionException("Nothing to Cut!");
if (getSelectedColumn() != JWorksheetProseClientPane.ASPECT_COL_INDEX)
throw new TableSelectionException("Cutting is allowed only on 'Aspects'.");
// find out what aspects to cut
HashSet myRememberList = new HashSet();
for (int i=0; i < selectedCells.length; i++) {
AspectSurrogate aspect = (AspectSurrogate)((Vector)data.get(selectedCells[i])).get(JWorksheetProseClientPane.ASPECT_COL_INDEX);
if (aspect == null)
throw new TableSelectionException("Empty cells in selection!");
myRememberList.add(aspect);
}
// cut the aspects
Iterator toCut = myRememberList.iterator();
WithdrawAspectsException maE = new WithdrawAspectsException();
while (toCut.hasNext()) {
try {
if (parentModel.getActiveTransactionID() == null)
exMngr.withdraw((AspectSurrogate)toCut.next());
else
exMngr.withdraw((AspectSurrogate)toCut.next(),parentModel.getActiveTransactionID());
}
catch (Exception e) {
maE.add(e);
}
}
// update the table
for (int i=0; i < table.size(); i++) {
AspectSurrogate aspect = (AspectSurrogate)((Vector)data.get(i)).get(JWorksheetProseClientPane.ASPECT_COL_INDEX);
if (myRememberList.contains(aspect)) {
data.remove(i);
table.remove(i);
i--;
}
}
updateTable(data);
if (maE.containsExceptions())
throw maE;
}
public void updateTable(Vector data) {
for (int i=data.size(); i < NR_OF_ROWS; i++)
data.add(nullVector);
if (addedFlag)
data.add(nullVector);
addedFlag = false;
this.setDataVector(data, createHeaders());
fireTableChanged(new TableModelEvent(this));
}
private Vector createHeaders() {
Vector v = new Vector();
v.add(new String("Aspect"));
v.add(new String("Crosscut"));
v.add(new String("Joinpoint"));
return v;
}
private void convertDataForGUI() {
pastedCells = null; // you can say, that at this point the pastedCells could be reset to null.
data = new Vector();
if (table == null)
return;
for (int i=0; i < table.size(); i++) {
Vector dataElement = new Vector();
dataElement.add(((Tuple)table.get(i)).getAspectSurrogate());
dataElement.add(((Tuple)table.get(i)).getCrosscutSurrogate());
dataElement.add(((Tuple)table.get(i)).getRequestSurrogate());
data.add(dataElement);
}
if (data.size() >= NR_OF_ROWS)
addedFlag = true;
}
public synchronized void refresh() throws java.rmi.RemoteException,java.rmi.NotBoundException,java.net.MalformedURLException, java.net.UnknownHostException {
int intPort;
RemoteAspectManager[] rams;
try {
intPort = Integer.parseInt(port);
}
catch (NumberFormatException thisIsNotAPortNum) {
throw new MalformedURLException("Illegal port number");
}
try {
rams = RemoteProseComponent.doGetRemoteAspectManagers(host,intPort);
if (isReal)
exMngr= rams[0];
else
exMngr = rams[1];
}
catch (java.io.IOException e) {
throw new RemoteException(e.toString());
}
}
public synchronized void commit(Object transactionId) throws java.rmi.RemoteException {
exMngr.commit(transactionId);
}
public synchronized void abort(Object transactionId) throws java.rmi.RemoteException {
exMngr.abort(transactionId);
}
public String toString() {
return name;
}
}