Mercurial > hg > release > thermostat-0.7
changeset 704:77998c10737b
Implement WebUpdate.
Reviewed-by: omajid
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003764.html
author | Roman Kennke <rkennke@redhat.com> |
---|---|
date | Fri, 19 Oct 2012 19:53:15 +0200 |
parents | 1dd0ea9aa8b4 |
children | 498473c85300 |
files | common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java web/common/src/main/java/com/redhat/thermostat/web/common/WebUpdate.java web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageEndpointTest.java |
diffstat | 6 files changed, 324 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Thu Oct 18 00:25:04 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Fri Oct 19 19:53:15 2012 +0200 @@ -332,11 +332,6 @@ collectionCache.put(name, coll); } - private void createConnectionKey(Category category) { - // TODO: There is probably some better place to do this, perhaps related to the inner class - // idea mentioned below. - } - @Override public Query createQuery() { return new MongoQuery();
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java Thu Oct 18 00:25:04 2012 +0200 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java Fri Oct 19 19:53:15 2012 +0200 @@ -47,7 +47,9 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -63,6 +65,7 @@ import com.redhat.thermostat.web.common.RESTQuery; import com.redhat.thermostat.web.common.WebInsert; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; public class RESTStorage extends Storage { @@ -83,7 +86,6 @@ } @Override public String getUrl() { - // TODO Auto-generated method stub return endpoint; } } @@ -138,9 +140,8 @@ } @Override - public Update createUpdate() { - // TODO Auto-generated method stub - return null; + public WebUpdate createUpdate() { + return new WebUpdate(categoryIds); } @Override @@ -283,9 +284,31 @@ } @Override - public void updatePojo(Update arg0) { - // TODO Auto-generated method stub - + public void updatePojo(Update update) { + WebUpdate webUp = (WebUpdate) update; + try { + URL url = new URL(endpoint + "/update-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + Gson gson = new Gson(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("update="); + writer.write(URLEncoder.encode(gson.toJson(webUp), "UTF-8")); + List<WebUpdate.UpdateValue> updateValues = webUp.getUpdates(); + List<Object> values = new ArrayList<>(updateValues.size()); + for (WebUpdate.UpdateValue updateValue : updateValues) { + values.add(updateValue.getValue()); + } + writer.write("&values="); + writer.write(URLEncoder.encode(gson.toJson(values), "UTF-8")); + writer.flush(); + checkResponseCode(conn); + } catch (IOException ex) { + throw new RuntimeException(ex); + } } public void setEndpoint(String endpoint) {
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java Thu Oct 18 00:25:04 2012 +0200 +++ b/web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java Fri Oct 19 19:53:15 2012 +0200 @@ -40,6 +40,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; @@ -66,6 +67,8 @@ import org.junit.Test; import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.redhat.thermostat.common.storage.Categories; import com.redhat.thermostat.common.storage.Category; @@ -80,6 +83,7 @@ import com.redhat.thermostat.web.common.RESTQuery; import com.redhat.thermostat.web.common.WebInsert; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; public class RESTStorageTest { @@ -93,12 +97,14 @@ private static Category category; private static Key<String> key1; + private static Key<Integer> key2; private RESTStorage storage; @BeforeClass public static void setupCategory() { key1 = new Key<>("property1", true); + key2 = new Key<>("property2", true); category = new Category("test", key1); } @@ -294,4 +300,76 @@ assertEquals(Criteria.EQUALS, qualifier.getCriteria()); assertEquals("test", qualifier.getValue()); } + + @Test + public void testCreateUpdate() { + WebUpdate update = (WebUpdate) storage.createUpdate(); + assertNotNull(update); + update = update.from(category); + assertEquals(42, update.getCategoryId()); + assertNotNull(update); + update = update.where(key1, "test"); + assertNotNull(update); + List<Qualifier<?>> qualifiers = update.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + update = update.set(key1, "fluff"); + assertNotNull(update); + List<WebUpdate.UpdateValue> updates = update.getUpdates(); + assertEquals(1, updates.size()); + assertEquals("fluff", updates.get(0).getValue()); + assertEquals(key1, updates.get(0).getKey()); + assertEquals("java.lang.String", updates.get(0).getValueClass()); + } + + @Test + public void testUpdate() throws UnsupportedEncodingException, IOException, JsonSyntaxException, ClassNotFoundException { + + WebUpdate update = storage.createUpdate().from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); + storage.updatePojo(update); + + Gson gson = new Gson(); + StringReader reader = new StringReader(requestBody); + BufferedReader bufRead = new BufferedReader(reader); + String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); + String [] params = line.split("&"); + assertEquals(2, params.length); + String[] parts = params[0].split("="); + assertEquals("update", parts[0]); + WebUpdate receivedUpdate = gson.fromJson(parts[1], WebUpdate.class); + assertEquals(42, receivedUpdate.getCategoryId()); + + List<WebUpdate.UpdateValue> updates = receivedUpdate.getUpdates(); + assertEquals(2, updates.size()); + + WebUpdate.UpdateValue update1 = updates.get(0); + assertEquals(key1, update1.getKey()); + assertEquals("java.lang.String", update1.getValueClass()); + assertNull(update1.getValue()); + + WebUpdate.UpdateValue update2 = updates.get(1); + assertEquals(key2, update2.getKey()); + assertEquals("java.lang.Integer", update2.getValueClass()); + assertNull(update2.getValue()); + + List<Qualifier<?>> qualifiers = receivedUpdate.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + + parts = params[1].split("="); + assertEquals(2, parts.length); + assertEquals("values", parts[0]); + JsonParser jsonParser = new JsonParser(); + JsonArray jsonArray = jsonParser.parse(parts[1]).getAsJsonArray(); + String value1 = gson.fromJson(jsonArray.get(0), String.class); + assertEquals("fluff", value1); + int value2 = gson.fromJson(jsonArray.get(1), Integer.class); + assertEquals(42, value2); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/WebUpdate.java Fri Oct 19 19:53:15 2012 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.web.common; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Update; +import com.redhat.thermostat.common.storage.Query.Criteria; + +public class WebUpdate implements Update { + + public static class UpdateValue { + private Key<?> key; + private transient Object value; + private String valueClass; + + public UpdateValue() { + this(null, null); + } + + public UpdateValue(Key<?> key, Object value) { + this.key = key; + this.value = value; + if (value != null) { + valueClass = value.getClass().getName(); + } + } + + public Key<?> getKey() { + return key; + } + + public void setKey(Key<?> key) { + this.key = key; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getValueClass() { + return valueClass; + } + + public void setValueClass(String valueClass) { + this.valueClass = valueClass; + } + + } + + private transient Map<Category, Integer> categoryIds; + private Integer categoryId; + private List<Qualifier<?>> qualifiers; + private List<UpdateValue> updateValues; + + // NOTE: This is needed for de-serialization! + public WebUpdate() { + this(null); + } + + public WebUpdate(Map<Category, Integer> categoryIds) { + qualifiers = new ArrayList<>(); + updateValues = new ArrayList<>(); + this.categoryIds = categoryIds; + } + + @Override + public WebUpdate from(Category category) { + categoryId = categoryIds.get(category); + return this; + } + + @Override + public <T> WebUpdate where(Key<T> key, T value) { + qualifiers.add(new Qualifier<T>(key, Criteria.EQUALS, value)); + return this; + } + + @Override + public <T> WebUpdate set(Key<T> key, T value) { + updateValues.add(new UpdateValue(key, value)); + return this; + } + + public int getCategoryId() { + return categoryId; + } + + public List<Qualifier<?>> getQualifiers() { + return qualifiers; + } + + public List<WebUpdate.UpdateValue> getUpdates() { + return updateValues; + } +}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java Thu Oct 18 00:25:04 2012 +0200 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java Fri Oct 19 19:53:15 2012 +0200 @@ -13,18 +13,23 @@ import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonParser; import com.redhat.thermostat.common.model.Pojo; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; +import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; +import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.Remove; import com.redhat.thermostat.common.storage.Storage; -import com.redhat.thermostat.common.storage.Query.Criteria; +import com.redhat.thermostat.common.storage.Update; import com.redhat.thermostat.web.common.Qualifier; import com.redhat.thermostat.web.common.RESTQuery; import com.redhat.thermostat.web.common.StorageWrapper; import com.redhat.thermostat.web.common.WebInsert; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; @SuppressWarnings("serial") public class RESTStorageEndPoint extends HttpServlet { @@ -61,6 +66,8 @@ registerCategory(req, resp); } else if (cmd.equals("remove-pojo")) { removePojo(req, resp); + } else if (cmd.equals("update-pojo")) { + updatePojo(req, resp); } } @@ -115,8 +122,40 @@ targetRemove = targetRemove.where(qualifier.getKey(), qualifier.getValue()); } storage.removePojo(targetRemove); + resp.setStatus(HttpServletResponse.SC_OK); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void updatePojo(HttpServletRequest req, HttpServletResponse resp) { + try { + String updateParam = req.getParameter("update"); + WebUpdate update = gson.fromJson(updateParam, WebUpdate.class); + Update targetUpdate = storage.createUpdate(); + targetUpdate = targetUpdate.from(getCategoryFromId(update.getCategoryId())); + List<Qualifier<?>> qualifiers = update.getQualifiers(); + for (Qualifier qualifier : qualifiers) { + assert (qualifier.getCriteria() == Criteria.EQUALS); + targetUpdate = targetUpdate.where(qualifier.getKey(), qualifier.getValue()); + } + String valuesParam = req.getParameter("values"); + JsonParser parser = new JsonParser(); + JsonArray jsonArray = parser.parse(valuesParam).getAsJsonArray(); + List<WebUpdate.UpdateValue> updates = update.getUpdates(); + int index = 0; + for (WebUpdate.UpdateValue updateValue : updates) { + Class valueClass = Class.forName(updateValue.getValueClass()); + Object value = gson.fromJson(jsonArray.get(index), valueClass); + index++; + Key key = updateValue.getKey(); + targetUpdate.set(key, value); + } + storage.updatePojo(targetUpdate); + resp.setStatus(HttpServletResponse.SC_OK); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } @SuppressWarnings({ "rawtypes", "unchecked" }) private void findPojo(HttpServletRequest req, HttpServletResponse resp) throws IOException {
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageEndpointTest.java Thu Oct 18 00:25:04 2012 +0200 +++ b/web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageEndpointTest.java Fri Oct 19 19:53:15 2012 +0200 @@ -73,6 +73,7 @@ import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.Remove; import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.common.storage.Update; import com.redhat.thermostat.test.FreePortFinder; import com.redhat.thermostat.test.FreePortFinder.TryPort; import com.redhat.thermostat.web.client.RESTStorage; @@ -80,6 +81,7 @@ import com.redhat.thermostat.web.common.StorageWrapper; import com.redhat.thermostat.web.common.WebInsert; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; public class RESTStorageEndpointTest { @@ -283,6 +285,42 @@ verify(mockStorage).removePojo(mockRemove); } + @Test + public void testUpdatePojo() throws IOException { + + Update mockUpdate = mock(Update.class); + when(mockUpdate.from(any(Category.class))).thenReturn(mockUpdate); + when(mockUpdate.where(any(Key.class), any())).thenReturn(mockUpdate); + when(mockUpdate.set(any(Key.class), any())).thenReturn(mockUpdate); + when(mockStorage.createUpdate()).thenReturn(mockUpdate); + + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/update-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + Map<Category,Integer> categoryIds = new HashMap<>(); + categoryIds.put(category, categoryId); + WebUpdate update = new WebUpdate(categoryIds).from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("update="); + gson.toJson(update, out); + out.write("&values="); + gson.toJson(new Object[] {"fluff", 42 }, out); + out.write("\n"); + out.flush(); + + assertEquals(200, conn.getResponseCode()); + verify(mockStorage).createUpdate(); + verify(mockUpdate).from(category); + verify(mockUpdate).where(key1, "test"); + verify(mockUpdate).set(key1, "fluff"); + verify(mockUpdate).set(key2, 42); + verify(mockStorage).updatePojo(mockUpdate); + } + private void registerCategory() { try {