Mercurial > hg > release > thermostat-0.15
changeset 1227:19edbf121251
Use where expressions for Replace.
Reviewed-by: omajid
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-August/008004.html
line wrap: on
line diff
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedStorage.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedStorage.java Thu Aug 22 15:05:29 2013 +0200 @@ -38,6 +38,7 @@ package com.redhat.thermostat.storage.core; import java.io.InputStream; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -52,13 +53,20 @@ private class QueuedReplace extends BasePut implements Replace { + private Expression expression; + private QueuedReplace(Category<?> category) { super(category); } @Override public void apply() { - replaceImpl(getCategory(), getPojo()); + replaceImpl(getCategory(), getPojo(), expression); + } + + @Override + public void where(Expression expression) { + this.expression = Objects.requireNonNull(expression); } } @@ -151,7 +159,7 @@ return replace; } - private void replaceImpl(final Category<?> category, final Pojo pojo) { + private void replaceImpl(final Category<?> category, final Pojo pojo, final Expression expression) { executor.execute(new Runnable() { @@ -159,6 +167,7 @@ public void run() { Replace replace = delegate.createReplace(category); replace.setPojo(pojo); + replace.where(expression); replace.apply(); }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java Thu Aug 22 15:05:29 2013 +0200 @@ -37,7 +37,19 @@ package com.redhat.thermostat.storage.core; +import com.redhat.thermostat.storage.query.Expression; + +/** + * Describes which object should get inserted into storage or which + * object should get updated with new values in storage. + * + * If the where expression matches an object in storage, this + * object will get updated. Otherwise a new object gets inserted into + * storage. + * + */ public interface Replace extends Put { + void where(Expression expression); }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/NetworkInterfaceInfoDAOImpl.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/NetworkInterfaceInfoDAOImpl.java Thu Aug 22 15:05:29 2013 +0200 @@ -54,6 +54,8 @@ import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; +import com.redhat.thermostat.storage.query.Expression; +import com.redhat.thermostat.storage.query.ExpressionFactory; public class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO { @@ -99,7 +101,16 @@ @Override public void putNetworkInterfaceInfo(NetworkInterfaceInfo info) { Replace replace = storage.createReplace(networkInfoCategory); + ExpressionFactory factory = new ExpressionFactory(); + String agentId = info.getAgentId(); + if (agentId == null) { + agentId = storage.getAgentId(); + } + Expression left = factory.equalTo(Key.AGENT_ID, agentId); + Expression right = factory.equalTo(NetworkInterfaceInfoDAO.ifaceKey, info.getInterfaceName()); + Expression expression = factory.and(left, right); replace.setPojo(info); + replace.where(expression); replace.apply(); }
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/QueuedStorageTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/QueuedStorageTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -69,6 +69,8 @@ import org.junit.Test; import com.redhat.thermostat.storage.model.Pojo; +import com.redhat.thermostat.storage.query.Expression; +import com.redhat.thermostat.storage.query.ExpressionFactory; public class QueuedStorageTest { @@ -233,12 +235,14 @@ } @Test - public void testInsert() { + public void testReplace() { Category<?> category = mock(Category.class); Pojo pojo = mock(Pojo.class); - Put put = queuedStorage.createReplace(category); + Replace put = queuedStorage.createReplace(category); put.setPojo(pojo); + Expression expression = new ExpressionFactory().equalTo(Key.AGENT_ID, "foo"); + put.where(expression); put.apply(); Runnable r = executor.getTask(); @@ -249,6 +253,7 @@ r.run(); verify(delegateStorage).createReplace(category); verify(delegateReplace).setPojo(pojo); + verify(delegateReplace).where(expression); verify(delegateReplace).apply(); verifyNoMoreInteractions(delegateStorage);
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/NetworkInterfaceInfoDAOTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/NetworkInterfaceInfoDAOTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.storage.internal.dao; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -61,6 +62,8 @@ import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; +import com.redhat.thermostat.storage.query.Expression; +import com.redhat.thermostat.storage.query.ExpressionFactory; public class NetworkInterfaceInfoDAOTest { @@ -132,19 +135,46 @@ @Test public void testPutNetworkInterfaceInfo() { + String agentId = "fooAgent"; + doTestPutNetworkInerfaceInfo(false, agentId); + } + + @Test + public void testPutNetworkInterfaceInfoWithoutAgentIdInInfo() { + String agentId = "fooStorageAgentId"; + doTestPutNetworkInerfaceInfo(true, agentId); + } + + private void doTestPutNetworkInerfaceInfo(boolean agentIdFromStorage, String agentId) { Storage storage = mock(Storage.class); Replace replace = mock(Replace.class); when(storage.createReplace(any(Category.class))).thenReturn(replace); + if (agentIdFromStorage) { + when(storage.getAgentId()).thenReturn(agentId); + } NetworkInterfaceInfo info = new NetworkInterfaceInfo(INTERFACE_NAME); info.setIp4Addr(IPV4_ADDR); info.setIp6Addr(IPV6_ADDR); + if (!agentIdFromStorage) { + info.setAgentId(agentId); + } else { + // case where agentId gets replaced by the DAO + // with the one set for storage. + assertNull(info.getAgentId()); + } + ExpressionFactory factory = new ExpressionFactory(); + Expression left = factory.equalTo(Key.AGENT_ID, agentId); + Expression right = factory.equalTo(NetworkInterfaceInfoDAO.ifaceKey, INTERFACE_NAME); + Expression expected = factory.and(left, right); NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage); dao.putNetworkInterfaceInfo(info); verify(storage).createReplace(NetworkInterfaceInfoDAO.networkInfoCategory); verify(replace).setPojo(info); + verify(replace).where(expected); verify(replace).apply(); } + }
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java Thu Aug 22 15:05:29 2013 +0200 @@ -37,10 +37,10 @@ package com.redhat.thermostat.storage.mongodb.internal; import java.io.InputStream; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -114,14 +114,28 @@ } private class MongoReplace extends BasePut implements Replace { + + private DBObject query; + private final MongoExpressionParser parser; private MongoReplace(Category<?> category) { super(category); + this.parser = new MongoExpressionParser(); } @Override public void apply() { - replaceImpl(getCategory(), getPojo()); + if (query == null) { + String msg = "where expression must be set. " + + "Please call where() before apply()."; + throw new IllegalStateException(msg); + } + replaceImpl(getCategory(), getPojo(), query); + } + + @Override + public void where(Expression expression) { + this.query = parser.parse(Objects.requireNonNull(expression)); } } @@ -231,18 +245,9 @@ coll.insert(toInsert); } - private void replaceImpl(final Category<?> cat, final Pojo pojo) { + private void replaceImpl(final Category<?> cat, final Pojo pojo, final DBObject query) { DBCollection coll = getCachedCollection(cat); DBObject toInsert = preparePut(pojo); - - DBObject query = new BasicDBObject(); - Collection<Key<?>> keys = cat.getKeys(); - for (Key<?> key : keys) { - if (key.isPartialCategoryKey()) { - String name = key.getName(); - query.put(name, toInsert.get(name)); - } - } coll.update(query, toInsert, true, false); }
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -69,6 +69,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; @@ -452,7 +453,7 @@ } @Test - public void verifyInsertReplaceCallsUpdate() { + public void verifyReplace() { TestClass pojo = new TestClass(); pojo.setAgentId("123"); pojo.setKey1("test1"); @@ -463,6 +464,11 @@ MongoStorage storage = makeStorage(); Replace replace = storage.createReplace(testCategory); + ExpressionFactory factory = new ExpressionFactory(); + Expression first = factory.equalTo(key1, "test1"); + Expression second = factory.equalTo(key2, "test2"); + Expression and = factory.and(first, second); + replace.where(and); replace.setPojo(pojo); replace.apply(); @@ -471,9 +477,16 @@ verify(testCollection).update(queryCaptor.capture(), valueCaptor.capture(), eq(true), eq(false)); DBObject query = queryCaptor.getValue(); - assertEquals(2, query.keySet().size()); - assertEquals("test1", query.get("key1")); - assertEquals("test2", query.get("key2")); + assertEquals("expected explicit and query", 1, query.keySet().size()); + Object andObj = query.get("$and"); + assertNotNull(andObj); + assertTrue(andObj instanceof BasicDBList); + BasicDBList list = (BasicDBList)andObj; + assertEquals("expected two operands", 2, list.size()); + DBObject firstCond = (DBObject)list.get(0); + DBObject secondCond = (DBObject)list.get(1); + assertEquals("test1", firstCond.get("key1")); + assertEquals("test2", secondCond.get("key2")); DBObject value = valueCaptor.getValue(); assertEquals(6, value.keySet().size());
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Sun Aug 25 18:32:31 2013 -0600 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Thu Aug 22 15:05:29 2013 +0200 @@ -55,6 +55,8 @@ import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.VmRef; import com.redhat.thermostat.storage.model.Pojo; +import com.redhat.thermostat.storage.query.Expression; +import com.redhat.thermostat.storage.query.ExpressionFactory; import com.redhat.thermostat.thread.dao.ThreadDao; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; import com.redhat.thermostat.thread.model.ThreadInfoData; @@ -137,7 +139,16 @@ @Override public void saveCapabilities(VMThreadCapabilities caps) { Replace replace = storage.createReplace(THREAD_CAPABILITIES); + ExpressionFactory factory = new ExpressionFactory(); + String agentId = caps.getAgentId(); + if (agentId == null) { + agentId = storage.getAgentId(); + } + Expression agentKey = factory.equalTo(Key.AGENT_ID, agentId); + Expression vmKey = factory.equalTo(Key.VM_ID, caps.getVmId()); + Expression and = factory.and(agentKey, vmKey); replace.setPojo(caps); + replace.where(and); replace.apply(); }
--- a/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -40,6 +40,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -55,6 +56,7 @@ import com.redhat.thermostat.storage.core.Cursor; import com.redhat.thermostat.storage.core.DescriptorParsingException; import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.Key; import com.redhat.thermostat.storage.core.PreparedStatement; import com.redhat.thermostat.storage.core.Replace; import com.redhat.thermostat.storage.core.StatementDescriptor; @@ -62,6 +64,8 @@ import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.VmRef; import com.redhat.thermostat.storage.model.Pojo; +import com.redhat.thermostat.storage.query.Expression; +import com.redhat.thermostat.storage.query.ExpressionFactory; import com.redhat.thermostat.thread.dao.ThreadDao; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; import com.redhat.thermostat.thread.model.VMThreadCapabilities; @@ -173,22 +177,64 @@ assertEquals(null, caps); } + /* + * Tests saving of VMCapabilities when agentId has been explicitly set + * in thread capabilities model class. + */ @Test public void testSaveVMCapabilities() { + String agentId = "fooAgent"; + doTestSaveVMCaps(false, agentId); + } + + /* + * Tests saving of VMCapabilities when agentId has NOT been explicitly set + * in thread capabilities model class. AgentId should get filled in from + * storage. + */ + @Test + public void testSaveVMCapabilitiesWithNoAgentIdExplicitlySet() { + String agentId = "fooStorageAgent"; + doTestSaveVMCaps(true, agentId); + } + + private void doTestSaveVMCaps(boolean agentIdFromStorage, String agentId) { Storage storage = mock(Storage.class); Replace replace = mock(Replace.class); when(storage.createReplace(any(Category.class))).thenReturn(replace); - - VMThreadCapabilities caps = mock(VMThreadCapabilities.class); - when(caps.supportContentionMonitor()).thenReturn(true); - when(caps.supportCPUTime()).thenReturn(true); - when(caps.supportThreadAllocatedMemory()).thenReturn(true); - when(caps.getVmId()).thenReturn("VM42"); + if (agentIdFromStorage) { + when(storage.getAgentId()).thenReturn(agentId); + } + + String vmId = "VM42"; + VMThreadCapabilities caps = new VMThreadCapabilities(); + String[] capsFeatures = new String[] { + ThreadDao.CONTENTION_MONITOR, + ThreadDao.CPU_TIME, + ThreadDao.THREAD_ALLOCATED_MEMORY, + }; + caps.setSupportedFeaturesList(capsFeatures); + assertTrue(caps.supportContentionMonitor()); + assertTrue(caps.supportCPUTime()); + assertTrue(caps.supportThreadAllocatedMemory()); + caps.setVmId(vmId); + if (!agentIdFromStorage) { + caps.setAgentId(agentId); + } else { + // case where we want to have agentId null on caps itself. + assertNull(caps.getAgentId()); + } ThreadDaoImpl dao = new ThreadDaoImpl(storage); dao.saveCapabilities(caps); - + + ExpressionFactory factory = new ExpressionFactory(); + Expression agentExpr = factory.equalTo(Key.AGENT_ID, agentId); + Expression vmExpr = factory.equalTo(Key.VM_ID, vmId); + Expression expected = factory.and(agentExpr, vmExpr); + verify(storage).createReplace(ThreadDao.THREAD_CAPABILITIES); verify(replace).setPojo(caps); + verify(replace).where(expected); verify(replace).apply(); }
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java Sun Aug 25 18:32:31 2013 -0600 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java Thu Aug 22 15:05:29 2013 +0200 @@ -91,7 +91,6 @@ import com.redhat.thermostat.storage.config.StartupConfiguration; import com.redhat.thermostat.storage.core.Add; import com.redhat.thermostat.storage.core.AuthToken; -import com.redhat.thermostat.storage.core.BasePut; import com.redhat.thermostat.storage.core.Category; import com.redhat.thermostat.storage.core.Connection; import com.redhat.thermostat.storage.core.Cursor; @@ -116,13 +115,14 @@ import com.redhat.thermostat.web.common.OperatorSerializer; import com.redhat.thermostat.web.common.PreparedParameterSerializer; import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebAdd; import com.redhat.thermostat.web.common.WebPreparedStatement; import com.redhat.thermostat.web.common.WebPreparedStatementResponse; import com.redhat.thermostat.web.common.WebPreparedStatementSerializer; import com.redhat.thermostat.web.common.WebQueryResponse; import com.redhat.thermostat.web.common.WebQueryResponseSerializer; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebReplace; import com.redhat.thermostat.web.common.WebUpdate; public class WebStorage implements Storage, SecureStorage { @@ -299,30 +299,28 @@ } - private class WebAdd extends BasePut implements Add { + private class WebAddImpl extends WebAdd { - private WebAdd(Category<?> category) { - super(category); + private WebAddImpl(int categoryId) { + super(categoryId); } @Override public void apply() { - int categoryId = getCategoryId(getCategory()); - addImpl(new WebInsert(categoryId), getPojo()); + addImpl(this); } } - private class WebReplace extends BasePut implements Replace { - - private WebReplace(Category<?> category) { - super(category); + private class WebReplaceImpl extends WebReplace { + + private WebReplaceImpl(int categoryId) { + super(categoryId); } @Override public void apply() { - int categoryId = getCategoryId(getCategory()); - replaceImpl(new WebInsert(categoryId), getPojo()); + replaceImpl(this); } } @@ -638,34 +636,38 @@ @Override public Add createAdd(Category<?> into) { - WebAdd add = new WebAdd(into); + int categoryId = getCategoryId(into); + WebAdd add = new WebAddImpl(categoryId); return add; } @Override public Replace createReplace(Category<?> into) { - WebReplace replace = new WebReplace(into); + int categoryId = getCategoryId(into); + WebReplace replace = new WebReplaceImpl(categoryId); return replace; } - private void addImpl(WebInsert insert, final Pojo pojo) throws StorageException { - List<NameValuePair> formParams = getPutFormParams(insert, pojo); + private void addImpl(final WebAdd add) throws StorageException { + Pojo pojo = add.getPojo(); + maybeAddAgentId(pojo); + NameValuePair pojoParam = new BasicNameValuePair("pojo", + gson.toJson(pojo)); + NameValuePair addParam = new BasicNameValuePair("add", + gson.toJson(add)); + List<NameValuePair> formParams = Arrays.asList(addParam, pojoParam); post(endpoint + "/add-pojo", formParams).close(); } - private List<NameValuePair> getPutFormParams(WebInsert insert, Pojo pojo) { + private void replaceImpl(final WebReplace replace) throws StorageException { + Pojo pojo = replace.getPojo(); maybeAddAgentId(pojo); - NameValuePair insertParam = new BasicNameValuePair("insert", - gson.toJson(insert)); + NameValuePair replaceParam = new BasicNameValuePair("replace", + gson.toJson(replace)); NameValuePair pojoParam = new BasicNameValuePair("pojo", gson.toJson(pojo)); - List<NameValuePair> formparams = Arrays.asList(insertParam, pojoParam); - return formparams; - } - - private void replaceImpl(WebInsert insert, final Pojo pojo) throws StorageException { - List<NameValuePair> formparams = getPutFormParams(insert, pojo); - post(endpoint + "/replace-pojo", formparams).close(); + List<NameValuePair> formParams = Arrays.asList(replaceParam, pojoParam); + post(endpoint + "/replace-pojo", formParams).close(); } private void maybeAddAgentId(final Pojo pojo) throws AssertionError {
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -90,6 +90,7 @@ import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.redhat.thermostat.storage.config.StartupConfiguration; +import com.redhat.thermostat.storage.core.Add; import com.redhat.thermostat.storage.core.AuthToken; import com.redhat.thermostat.storage.core.Categories; import com.redhat.thermostat.storage.core.Category; @@ -117,13 +118,14 @@ import com.redhat.thermostat.web.common.OperatorSerializer; import com.redhat.thermostat.web.common.PreparedParameterSerializer; import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebAdd; import com.redhat.thermostat.web.common.WebPreparedStatement; import com.redhat.thermostat.web.common.WebPreparedStatementResponse; import com.redhat.thermostat.web.common.WebPreparedStatementSerializer; import com.redhat.thermostat.web.common.WebQueryResponse; import com.redhat.thermostat.web.common.WebQueryResponseSerializer; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebReplace; import com.redhat.thermostat.web.common.WebUpdate; public class WebStorageTest { @@ -389,6 +391,43 @@ // Pass. } } + + @Test + public void testAdd() throws IOException, JsonSyntaxException, ClassNotFoundException { + + TestObj obj = new TestObj(); + obj.setProperty1("fluff"); + + // We need an agentId, so that we can check automatic insert of agentId. + UUID agentId = new UUID(1, 2); + storage.setAgentId(agentId); + + Add add = storage.createAdd(category); + add.setPojo(obj); + + prepareServer(); + add.apply(); + + 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("add", parts[0]); + WebAdd add2 = gson.fromJson(parts[1], WebAdd.class); + assertEquals(42, add2.getCategoryId()); + + parts = params[1].split("="); + assertEquals(2, parts.length); + assertEquals("pojo", parts[0]); + Object resultObj = gson.fromJson(parts[1], TestObj.class); + + // Set agentId on expected object, because we expect WebStorage to insert it for us. + obj.setAgentId(agentId.toString()); + assertEquals(obj, resultObj); + } @Test public void testReplace() throws IOException, JsonSyntaxException, ClassNotFoundException { @@ -401,20 +440,26 @@ storage.setAgentId(agentId); Replace replace = storage.createReplace(category); + Expression expr = new ExpressionFactory().equalTo(key1, "fluff"); replace.setPojo(obj); + replace.where(expr); prepareServer(); replace.apply(); - Gson gson = new Gson(); + Gson gson = new GsonBuilder() + .registerTypeHierarchyAdapter(Expression.class, + new ExpressionSerializer()) + .registerTypeHierarchyAdapter(Operator.class, + new OperatorSerializer()).create(); 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("insert", parts[0]); - WebInsert insert = gson.fromJson(parts[1], WebInsert.class); + assertEquals("replace", parts[0]); + WebReplace insert = gson.fromJson(parts[1], WebReplace.class); assertEquals(42, insert.getCategoryId()); parts = params[1].split("=");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/WebAdd.java Thu Aug 22 15:05:29 2013 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 2013 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 com.redhat.thermostat.storage.core.Add; +import com.redhat.thermostat.storage.model.Pojo; + + +public class WebAdd implements Add { + + private int categoryId; + private transient Pojo pojo; + + public WebAdd() { + } + + public WebAdd(int categoryId) { + this.categoryId = categoryId; + } + + public int getCategoryId() { + return categoryId; + } + + public void setCategoryId(int categoryId) { + this.categoryId = categoryId; + } + + + @Override + public void setPojo(Pojo pojo) { + this.pojo = pojo; + } + + public Pojo getPojo() { + return pojo; + } + + @Override + public void apply() { + // Should never be called directly, but overridden by + // the actual implementation. Here only so that it can be used + // for serialization. + throw new IllegalStateException(); + } +} +
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/WebInsert.java Sun Aug 25 18:32:31 2013 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright 2012, 2013 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; - - -public class WebInsert { - - private int categoryId; - - public WebInsert() { - } - - public WebInsert(int categoryId) { - this.categoryId = categoryId; - } - - public int getCategoryId() { - return categoryId; - } - - public void setCategoryId(int categoryId) { - this.categoryId = categoryId; - } - -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/WebReplace.java Thu Aug 22 15:05:29 2013 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright 2012, 2013 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 com.redhat.thermostat.storage.core.Replace; +import com.redhat.thermostat.storage.model.Pojo; +import com.redhat.thermostat.storage.query.Expression; + +public class WebReplace implements Replace { + + private int categoryId; + private transient Pojo pojo; + private Expression whereExpression; + + public WebReplace() { + // nothing + } + + public WebReplace(int categoryId) { + this.categoryId = categoryId; + } + + @Override + public void setPojo(Pojo pojo) { + this.pojo = pojo; + } + + @Override + public void apply() { + // Should never be called directly, but overridden by + // the actual implementation. Here only so that it can be used + // for serialization. + throw new IllegalStateException(); + } + + @Override + public void where(Expression expression) { + this.whereExpression = expression; + } + + public int getCategoryId() { + return categoryId; + } + + public void setCategoryId(int categoryId) { + this.categoryId = categoryId; + } + + public Pojo getPojo() { + return pojo; + } + + public Expression getWhereExpression() { + return whereExpression; + } + +}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java Sun Aug 25 18:32:31 2013 -0600 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java Thu Aug 22 15:05:29 2013 +0200 @@ -106,13 +106,14 @@ import com.redhat.thermostat.web.common.PreparedParameterSerializer; import com.redhat.thermostat.web.common.StorageWrapper; import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebAdd; import com.redhat.thermostat.web.common.WebPreparedStatement; import com.redhat.thermostat.web.common.WebPreparedStatementResponse; import com.redhat.thermostat.web.common.WebPreparedStatementSerializer; import com.redhat.thermostat.web.common.WebQueryResponse; import com.redhat.thermostat.web.common.WebQueryResponseSerializer; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebReplace; import com.redhat.thermostat.web.common.WebUpdate; import com.redhat.thermostat.web.server.auth.FilterResult; import com.redhat.thermostat.web.server.auth.Roles; @@ -526,9 +527,9 @@ if (! isAuthorized(req, resp, Roles.APPEND)) { return; } - String insertParam = req.getParameter("insert"); - WebInsert insert = gson.fromJson(insertParam, WebInsert.class); - int categoryId = insert.getCategoryId(); + String addParam = req.getParameter("add"); + WebAdd add = gson.fromJson(addParam, WebAdd.class); + int categoryId = add.getCategoryId(); Category<?> category = getCategoryFromId(categoryId); Add targetAdd = storage.createAdd(category); Class<? extends Pojo> pojoCls = category.getDataClass(); @@ -544,15 +545,17 @@ if (! isAuthorized(req, resp, Roles.REPLACE)) { return; } - String insertParam = req.getParameter("insert"); - WebInsert insert = gson.fromJson(insertParam, WebInsert.class); - int categoryId = insert.getCategoryId(); + String replaceParam = req.getParameter("replace"); + WebReplace replace = gson.fromJson(replaceParam, WebReplace.class); + int categoryId = replace.getCategoryId(); Category<?> category = getCategoryFromId(categoryId); Replace targetReplace = storage.createReplace(category); Class<? extends Pojo> pojoCls = category.getDataClass(); String pojoParam = req.getParameter("pojo"); Pojo pojo = gson.fromJson(pojoParam, pojoCls); targetReplace.setPojo(pojo); + Expression expr = replace.getWhereExpression(); + targetReplace.where(expr); targetReplace.apply(); resp.setStatus(HttpServletResponse.SC_OK); }
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java Sun Aug 25 18:32:31 2013 -0600 +++ b/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java Thu Aug 22 15:05:29 2013 +0200 @@ -113,8 +113,8 @@ import com.redhat.thermostat.storage.core.Replace; import com.redhat.thermostat.storage.core.StatementDescriptor; import com.redhat.thermostat.storage.core.Update; +import com.redhat.thermostat.storage.core.auth.CategoryRegistration; import com.redhat.thermostat.storage.core.auth.DescriptorMetadata; -import com.redhat.thermostat.storage.core.auth.CategoryRegistration; import com.redhat.thermostat.storage.core.auth.StatementDescriptorRegistration; import com.redhat.thermostat.storage.dao.HostInfoDAO; import com.redhat.thermostat.storage.model.AggregateCount; @@ -132,13 +132,14 @@ import com.redhat.thermostat.web.common.PreparedParameterSerializer; import com.redhat.thermostat.web.common.StorageWrapper; import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebAdd; import com.redhat.thermostat.web.common.WebPreparedStatement; import com.redhat.thermostat.web.common.WebPreparedStatementResponse; import com.redhat.thermostat.web.common.WebPreparedStatementSerializer; import com.redhat.thermostat.web.common.WebQueryResponse; import com.redhat.thermostat.web.common.WebQueryResponseSerializer; import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebReplace; import com.redhat.thermostat.web.common.WebUpdate; import com.redhat.thermostat.web.server.auth.BasicRole; import com.redhat.thermostat.web.server.auth.RolePrincipal; @@ -900,6 +901,7 @@ TestClass expected1 = new TestClass(); expected1.setKey1("fluff1"); expected1.setKey2(42); + Expression expectedExpression = new ExpressionFactory().equalTo(key1, "fluff1"); String endpoint = getEndpoint(); @@ -910,11 +912,16 @@ conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - WebInsert insert = new WebInsert(categoryId); - Gson gson = new Gson(); + WebReplace webReplace = new WebReplace(categoryId); + webReplace.where(expectedExpression); + Gson gson = new GsonBuilder() + .registerTypeHierarchyAdapter(Expression.class, + new ExpressionSerializer()) + .registerTypeHierarchyAdapter(Operator.class, + new OperatorSerializer()).create(); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("insert="); - gson.toJson(insert, out); + out.write("replace="); + gson.toJson(webReplace, out); out.flush(); out.write("&pojo="); gson.toJson(expected1, out); @@ -923,6 +930,7 @@ assertEquals(200, conn.getResponseCode()); verify(mockStorage).createReplace(category); verify(replace).setPojo(expected1); + verify(replace).where(eq(expectedExpression)); verify(replace).apply(); } @@ -955,12 +963,15 @@ conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - // replace - WebInsert insert = new WebInsert(categoryId); - Gson gson = new Gson(); + WebReplace webReplace = new WebReplace(categoryId); + Gson gson = new GsonBuilder() + .registerTypeHierarchyAdapter(Expression.class, + new ExpressionSerializer()) + .registerTypeHierarchyAdapter(Operator.class, + new OperatorSerializer()).create(); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("insert="); - gson.toJson(insert, out); + out.write("replace="); + gson.toJson(webReplace, out); out.flush(); out.write("&pojo="); TestClass expected1 = new TestClass(); @@ -1009,10 +1020,10 @@ conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - WebInsert ins = new WebInsert(categoryId); + WebAdd ins = new WebAdd(categoryId); Gson gson = new Gson(); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("insert="); + out.write("add="); gson.toJson(ins, out); out.flush(); out.write("&pojo="); @@ -1054,11 +1065,10 @@ conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - // replace - WebInsert insert = new WebInsert(categoryId); + WebAdd insert = new WebAdd(categoryId); Gson gson = new Gson(); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("insert="); + out.write("add="); gson.toJson(insert, out); out.flush(); out.write("&pojo=");