changes to incorporate Retina Help features

cmurphy [2007-12-12 20:19:37]
changes to incorporate Retina Help features
Filename
retina/db/BotEventHandler.java
retina/db/DatabaseManager.java
retina/db/MessageSender.java
retina/db/Retina.java
retina/db/SuggestionManager.java
retina/db/XMLLoader.java
retina/db/XmlServer.java
diff --git a/retina/db/BotEventHandler.java b/retina/db/BotEventHandler.java
new file mode 100644
index 0000000..1bb5300
--- /dev/null
+++ b/retina/db/BotEventHandler.java
@@ -0,0 +1,234 @@
+package retina.db;
+import java.util.Date;
+import java.util.HashMap;
+import com.itbs.aimcer.bean.Contact;
+import com.itbs.aimcer.bean.Message;
+import com.itbs.aimcer.bean.MessageImpl;
+import com.itbs.aimcer.bean.Nameable;
+import com.itbs.aimcer.commune.Connection;
+import com.itbs.aimcer.commune.ConnectionEventListener;
+import com.itbs.aimcer.commune.FileTransferSupport;
+import com.itbs.aimcer.commune.IconSupport;
+import com.itbs.aimcer.commune.MessageSupport;
+import com.itbs.util.GeneralUtils;
+import retina.common.CompilationErrorEvent;
+import retina.common.Student;
+
+public class BotEventHandler implements ConnectionEventListener {
+
+	private DatabaseManager dbmanager = new DatabaseManager();
+	private SuggestionManager smanager = new SuggestionManager();
+	private MessageSender sender;
+
+	// maps IM handles to Retina usernames
+	private HashMap<String, String> names = new HashMap<String, String>();
+
+
+	/**
+	 * Public constructor is used to initialize the reference to the MessageSender
+	 */
+	public BotEventHandler(MessageSender ms)
+	{
+		sender = ms;
+	}
+
+	/**
+	 * No-argument constructor probably shouldn't be used, otherwise it can't share
+	 * the MessageSender
+	 */
+	public BotEventHandler()
+	{
+		sender = new MessageSender();
+	}
+
+
+    public boolean messageReceived(MessageSupport connection, Message message) {
+        if (message.isOutgoing()) // Not doing anything with outgoing messages
+            return true;
+        try {
+        	// lookup the student's username based on the contact name
+        	String username = names.get(message.getContact().getName());
+
+            String line = GeneralUtils.stripHTML(message.getText());
+            //System.out.println(message.getContact().getName()+ " says: " + message.getPlainText());
+
+            String reply = "";
+            if (line.startsWith("status"))
+            {
+            	reply = "up! " + new Date();
+            }
+            else if (line.equals("help"))
+            {
+            	reply = "Here are the commands I currently understand: \n\r";
+            	reply += "status: get the current date/time\n\r";
+            	reply += "shutdown: shut down the server\n\r";
+            	reply += "errors [assignment]: list all your errors for the specified assignment\n\r";
+            	reply += "explain [error]: explain what the error means\n\r";
+            	reply += "suggest friend: suggest the name of a student with similar errors\n\r";
+            	reply += "login [username]: log in to the system with your username";
+
+            }
+            else if (line.equals("shutdown"))
+            {
+                    connection.sendMessage(new MessageImpl(message.getContact(), true, "shutting down."));
+                    Thread.sleep(1000); // Let it finalize communications.
+                    connection.disconnect(true);
+                    System.exit(1);
+
+            }
+            else if (line.startsWith("errors"))
+            {
+        		String assignment = line.split(" ")[1];
+
+            	CompilationErrorEvent[] errors = dbmanager.getCompilationErrorEvents(username, assignment);
+
+        		if (errors == null || errors.length == 0)
+            	{
+            		reply = "You have made no compilation errors on assignment #" + assignment;
+            	}
+            	else if (errors.length == 1)
+            	{
+            		reply = "The only compilation error on assignment #" + assignment + " was " + errors[0];
+            	}
+            	else
+            	{
+            		reply = "You have made " + errors.length + " errors on assignment #" + assignment + ".\n\r";
+            		reply += "The most common error is " + dbmanager.getMostCommonCompilationError(username, assignment).getError();
+            	}
+            }
+            else if (line.startsWith("explain"))
+            {
+            	String error = line.replaceFirst("explain", "").trim();
+            	if (error.equals("; expected"))
+            	{
+            		reply = "That means you forgot to put a semicolon at the end of a line";
+            	}
+            	else if (error.equals("} expected"))
+            	{
+            		reply = "You probably forgot to put a curly brace at the end of a method";
+            	}
+            	else reply = "I'm sorry, I'm not sure what " + error + " means";
+            }
+            else if (line.equals("suggest friend"))
+            {
+            	Student user = smanager.suggestFriend(username);
+            	if (user == null) reply = "I'm sorry, I don't have any suggestions for you";
+            	else reply = user.getName() + " (" + user.getUni() + ") seems to be someone who is a similar programmer to you";
+            }
+            else if (line.contains("fuck"))
+            {
+            	reply = "You kiss your mother with that mouth?";
+            }
+            else if (line.startsWith("login"))
+            {
+            	username = line.split(" ")[1];
+
+            	// see if it's a valid username
+            	String name = dbmanager.getStudentName(username);
+            	if (name != null)
+            	{
+            		// map the IM name to the username
+            		names.put(message.getContact().getName(), username);
+            		// map the username to the IM connection
+            		sender.map(username, connection, message);
+
+            		// pull out the first name, instead of the whole name
+            		name = name.split(" ")[0];
+            		reply = "Hello, " + name + ", welcome to Retina Help.";
+            	}
+            	else
+            	{
+            		reply = "I'm sorry, I don't recognize that username";
+            	}
+            }
+            else if (line.startsWith("hello"))
+            {
+            	if (username == null)
+            	{
+            		reply = "Hello, " + message.getContact().getName() + ", it's nice to meet you. Use the \"login\" command to log in";
+            	}
+            	else
+            	{
+            		reply = "Hello, " + username + ", let me know if I can be of any help.";
+            	}
+            }
+            else
+            {
+            	reply = "I'm sorry, I don't understand '" + line + "'\nType 'help' if you need help";
+            }
+
+            // now send the reply
+            connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+
+
+        }
+        catch (InterruptedException e)
+        {
+            System.out.println("Failed while processing a message.");
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+
+
+	public void connectionEstablished(Connection arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void connectionFailed(Connection arg0, String arg1) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void connectionInitiated(Connection arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void connectionLost(Connection arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public boolean contactRequestReceived(String arg0, MessageSupport arg1) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public boolean emailReceived(MessageSupport arg0, Message arg1) throws Exception {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void errorOccured(String arg0, Exception arg1) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void fileReceiveRequested(FileTransferSupport arg0, Contact arg1, String arg2, String arg3, Object arg4) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void pictureReceived(IconSupport arg0, Contact arg1) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void statusChanged(Connection arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void statusChanged(Connection arg0, Contact arg1, boolean arg2, boolean arg3, int arg4) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void typingNotificationReceived(MessageSupport arg0, Nameable arg1) {
+		// TODO Auto-generated method stub
+
+	}
+}
\ No newline at end of file
diff --git a/retina/db/DatabaseManager.java b/retina/db/DatabaseManager.java
index e317282..442999e 100644
--- a/retina/db/DatabaseManager.java
+++ b/retina/db/DatabaseManager.java
@@ -165,6 +165,44 @@ public class DatabaseManager extends DatabaseConnector implements DatabaseReader
 		return null;
 	}

+	/**
+	 * This method looks up a student's name, given their UNI
+	 */
+	public String getStudentName(String uni)
+	{
+		try
+		{
+			con = getConnection();
+
+			if (con != null)
+			{
+				// create a Statement
+				Statement stmt = con.createStatement();
+
+				// now create the SQL query
+				String query = "SELECT name FROM students WHERE uni = '" + uni + "'";
+
+				// execute the query
+				ResultSet rs = stmt.executeQuery(query);
+				//System.out.println("Executed " + query);
+
+				if (rs.next())
+				{
+					return rs.getString("name");
+				}
+			}
+		}
+		catch(Exception e)
+		{
+			e.printStackTrace();
+		}
+		finally
+		{
+			closeConnection();
+		}
+		return null;
+
+	}

 	/**
 	 * This method returns the list of all assignment IDs.
@@ -258,10 +296,7 @@ public class DatabaseManager extends DatabaseConnector implements DatabaseReader
 				// String query = "INSERT INTO compilation_errors (student, assignment, date, error, message) VALUES ('" + e.getUser() + "', '" + assignment + "', '" + e.getTime() + "', '" + e.getError() + "', '" + e.getMessage() + "')";

 				stmt.setString(1, e.getUser());
-
-				// TODO: what if we don't know the assignment number??
-				stmt.setString(2, e.getAssignment().equals("unknown") ? "1" : e.getAssignment());
-
+				stmt.setString(2, e.getAssignment());
 				stmt.setString(3, e.getTime());
 				stmt.setString(4, e.getError());
 				stmt.setString(5, e.getMessage());
@@ -305,10 +340,8 @@ public class DatabaseManager extends DatabaseConnector implements DatabaseReader

 				// now create the SQL query
 				String success = e.isSuccessful() ? "TRUE" : "FALSE";
-				// TODO: how do we get the assignment?
-				String assignment = e.getAssignment().equals("unknown") ? "1" : e.getAssignment();

-				String query = "INSERT INTO compilations (student, assignment, date, success) VALUES ('" + e.getUser() + "', '" + assignment + "', '" + e.getTime() + "', '" + success + "')";
+				String query = "INSERT INTO compilations (student, assignment, date, success) VALUES ('" + e.getUser() + "', '" + e.getAssignment() + "', '" + e.getTime() + "', '" + success + "')";

 				// execute the query
 				stmt.executeUpdate(query);
@@ -348,11 +381,11 @@ public class DatabaseManager extends DatabaseConnector implements DatabaseReader
 				Statement stmt = con.createStatement();

 				// now create the SQL query
-				String query = "SELECT date, error, message FROM compilation_errors WHERE student = '" + user + "' AND assignment = '" + assignment + "' ORDER BY assignment";
+				String query = "SELECT date, error, message FROM compilation_errors WHERE student = '" + user + "' AND assignment = '" + assignment + "' ORDER BY date";

 				// execute the query
 				ResultSet rs = stmt.executeQuery(query);
-				// System.out.println("Executed " + query);
+				//System.out.println("Executed " + query);

 				// we can't actually know the size of the ResultSet in advance
 				// so we can't create an array... yet
diff --git a/retina/db/MessageSender.java b/retina/db/MessageSender.java
new file mode 100644
index 0000000..6cdd030
--- /dev/null
+++ b/retina/db/MessageSender.java
@@ -0,0 +1,103 @@
+package retina.db;
+
+import java.util.HashMap;
+
+import com.itbs.aimcer.bean.MessageImpl;
+import com.itbs.aimcer.bean.Message;
+import com.itbs.aimcer.commune.MessageSupport;
+import retina.common.CompilationErrorEvent;
+
+/**
+ * This class contains methods for sending instant messages to the students "asynchronously",
+ * i.e. not responding to messages but rather sending them whenever needed.
+ *
+ */
+
+public class MessageSender
+{
+	// maps Retina usernames to IM connections
+	private HashMap<String, MessageSupport> connections = new HashMap<String, MessageSupport>();
+	// maps Retina usernames to IM messages (not sure what those are, though...)
+	private HashMap<String, Message> messages = new HashMap<String, Message>();
+
+	// for accessing the database
+	private DatabaseManager manager = new DatabaseManager();
+
+	public void map(String username, MessageSupport connection, Message message)
+	{
+		connections.put(username, connection);
+		messages.put(username, message);
+	}
+
+    /**
+     * This method returns an instant messaging connection to the specified user
+     */
+    public MessageSupport getConnection(String username)
+    {
+    	return connections.get(username);
+    }
+
+    /**
+     * This method returns the IM message used to send something to the user
+     */
+    public Message getMessage(String username)
+    {
+    	return messages.get(username);
+    }
+
+	/**
+	 * This method should be called whenever some compilation errors have been processed
+	 */
+	public void handleCompilationErrorEvents(CompilationErrorEvent[] events)
+	{
+		// get the username
+		String username = events[0].getUser();
+
+		// get the stuff we need to send a message
+		MessageSupport connection = getConnection(username);
+		Message message = getMessage(username);
+
+		// only send if we can figure out who the user is, of course
+		if (connection != null && message != null)
+		{
+			String reply = null;
+			if (events.length == 0)
+			{
+				reply = "Compilation successful! Good job!";
+				connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+			}
+			else
+			{
+				// generate an appropriate message based on the compilation errors
+				if (events.length == 1)
+					reply = "You made one compilation error.";
+				else
+					reply = "You made " + events.length + " compilation errors.";
+				connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+
+				/*
+				// get the most common error for this assignment
+				CompilationErrorEvent error = manager.getMostCommonCompilationError(username, events[0].getAssignment());
+				reply = "Your most common error on this assignment is '" + error.getError() + "'";
+				connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+				*/
+
+				CompilationErrorEvent error = events[0];
+				//System.out.println("ERROR IS " + error.getError());
+				if (error.getError().equals("cannot find symbol"))
+				{
+					reply = "You may be forgetting to declare variables or perhaps are just misspelling variable/method names";
+					connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+				}
+				else if (error.getError().equals("';' expected"))
+				{
+					reply = "Don't forget to end each line with a semi-colon";
+					connection.sendMessage(new MessageImpl(message.getContact(), true, reply));
+				}
+
+
+			}
+		}
+	}
+
+}
diff --git a/retina/db/Retina.java b/retina/db/Retina.java
new file mode 100644
index 0000000..0fca678
--- /dev/null
+++ b/retina/db/Retina.java
@@ -0,0 +1,124 @@
+package retina.db;
+import javax.swing.Icon;
+
+import com.itbs.aimcer.bean.*;
+import com.itbs.aimcer.commune.Connection;
+import com.itbs.aimcer.commune.MessageSupport;
+import com.itbs.aimcer.commune.msn.*;
+import com.itbs.aimcer.commune.smack.*;
+import com.itbs.aimcer.commune.ymsg.*;
+import com.itbs.util.GeneralUtils;
+
+class GroupImplFactory implements GroupFactory {
+            public Group create(String group) {
+                return new GroupImpl();
+            }
+            public Group create(Group group) {
+                return new GroupImpl();
+            }
+			public GroupList getGroupList() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+    }
+    class GroupImpl implements Group {
+        public int size() { return 0; }
+        public void clear(Connection connection) { }
+        public Nameable get(int index) { return null; }
+        public Nameable add(Nameable contact) { return null; }
+        public boolean remove(Nameable contact) { return false; }
+        public String getName() { return "Group"; }
+		public Nameable[] toArray() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+    }
+
+
+    class ContactImplFactory implements ContactFactory {
+            public Contact create(Nameable buddy, Connection connection) {
+                return create(buddy.getName(), connection);
+            }
+
+
+            public Contact create(String name, Connection connection) {
+                return new ContactImpl(connection, name);
+            }
+
+
+            public Contact get(String name, Connection connection) {
+                return new ContactImpl(connection, name);
+            }
+    }
+
+
+    class ContactImpl implements Contact {
+        private final Status status = new StatusImpl(this);
+        private final Connection connection;
+        private final String name;
+
+
+        public ContactImpl(Connection connection, String name) {
+            this.connection = connection;
+            this.name = name;
+        }
+        public void statusChanged() {}
+        public Icon getIcon() { return null; }
+        public void setIcon(Icon icon) {}
+        public Icon getPicture() { return null; }
+        public void setPicture(Icon icon) { }
+        public String getDisplayName() { return name; }
+        public void setDisplayName(String name) {}
+        public Status getStatus() { return status; }
+        public Connection getConnection() { return connection; }
+        public String getName() { return name; }
+    }
+
+
+
+public class Retina {
+
+	public static void main(String[] args) throws Exception
+	{
+
+		/* Initialize shared objects */
+		MessageSender sender = new MessageSender();
+
+		/* Start the IM bot */
+
+		// for Yahoo
+		MessageSupport conn = new YMsgConnection();
+        conn.setUserName("retina_help");
+        conn.setPassword("retina.help123");
+
+        /*
+		// for MSN Messenger
+		MessageSupport conn = new MSNConnection();
+        conn.setUserName("retina.help@hotmail.com");
+        conn.setPassword("columbia.123");
+         */
+
+        conn.assignGroupFactory(new GroupImplFactory());
+        conn.assignContactFactory(new ContactImplFactory());
+
+        try {
+            conn.addEventListener(new BotEventHandler(sender));
+            conn.connect();
+            System.out.println("IM bot connected");
+        } catch (Exception e) {
+            System.out.println("Failed to create required pieces.  Shutting down.");
+            e.printStackTrace();
+            return; // No point waiting if connection isn't available
+        }
+
+        /* Now, start the XmlServer to listen for incoming data */
+        XmlServer xs = new XmlServer(1234, sender);
+        xs.start();
+
+        while (true) { // Simplified version of "stick around" wait
+            //System.out.println("waiting");
+            GeneralUtils.sleep(60*60*1000);
+        }
+    } // main()
+
+}
diff --git a/retina/db/SuggestionManager.java b/retina/db/SuggestionManager.java
new file mode 100644
index 0000000..423d68f
--- /dev/null
+++ b/retina/db/SuggestionManager.java
@@ -0,0 +1,62 @@
+package retina.db;
+import java.sql.*;
+import retina.common.Student;
+
+/***********************************************************************************
+ *
+ * This class holds all the code for dealing with suggestions of networks to join,
+ * people to get in touch with, etc.
+ *
+ * @author cmurphy
+ *
+ **********************************************************************************/
+
+
+public class SuggestionManager extends DatabaseManager
+{
+	public SuggestionManager() { }
+
+
+
+	/**
+	 *  For the user specified in the parameter, this method tries to find another
+	 *  user who has made similar errors.
+	 */
+	public Student suggestFriend(String user)
+	{
+		try
+		{
+			con = getConnection();
+
+			if (con != null)
+			{
+				// create a Statement
+				Statement stmt = con.createStatement();
+
+				// now create the SQL query
+				String query = "SELECT uni, name FROM students WHERE uni <> '" + user + "'";
+
+				// execute the query
+				ResultSet rs = stmt.executeQuery(query);
+				//System.out.println("Executed " + query);
+
+				if (rs.next())
+				{
+					// get the "name" column for this particular result
+					return new Student(rs.getString("uni").trim(), rs.getString("name").trim());
+				}
+				else return null;
+			}
+		}
+        catch(Exception e)
+        {
+			e.printStackTrace();
+		}
+		finally
+		{
+			closeConnection();
+		}
+
+		return null;
+	}
+}
diff --git a/retina/db/XMLLoader.java b/retina/db/XMLLoader.java
index 36082d3..2064c3a 100644
--- a/retina/db/XMLLoader.java
+++ b/retina/db/XMLLoader.java
@@ -19,8 +19,8 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;

-import retina.common.CompilationErrorEvent;
-import retina.common.CompilationEvent;
+import retina.common.CompilationErrorEvent;
+import retina.common.CompilationEvent;

 public class XMLLoader {

@@ -32,14 +32,26 @@ public class XMLLoader {

 	// the utility we'll use for writing to the database
 	private DatabaseWriter mgr = new DatabaseManager();
+
+	// used for sending messages
+	private MessageSender sender;

+	public XMLLoader()
+	{
+		sender = new MessageSender();
+	}
+
+	public XMLLoader(MessageSender ms)
+	{
+		sender = ms;
+	}

 	/**
 	 * This is the starting point for any other object that wants to use this one.
 	 * Specify the name of the file to read and then load into the database
 	 * @param file The full path to the file
 	 */
-	public void readAndLoad(String file) {
+	public void readAndLoad(String file) {

 		// reset the list of events
 		events = new ArrayList<CompilationErrorEvent>();
@@ -57,6 +69,8 @@ public class XMLLoader {
 			//System.out.println("Inserted");
 		}

+		// now send a message to the student
+		sender.handleCompilationErrorEvents(events.toArray(new CompilationErrorEvent[events.size()]));

 	}

@@ -167,7 +181,7 @@ public class XMLLoader {
 		}

 		// get the assignment number
-		String assignment = "unknown";
+		String assignment = null;
 		NodeList nl3 = empEl.getElementsByTagName("assignment");
 		if(nl3 != null && nl3.getLength() > 0) {
 				Element e = (Element)nl3.item(0);
@@ -176,6 +190,8 @@ public class XMLLoader {
 				//System.out.println(assignment);
 		}

+		// TODO: how do we get the assignment?
+		if (assignment == null) assignment = "1";

 		// records whether or not this was a successful compilation
 		boolean success = true;
diff --git a/retina/db/XmlServer.java b/retina/db/XmlServer.java
index 8b57cf8..c08d472 100644
--- a/retina/db/XmlServer.java
+++ b/retina/db/XmlServer.java
@@ -10,32 +10,39 @@ import java.io.*;
 import java.net.*;
 import java.util.Scanner;

-public class XmlServer
+
+public class XmlServer extends Thread
 {
     // the output stream for writing the file
     private PrintWriter out;

     // the input stream for reading from the network
-    private Scanner in;
+    private Scanner in;

     // the server
     private ServerSocket server;

     // the tool for writing to the database
-    private XMLLoader reader = new XMLLoader();
+    private XMLLoader loader;
+
+    // used for sending messages
+    private MessageSender sender;

     /* This is the main method for starting the Server */
     public static void main(String[] args)
     {
-		if (args.length < 1)
+    	int port = 1234;
+		if (args.length >= 1)
+		{
+			port = Integer.parseInt(args[0]);
+		}
+		else
 		{
-		    System.out.println("Please specify a port number!");
-		    System.exit(0);
+			System.out.println("Port not specified, using " + port + " as default");
 		}

-		int port = Integer.parseInt(args[0]);
 		XmlServer xs = new XmlServer(port);
-		xs.run();
+		xs.start();
     }

     /**
@@ -44,10 +51,24 @@ public class XmlServer
      */
     public XmlServer(int port)
     {
+    	sender = new MessageSender();
+    	loader = new XMLLoader(sender);
+    	init(port);
+    }
+
+    public XmlServer(int port, MessageSender ms)
+    {
+    	sender = ms;
+    	loader = new XMLLoader(sender);
+    	init(port);
+    }
+
+    private void init(int port)
+    {
 		try
 		{
 		    server = new ServerSocket(port);
-		    System.out.println("Server started... waiting for connection");
+		    System.out.println("XmlServer started... waiting for connection");
 		}
 		catch (Exception e)
 		{
@@ -55,7 +76,8 @@ public class XmlServer
 		    e.printStackTrace();
 		}
     }
-
+
+
     /**
      * This method does all the work
      */
@@ -68,14 +90,14 @@ public class XmlServer
     		{
     			// wait for a client
     			Socket socket = server.accept();
-    			System.out.println("Connection established");
+    			//System.out.println("Connection established");

     			// get the input stream
     			in = new Scanner(socket.getInputStream());

     			// the name of the file should be on the first line
     			String fileName = "_" + in.nextLine();
-    			System.out.println("File is " + fileName);
+    			//System.out.println("File is " + fileName);

     			// create the File object
     			File file = new File(fileName);
@@ -109,7 +131,7 @@ public class XmlServer
     			}

     			// we have the file, now write it to the database using the "XMLLoader"
-    			reader.readAndLoad(fileName);
+    			loader.readAndLoad(fileName);
     		}
     		catch (Exception e)
     		{