package open.dolphin.client; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonArrayBuilder; import javax.json.JsonObjectBuilder; import javax.json.JsonReader; import javax.json.JsonValue; import javax.json.JsonWriter; import javax.json.JsonWriterFactory; import javax.json.stream.JsonGenerator; import javax.swing.SwingWorker; import javax.websocket.ClientEndpoint; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Response; import javax.websocket.ContainerProvider; import javax.websocket.DeploymentException; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.WebSocketContainer; import open.dolphin.delegater.PHRDelegater; import open.dolphin.util.ZenkakuUtils; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; /** * * @author kazushi Minagawa */ @ClientEndpoint(subprotocols = {"layer-1.0"}) public final class PHRProxy implements MainService { private static final String LAYER_ROOT_URI = "https://api.layer.com"; private static final String LAER_APP_ID = "layer:///apps/staging/3a031e94-5c3b-11e5-b0e1-e9979f007fc5"; private static final String IDENTITY_SERVER_URI = "https://i18n.opendolphin.com:443/openDolphin/resources/20/adm/phr/identityToken"; // 患者毎にユニーク //private static final String CONVERSATION_UUID = "e0878218-2258-4778-8c9f-772c3b8d065e"; private static final String USER_ID = "kazushi"; private MainWindow context; private Session webSocketSession; private String session_token; public PHRProxy() { } private String getIdentityToken(String nonce, String userId) { String json = Json.createObjectBuilder() .add("nonce", nonce) .add("user", userId) .build() .toString(); ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target(IDENTITY_SERVER_URI); Response response = target.request().post(Entity.text(json)); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); return entity; } private ResteasyWebTarget getWebTarget(String path) { StringBuilder sb = new StringBuilder(); sb.append(LAYER_ROOT_URI); if (path.startsWith("/")) { sb.append(path); } else { sb.append("/").append(path); } String uri = sb.toString(); ResteasyClient client = new ResteasyClientBuilder().build(); client.register((ClientRequestFilter) (ClientRequestContext crc) -> { crc.getHeaders().add("Accept", "application/vnd.layer+json; version=1.0"); crc.getHeaders().add("Content-type", "application/json"); }); return client.target(uri); } private ResteasyWebTarget getWebTarget(String path, final String sessionToken) { StringBuilder sb = new StringBuilder(); sb.append(LAYER_ROOT_URI); if (path.startsWith("/")) { sb.append(path); } else { sb.append("/").append(path); } String uri = sb.toString(); ResteasyClient client = new ResteasyClientBuilder().build(); client.register((ClientRequestFilter) (ClientRequestContext crc) -> { StringBuilder sb1 = new StringBuilder(); sb1.append("Layer session-token="); sb1.append("'").append(sessionToken).append("'"); String token = sb1.toString(); crc.getHeaders().add("Accept", "application/vnd.layer+json; version=1.0"); crc.getHeaders().add("Content-type", "application/json"); crc.getHeaders().add("Authorization", token); }); return client.target(uri); } private Response postEasy(String path, String json) { getLogger().log(Level.INFO, "json={0}", json); ResteasyWebTarget target = getWebTarget(path); return target.request().post(Entity.text(json)); } private Response postEasy(String path, String sessionToken, String json) { getLogger().log(Level.INFO, "json={0}", json); ResteasyWebTarget target = getWebTarget(path, sessionToken); return target.request().post(Entity.text(json)); } private Response getEasy(String path, String sessionToken) { ResteasyWebTarget target = getWebTarget(path, sessionToken); return target.request().get(); } private String getNonce() { String path = "/nonces"; Response response = postEasy(path, ""); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); if (status/100 == 2) { JsonObject jso = getJsonObject(entity); return jso.getString("nonce"); } return null; } private String getSessionToken(String identityToken) { String path = "/sessions"; String json = Json.createObjectBuilder() .add("identity_token", identityToken) .add("app_id", LAER_APP_ID) .build() .toString(); Response response = postEasy(path, json); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status/100 == 2) { JsonObject jso = getJsonObject(entity); return jso.getString("session_token"); } else if (status==401) { return authenticationChallenge(entity); } else { throw new RuntimeException("Unknown HTTP error: " + status); } } private String authenticationChallenge(String json) { JsonObject jso = getJsonObject(json); printJson(jso); JsonObject data = jso.getJsonObject("data"); String nonce = data.getString("nonce"); String token = getIdentityToken(nonce, USER_ID); String session = getSessionToken(token); return session; } private void createConversation(String[] participants, boolean distinct) { JsonArrayBuilder arr = Json.createArrayBuilder(); for (String p : participants) { arr.add(p); } String json = Json.createObjectBuilder() .add("participants", arr) .add("distinct", distinct) .build() .toString(); String path = "/conversations"; Response response = postEasy(path, session_token, json); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status==401) { session_token = authenticationChallenge(entity); createConversation(participants, distinct); } } private void getConversation(String uuid) { StringBuilder sb = new StringBuilder(); sb.append("/conversations/").append(uuid); String path = sb.toString(); Response response = getEasy(path, session_token); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status/100==2) { JsonObject jsonObject = getJsonObject(entity); printJson(jsonObject); } else if (status==401) { session_token = authenticationChallenge(entity); getConversation(uuid); } } private void getAllMessages(String uuid) { StringBuilder sb = new StringBuilder(); sb.append("/conversations/").append(uuid).append("/messages"); String path = sb.toString(); Response response = getEasy(path, session_token); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status/100 ==2) { javax.json.JsonArray array = getJsonArray(entity); for (JsonValue value : array) { JsonObject jso = (JsonObject)value; JsonArray parts = jso.getJsonArray("parts"); JsonObject part = (JsonObject)parts.getJsonObject(0); if ("text/plain".equals(part.getString("mime_type"))) { getLogger().log(Level.INFO, "body={0}", part.getString("body")); } } } else if (status==401) { session_token = authenticationChallenge(entity); getAllMessages(uuid); } } private void getMessage(String uuid) { StringBuilder sb = new StringBuilder(); sb.append("/messages/").append(uuid); String path = sb.toString(); Response response = getEasy(path, session_token); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status/100 ==2) { JsonObject jsonObject = getJsonObject(entity); printJson(jsonObject); } else if (status==401) { session_token = authenticationChallenge(entity); getMessage(uuid); } } private void sendTextMessage(String conversation_UUID, String text) { JsonObjectBuilder msgObject = Json.createObjectBuilder(); msgObject.add("body", text); msgObject.add("mime_type", "text/plain"); JsonArrayBuilder arr = Json.createArrayBuilder(); arr.add(msgObject); String json = Json.createObjectBuilder().add("parts", arr).build().toString(); StringBuilder sb = new StringBuilder(); sb.append("/conversations/").append(conversation_UUID).append("/messages"); String path = sb.toString(); Response response = postEasy(path, session_token, json); int status = response.getStatus(); String entity = response.readEntity(String.class); log(status, entity); response.close(); if (status/100 ==2) { // } else if (status==401) { session_token = authenticationChallenge(entity); sendTextMessage(conversation_UUID, text); } } private String createTextMessage(String conversation_UUID, String text) { JsonObjectBuilder part = Json.createObjectBuilder(); part.add("body", text); part.add("mime_type", "text/plain"); JsonArrayBuilder parts = Json.createArrayBuilder(); parts.add(part); JsonObjectBuilder data = Json.createObjectBuilder(); data.add("parts", parts); JsonObjectBuilder body = Json.createObjectBuilder(); body.add("method", "Message.create"); body.add("request_id", UUID.randomUUID().toString()); // uuid body.add("object_id", conversation_UUID); body.add("data", data); JsonObjectBuilder msgObject = Json.createObjectBuilder(); msgObject.add("type", "request"); msgObject.add("body", body); JsonObject test = msgObject.build(); printJson(test); return test.toString(); } private JsonObject getJsonObject(String jsonStr) { JsonObject jsonObject; try (StringReader sr = new StringReader(jsonStr); JsonReader jsonReader = Json.createReader(sr)) { jsonObject = jsonReader.readObject(); } return jsonObject; } private void printJson(JsonObject jso) { Map<String, Object> properties = new HashMap<>(1); properties.put(JsonGenerator.PRETTY_PRINTING, true); StringWriter sw = new StringWriter(); JsonWriterFactory writerFactory = Json.createWriterFactory(properties); try (JsonWriter jsonWriter = writerFactory.createWriter(sw)) { jsonWriter.writeObject(jso); getLogger().log(Level.INFO, "json={0}", sw.toString()); } } private JsonArray getJsonArray(String jsonStr) { JsonArray jsonArray; try (StringReader sr = new StringReader(jsonStr); JsonReader jsonReader = Json.createReader(sr)) { jsonArray = jsonReader.readArray(); } return jsonArray; } private Logger getLogger() { return Logger.getLogger(this.getClass().getName()); } private void log(int status, String entity) { getLogger().log(Level.INFO, "status={0}", status); getLogger().log(Level.INFO, "entity={0}", entity); } private void sendPHRRequest(final String conversation_uuid, String sender, String dataType) { final String pid = sender.equals("shiho") ? "000008" : null; if (pid==null) { return; } SwingWorker worker; worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { PHRDelegater phrd = new PHRDelegater(); String text = phrd.getPHRdata(pid, dataType); text = ZenkakuUtils.toHalfNumber(text); sendTextMessage(conversation_uuid, text); return null; } }; worker.execute(); } @OnOpen public void onOpen(Session session) { getLogger().log(Level.INFO, "onOpen"); } @OnMessage public void onMessage(String message) { getLogger().log(Level.INFO, "onMessage"); JsonObject jso = getJsonObject(message); printJson(jso); // type String type = jso.getString("type"); // change, request, response, signal JsonObject body = jso.getJsonObject("body"); String timestamp = jso.getString("timestamp"); int counter = jso.getInt("counter"); if (!"change".equals(type)) { return; } if (!"create".equals(body.getString("operation"))) { // create, delete, update return; } if (!"Message".equals(body.getJsonObject("object").getString("type"))) { // Conversation, Message return; } JsonArray parts = body.getJsonObject("data").getJsonArray("parts"); JsonObject part0 = parts.getJsonObject(0); if (!"text/plain".equals(part0.getString("mime_type"))) { return; } String sender = body.getJsonObject("data").getJsonObject("sender").getString("user_id"); if (USER_ID.equals(sender)) { return; } // Conversatuin ID String conversation_uuid = body.getJsonObject("data").getJsonObject("conversation").getString("id"); int index = conversation_uuid.lastIndexOf("/"); if (index <= 0) { return; } conversation_uuid = conversation_uuid.substring(index + 1); String text = part0.getString("body"); if (text.equals("処方") || text.equals("検査") || text.equals("病名") || text.equals("アレルギー")) { sendPHRRequest(conversation_uuid, sender, text); } } @OnError public void onError(Throwable t) { getLogger().log(Level.SEVERE, null, t); } @OnClose public void onClose(Session session) { getLogger().log(Level.INFO, "onClose"); } @Override public String getName() { return "PHR Proxy"; } @Override public void setName(String name) { } @Override public MainWindow getContext() { return context; } @Override public void setContext(MainWindow context) { this.context = context; } @Override public void start() { String nonce = this.getNonce(); String token = this.getIdentityToken(nonce, USER_ID); session_token = this.getSessionToken(token); try { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); URI uri = URI.create("wss://api.layer.com/websocket?session_token="+session_token); webSocketSession = container.connectToServer(this, uri); } catch (DeploymentException | IOException ex) { Logger.getLogger(PHRProxy.class.getName()).log(Level.SEVERE, null, ex); } } @Override public void stop() { try { if (webSocketSession!=null) { webSocketSession.close(); } } catch (IOException ex) { Logger.getLogger(PHRProxy.class.getName()).log(Level.SEVERE, null, ex); } } }