People,
I am making a little progress learning Rust and the success of this "concept exercise":
has prompted me to continue the effort. I have some old (paid for) Java chatbot code and, some years ago I thought of getting it re-written entirely in Rust but real-world issues demanded attention and I never made any more progress with the idea. Now that I am attempting to learn Rust myself, it occurred to me that, as an exercise mostly, I could just re-write a small module of the Java code instead of the whole application. I attach the module in question below but I think my options are now:
-
If the conversion to Rust is sensibly doable, try and do the work myself - however, I am entirely unenthusiastic about having to learn Java as well so this may not be a good use of my time in terms of making good progress learning Rust . .
-
If the conversion to Rust is sensibly doable but the effort is really beyond me, so just pay a guru to do it - if it is not going to break the bank . . This would be nice but not critical . .
-
Since it is mostly an exercise, although the conversion might be doable, it might still be a waste of time so I should concentrate my Rust learning elsewhere . .
Feedback appreciated!
Regards,
Phil.
package com.thisiscool.honesty.server;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import com.thisiscool.honesty.common.PropertiesManager;
import com.thisiscool.honesty.common.Sex;
import com.thisiscool.honesty.knowledge.Knowledge;
import com.thisiscool.honesty.model.HModel;
import com.thisiscool.honesty.model.types.HInstance;
import com.thisiscool.honesty.model.types.HValue;
import com.thisiscool.honesty.process.ConversationSessionData;
import com.thisiscool.honesty.process.MainLoop;
import com.thisiscool.honesty.process.NosyGoal;
import com.thisiscool.honesty.subject.SubjectsManager;
public class HonestyServer
{
public static void main(String[] args) throws IOException
{
PropertiesManager pm = PropertiesManager.instance();
int port = pm.getIntApplicationProperty("app.honesty.port");
int poolSize = pm.getIntApplicationProperty("app.honesty.poolsize");
HonestyServer hs = new HonestyServer(port, poolSize);
hs.run();
}
public HonestyServer(int port, int poolSize) throws IOException
{
serverSocket = new ServerSocket(port);
pool =
new ThreadPoolExecutor(1, poolSize,
2, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>());
}
public final void run()
{
try
{
mainLoop = new MainLoop();
mainLoop.init();
try
{
System.out.println("Honesty Server ready for action!");
for (;;)
{
pool.execute(new Handler(serverSocket.accept()));
}
}
catch (IOException ex)
{
pool.shutdown();
}
finally
{
serverSocket.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
// private //
private static final String SHUTDOWN = "!@#$%^*!@^T$%&#@SHUTDOWN";
private static final String ERROR = "Malformed request.";
@SuppressWarnings("unchecked")
private static String toJSONString(Collection<HInstance> instances)
{
JSONArray result = new JSONArray();
for (HInstance instance : instances)
{
Map<String,String> inst = new HashMap<String,String>();
inst.put("uuid", instance.getUUID());
inst.put("name", instance.getName());
inst.put("friendly_name", instance.getFriendlyName());
HInstance parent = instance.getParent();
if (parent == null)
inst.put("parent", "null");
else
inst.put("parent", parent.getUUID());
result.add(inst);
}
return result.toJSONString();
}
private final ServerSocket serverSocket;
private final ExecutorService pool;
private MainLoop mainLoop;
private SessionManager sessionManager = new SessionManager();
private String handle(String request)
{
JSONObject input = (JSONObject) JSONValue.parse(request);
if (input == null)
return ERROR;
String sessionId = (String) input.get("session_id");
String message = (String) input.get("message");
String subjectName = null;
if (input.get("commands") != null)
{
JSONObject cmds = (JSONObject) input.get("commands");
if (cmds != null)
{
String name = (String) cmds.get("name");
if (name != null)
{
subjectName = name;
if (subjectName.toLowerCase().startsWith("future "))
subjectName = subjectName.substring(7);
}
}
}
boolean create = false;
if (sessionId.startsWith("@"))
{
create = true;
sessionId = sessionId.substring(1);
}
if (message!=null && message.equals(SHUTDOWN))
{
sessionManager.dispose(sessionId);
return "OK";
}
else
{
ConversationSessionData csd =
sessionManager.getSessionDataFor(sessionId, create, mainLoop);
if (csd == null)
return "@@BAD SESSION";
String result = "@@BAD RESPONSE";
synchronized (csd)
{
// new name?
if (subjectName != null)
{
SubjectsManager sm = csd.getSubjectsManager();
String current = sm.getSubjectName();
if (current==null || !current.equalsIgnoreCase(subjectName))
sm.setSubjectName(subjectName);
}
if (input.get("chip_cmd") != null)
{
result = handleChipCommand(input, csd);
}
else
{
result = mainLoop.submit(message, csd);
sessionManager.save(sessionId, csd);
}
}
return result;
}
}
private String handleChipCommand(JSONObject input, ConversationSessionData csd)
{
String chipCmd = (String) input.get("chip_cmd");
String result = null;
if (chipCmd.equals("retrieve_instances"))
{
result = handleRetrieveInstances(input,csd);
}
else if (chipCmd.equals("set_current_instance"))
{
result = handleSetCurrentInstance(input,csd);
}
else if (chipCmd.equals("create_instance"))
{
result = handleCreateInstance(input,csd);
}
if (result == null)
return "{\"error\": \"Unknown command\"}";
else
return result;
}
private String handleRetrieveInstances(JSONObject input, ConversationSessionData csd)
{
Set<HInstance> instances = csd.getExecutionEngine().getInstances();
return toJSONString(instances);
}
private String handleSetCurrentInstance(JSONObject input, ConversationSessionData csd)
{
String uuid = (String) input.get("uuid");
// Does it exist?
String result = null;
HInstance instance = csd.getExecutionEngine().findByUUID(uuid);
if (instance == null)
{
result = "{\"error\": \"No such instance\"}";
}
else
{
csd.getExecutionEngine().setFocusedInstance(instance);
result = "{\"status\": \"success\"}";
}
return result;
}
private String handleCreateInstance(JSONObject input, ConversationSessionData csd)
{
String parentUUID = (String) input.get("parent_uuid");
String type = (String) input.get("type");
String name = (String) input.get("name");
String result = null;
HInstance parent = csd.getExecutionEngine().findByUUID(parentUUID);
if (parent == null)
{
result = "{\"error\": \"No such parent instance\"}";
}
else
{
HModel model = parent.getType().getModel();
String field = NosyGoal.findFieldFor(model, type);
if (field == null)
{
result = "{\"error\": \"Unsupported child instance type: "+type+"\"}";
}
else
{
Sex sex = Knowledge.getSexFor(csd.getGoalManager(), type);
HInstance[] instances = parent.addQualified(field, 1, type, sex);
if (name != null)
{
for (HInstance instance : instances)
{
instance.set("name", name);
}
}
// adjust the backpointers for mother or father depending on the sex of the parent
if (type.equals("son") || type.equals("daughter"))
{
for (HInstance instance : instances)
{
HValue hval = parent.get("sex");
if (hval != null)
{
Sex parentSex = Sex.UNKNOWN;
String current = hval.toString();
if (current.equals("male"))
parentSex = Sex.MALE;
else if (current.equals("female"))
parentSex = Sex.FEMALE;
switch (parentSex)
{
case MALE:
instance.getEngine().remove((HInstance) instance.get("father"));
instance.set("father", parent);
break;
case FEMALE:
instance.getEngine().remove((HInstance) instance.get("mother"));
instance.set("mother", parent);
break;
}
}
}
}
result = toJSONString(Arrays.asList(instances));
}
}
return result;
}
////////////////////////////////////////////////////////////////
// inner class Handler
private class Handler implements Runnable
{
// Runnable overrides
public final void run()
{
try
{
PrintStream strmOut = new PrintStream(
new BufferedOutputStream(socket
.getOutputStream()));
BufferedReader rdrIn = new BufferedReader(
new InputStreamReader(socket
.getInputStream()));
// Receive request
String request = rdrIn.readLine();
//@LOG@ System.out.println("Got " + request);
// Determine and send response
String reply = handle(request);
strmOut.println(reply);
strmOut.println("@@END_OF_REPLY");
//@LOG@ System.out.println(" ...sent reply: "+reply);
strmOut.close();
rdrIn.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch (IOException e)
{}
}
}
// "internal" //
Handler(Socket socket)
{
this.socket = socket;
}
// private //
private final Socket socket;
}
// end inner class Handler
////////////////////////////////////////////////////////////////
}