Mercurial > hg > release > thermostat-0.15
changeset 1270:11bb959f9814
Refactor Add/Replace/Update to use a generic set(String, Object).
Reviewed-by: vanaltj
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-October/008360.html
PR1569
line wrap: on
line diff
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java Fri Oct 04 14:23:39 2013 +0200 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java Mon Sep 30 17:12:26 2013 +0200 @@ -162,7 +162,9 @@ for (int i = 0; i < numberOfItems; i++) { CpuStat pojo = new CpuStat("test-agent-id", i, new double[] {i, i*2}); Add<CpuStat> add = storage.createAdd(CpuStatDAO.cpuStatCategory); - add.setPojo(pojo); + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); + add.set(CpuStatDAO.cpuLoadKey.getName(), pojo.getPerProcessorUsage()); + add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp()); add.apply(); } @@ -212,8 +214,7 @@ pojo.setLoadedClasses(12345); pojo.setTimeStamp(42); pojo.setVmId(VM_ID1); - add.setPojo(pojo); - add.apply(); + addVmClassStat(add, pojo); // Add another couple of entries add = mongoStorage.createAdd(VmClassStatDAO.vmClassStatsCategory); @@ -222,8 +223,7 @@ pojo.setLoadedClasses(67890); pojo.setTimeStamp(42); pojo.setVmId(VM_ID2); - add.setPojo(pojo); - add.apply(); + addVmClassStat(add, pojo); add = mongoStorage.createAdd(VmClassStatDAO.vmClassStatsCategory); pojo = new VmClassStat(); @@ -231,12 +231,19 @@ pojo.setLoadedClasses(34567); pojo.setTimeStamp(42); pojo.setVmId(VM_ID3); - add.setPojo(pojo); - add.apply(); + addVmClassStat(add, pojo); mongoStorage.getConnection().disconnect(); } + private void addVmClassStat(Add<VmClassStat> add, VmClassStat pojo) { + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); + add.set(Key.VM_ID.getName(), pojo.getVmId()); + add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp()); + add.set(VmClassStatDAO.loadedClassesKey.getName(), pojo.getLoadedClasses()); + add.apply(); + } + @Test public void canQueryNoWhere() throws Exception { CountDownLatch latch = new CountDownLatch(1); @@ -514,7 +521,10 @@ double cpuLoad = 0.15; VmCpuStat pojo = new VmCpuStat(uuid.toString(), timeStamp, VM_ID1, cpuLoad); Add<VmCpuStat> add = mongoStorage.createAdd(VmCpuStatDAO.vmCpuStatCategory); - add.setPojo(pojo); + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); + add.set(Key.VM_ID.getName(), pojo.getVmId()); + add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp()); + add.set(VmCpuStatDAO.vmCpuLoadKey.getName(), pojo.getCpuLoad()); add.apply(); Query<VmCpuStat> query = mongoStorage.createQuery(VmCpuStatDAO.vmCpuStatCategory);
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java Fri Oct 04 14:23:39 2013 +0200 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java Mon Sep 30 17:12:26 2013 +0200 @@ -407,7 +407,9 @@ for (int i = 0; i < numberOfItems; i++) { CpuStat pojo = new CpuStat("test-agent-id", i, new double[] {i, i*2}); Add<CpuStat> add = storage.createAdd(CpuStatDAO.cpuStatCategory); - add.setPojo(pojo); + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); + add.set(CpuStatDAO.cpuLoadKey.getName(), pojo.getPerProcessorUsage()); + add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp()); add.apply(); } @@ -421,7 +423,13 @@ for (int i = 0; i < numberOfItems; i++) { HostInfo hostInfo = new HostInfo("test-host-agent-id", "foo " + i, "linux " + i, "kernel", "t8", i, i * 1000); Add<HostInfo> add = storage.createAdd(HostInfoDAO.hostInfoCategory); - add.setPojo(hostInfo); + add.set(Key.AGENT_ID.getName(), hostInfo.getAgentId()); + add.set(HostInfoDAO.hostNameKey.getName(), hostInfo.getHostname()); + add.set(HostInfoDAO.cpuCountKey.getName(), hostInfo.getCpuCount()); + add.set(HostInfoDAO.cpuModelKey.getName(), hostInfo.getCpuModel()); + add.set(HostInfoDAO.hostMemoryTotalKey.getName(), hostInfo.getTotalMemory()); + add.set(HostInfoDAO.osKernelKey.getName(), hostInfo.getOsKernel()); + add.set(HostInfoDAO.osNameKey.getName(), hostInfo.getOsName()); add.apply(); } @@ -434,7 +442,11 @@ for (AgentInformation info: items) { Add<AgentInformation> add = storage.createAdd(AgentInfoDAO.CATEGORY); - add.setPojo(info); + add.set(Key.AGENT_ID.getName(), info.getAgentId()); + add.set(AgentInfoDAO.ALIVE_KEY.getName(), info.isAlive()); + add.set(AgentInfoDAO.CONFIG_LISTEN_ADDRESS.getName(), info.getConfigListenAddress()); + add.set(AgentInfoDAO.START_TIME_KEY.getName(), info.getStartTime()); + add.set(AgentInfoDAO.STOP_TIME_KEY.getName(), info.getStopTime()); add.apply(); } @@ -1070,7 +1082,10 @@ BackingStorage storage = getAndConnectBackingStorage(); storage.registerCategory(VmCpuStatDAO.vmCpuStatCategory); Add<VmCpuStat> add = storage.createAdd(VmCpuStatDAO.vmCpuStatCategory); - add.setPojo(pojo); + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); + add.set(Key.VM_ID.getName(), pojo.getVmId()); + add.set(Key.TIMESTAMP.getName(), pojo.getTimeStamp()); + add.set(VmCpuStatDAO.vmCpuLoadKey.getName(), pojo.getCpuLoad()); add.apply(); storage.getConnection().disconnect(); }
--- a/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Fri Oct 04 14:23:39 2013 +0200 +++ b/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Mon Sep 30 17:12:26 2013 +0200 @@ -1,14 +1,5 @@ -# FIXME: Remove commons-beanutils, commons-codec, commons-logging, -# commons-collections from bootstrap list once storage-core -# does no longer depend on beanutils. It has been made -# dependent on this because it was required as an interim -# measure to switch over to prepared writes. bundles=thermostat-shared-config-${project.version}.jar, \ thermostat-keyring-${project.version}.jar, \ - commons-codec-${commons-codec.version}.jar, \ - commons-logging-${commons-logging.version}.jar, \ - commons-collections-${commons-collections.version}.jar, \ - commons-beanutils-${commons-beanutils.version}.jar, \ thermostat-storage-core-${project.version}.jar, \ thermostat-common-core-${project.version}.jar, \ thermostat-plugin-validator-${project.version}.jar, \
--- a/storage/core/pom.xml Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/pom.xml Mon Sep 30 17:12:26 2013 +0200 @@ -106,18 +106,6 @@ <artifactId>org.apache.felix.framework</artifactId> </dependency> <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - </dependency> - <dependency> - <groupId>commons-collections</groupId> - <artifactId>commons-collections</artifactId> - </dependency> - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </dependency> - <dependency> <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-annotations</artifactId> <version>${project.version}</version>
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Add.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Add.java Mon Sep 30 17:12:26 2013 +0200 @@ -50,11 +50,16 @@ public interface Add<T extends Pojo> extends DataModifyingStatement<T> { /** - * Sets the POJO that is to be added into storage. - * - * @param pojo the pojo to be added into storage + * Sets a field to the specified value. If the same key is + * set more than once, the latest value overrides the former value for that + * key. + * + * @param key + * the name of the field to update. + * @param value + * the value with which to update the field. */ - void setPojo(Pojo pojo); + void set(String key, Object value); /** * Applies this {@code Add} operation to storage.
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/AddReplaceHelper.java Fri Oct 04 14:23:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +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.storage.core; - -import java.util.Objects; - -import com.redhat.thermostat.storage.model.Pojo; - -/** Helps in implementing {@link Add} and {@link Replace} classes */ -public abstract class AddReplaceHelper { - - private final Category<?> category; - private Pojo pojo; - - public AddReplaceHelper(Category<?> category) { - this.category = Objects.requireNonNull(category); - } - - public final Category<?> getCategory() { - return category; - } - - public final void setPojo(Pojo pojo) { - this.pojo = pojo; - } - - public final Pojo getPojo() { - return pojo; - } - -} -
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedBackingStorage.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedBackingStorage.java Mon Sep 30 17:12:26 2013 +0200 @@ -72,8 +72,8 @@ } @Override - public void setPojo(Pojo pojo) { - delegateReplace.setPojo(pojo); + public void set(String key, Object value) { + delegateReplace.set(key, value); } } @@ -100,8 +100,8 @@ } @Override - public void setPojo(Pojo pojo) { - delegateAdd.setPojo(pojo); + public void set(String key, Object value) { + delegateAdd.set(key, value); } } @@ -121,7 +121,7 @@ } @Override - public <S> void set(Key<S> key, S value) { + public void set(String key, Object value) { delegateUpdate.set(key, value); }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Replace.java Mon Sep 30 17:12:26 2013 +0200 @@ -59,12 +59,16 @@ public interface Replace<T extends Pojo> extends DataModifyingStatement<T> { /** - * Sets the POJO that will be used to replace the value in storage. - * - * @param pojo the pojo which describes the updated values or the new - * record to be added to storage. + * Sets a field in a found record to the specified value. If the same key is + * set more than once, the latest value overrides the former value for that + * key. + * + * @param key + * the name of the field to update. + * @param value + * the value with which to update the field. */ - void setPojo(Pojo pojo); + void set(String key, Object value); /** * Specifies what criteria to use to find the record to replace
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Update.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Update.java Mon Sep 30 17:12:26 2013 +0200 @@ -61,14 +61,15 @@ /** * Sets a field in a found record to the specified value. If the same key is - * set more than once, the latest values overrides the former values. + * set more than once, the latest value overrides the former value for that + * key. * * @param key - * the key of the field + * the name of the field to update. * @param value - * the value to set + * the value with which to update the field. */ - <S> void set(Key<S> key, S value); + void set(String key, Object value); /** * Applies this update operation.
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImpl.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImpl.java Mon Sep 30 17:12:26 2013 +0200 @@ -38,7 +38,6 @@ import com.redhat.thermostat.storage.core.Add; import com.redhat.thermostat.storage.core.IllegalPatchException; -import com.redhat.thermostat.storage.core.Key; import com.redhat.thermostat.storage.core.ParsedStatement; import com.redhat.thermostat.storage.core.PreparedParameter; import com.redhat.thermostat.storage.core.Query; @@ -46,7 +45,6 @@ import com.redhat.thermostat.storage.core.Replace; import com.redhat.thermostat.storage.core.Statement; import com.redhat.thermostat.storage.core.Update; -import com.redhat.thermostat.storage.internal.statement.PatchedSetListPojoConverter.IllegalPojoException; import com.redhat.thermostat.storage.model.Pojo; import com.redhat.thermostat.storage.query.Expression; @@ -60,14 +58,12 @@ class ParsedStatementImpl<T extends Pojo> implements ParsedStatement<T> { private final Statement<T> statement; - private final Class<T> dataClass; private int numParams; private SuffixExpression suffixExpn; private SetList setList; - ParsedStatementImpl(Statement<T> statement, Class<T> dataClass) { + ParsedStatementImpl(Statement<T> statement) { this.statement = statement; - this.dataClass = dataClass; } @Override @@ -105,35 +101,24 @@ PatchedSetList patchedSetList = setList.patch(params); // set the values if (statement instanceof Add) { - T pojo = convertToPojo(patchedSetList); Add<T> add = (Add<T>)statement; - add.setPojo(pojo); + for (PatchedSetListMember member: patchedSetList.getSetListMembers()) { + add.set(member.getKey().getName(), member.getValue()); + } } if (statement instanceof Replace) { - T pojo = convertToPojo(patchedSetList); Replace<T> replace = (Replace<T>)statement; - replace.setPojo(pojo); + for (PatchedSetListMember member: patchedSetList.getSetListMembers()) { + replace.set(member.getKey().getName(), member.getValue()); + } } if (statement instanceof Update) { Update<T> update = (Update<T>)statement; - for (PatchedSetListMember mem: patchedSetList.getSetListMembers()) { - @SuppressWarnings("unchecked") - Key<Object> key = (Key<Object>)mem.getKey(); - update.set(key, mem.getValue()); + for (PatchedSetListMember member: patchedSetList.getSetListMembers()) { + update.set(member.getKey().getName(), member.getValue()); } } } - - private T convertToPojo(PatchedSetList setList) throws IllegalPatchException { - PatchedSetListPojoConverter<T> converter = new PatchedSetListPojoConverter<>(setList, dataClass); - T pojo = null; - try { - pojo = converter.convertToPojo(); - } catch (IllegalPojoException e) { - throw new IllegalPatchException(e); - } - return pojo; - } private void patchLimit(PreparedParameter[] params) throws IllegalPatchException { LimitExpression expn = suffixExpn.getLimitExpn();
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverter.java Fri Oct 04 14:23:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +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.storage.internal.statement; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.apache.commons.beanutils.PropertyUtils; - -import com.redhat.thermostat.storage.model.Pojo; - -class PatchedSetListPojoConverter<T extends Pojo> { - - private final PatchedSetList setList; - private final Class<T> dataClass; - - PatchedSetListPojoConverter(PatchedSetList setList, Class<T> dataClass) { - this.setList = setList; - this.dataClass = dataClass; - } - - T convertToPojo() throws IllegalPojoException { - T instance = null; - try { - instance = dataClass.newInstance(); - PatchedSetListMember[] members = setList.getSetListMembers(); - for (PatchedSetListMember mem: members) { - String propName = mem.getKey().getName(); - PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(instance, propName); - if (desc == null) { - throw new IllegalPojoException("Property " + propName + " not found in Pojo: " + dataClass); - } - setValueForProperty(instance, desc, mem); - } - } catch (NoSuchMethodException | InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException e) { - throw new IllegalPojoException(e); - } - return instance; - } - - private void setValueForProperty(T instance, PropertyDescriptor desc, - PatchedSetListMember mem) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method writeMethod = desc.getWriteMethod(); - Object value = mem.getValue(); - writeMethod.invoke(instance, value); - } - - @SuppressWarnings("serial") - static class IllegalPojoException extends Exception { - - IllegalPojoException(Throwable cause) { - super(cause); - } - - private IllegalPojoException(String msg) { - super(msg); - } - } -}
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/StatementDescriptorParser.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/StatementDescriptorParser.java Mon Sep 30 17:12:26 2013 +0200 @@ -806,31 +806,30 @@ // matchStatementType and matchCategory advanced currTokenIndex, // lets use idx of 0 here. final String statementType = tokens[0]; - Class<T> dataClass = desc.getCategory().getDataClass(); if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_QUERY])) { // regular query case Query<T> query = storage.createQuery(desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(query, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(query); } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_QUERY_COUNT])) { // create aggregate count query Query<T> query = storage.createAggregateQuery(AggregateFunction.COUNT, desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(query, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(query); } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_ADD])) { // create add Add<T> add = storage.createAdd(desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(add, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(add); } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_REPLACE])) { // create replace Replace<T> replace = storage.createReplace(desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(replace, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(replace); } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_UPDATE])) { // create replace Update<T> update = storage.createUpdate(desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(update, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(update); } else if (statementType.equals(KNOWN_STATEMENT_TYPES[IDX_REMOVE])) { // create remove Remove<T> remove = storage.createRemove(desc.getCategory()); - this.parsedStatement = new ParsedStatementImpl<>(remove, dataClass); + this.parsedStatement = new ParsedStatementImpl<>(remove); } else { throw new IllegalStateException("Don't know how to create statement type '" + statementType + "'"); }
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/AddReplaceHelperTest.java Fri Oct 04 14:23:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +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.storage.core; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; - -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.storage.model.Pojo; - -public class AddReplaceHelperTest { - - private Category<?> category; - - @Before - public void setup() { - category = mock(Category.class); - } - - @Test - public void testCategory() { - TestBasePut insert = new TestBasePut(category); - - assertNotNull(insert.getCategory()); - assertSame(category, insert.getCategory()); - - try { - insert = new TestBasePut(null); - fail(); - } catch (NullPointerException ex) { - // Ok. - } - } - - @Test - public void testPojo() { - Pojo pojo = mock(Pojo.class); - - TestBasePut insert = new TestBasePut(category); - assertNull(insert.getPojo()); - insert.setPojo(pojo); - assertSame(pojo, insert.getPojo()); - } - - private static class TestBasePut extends AddReplaceHelper { - - public TestBasePut(Category<?> category) { - super(category); - } - - } -} -
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java Mon Sep 30 17:12:26 2013 +0200 @@ -42,7 +42,9 @@ import static org.junit.Assert.fail; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.After; import org.junit.Before; @@ -85,7 +87,7 @@ @Test public void canPatchWhereAndExpr() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); SuffixExpression suffixExpn = new SuffixExpression(); suffixExpn.setLimitExpn(null); suffixExpn.setSortExpn(null); @@ -159,7 +161,7 @@ @Test public void canPatchBasicWhereEquals() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); SuffixExpression suffixExpn = new SuffixExpression(); suffixExpn.setLimitExpn(null); suffixExpn.setSortExpn(null); @@ -223,7 +225,7 @@ @Test public void canPatchBasicWhereEqualsLHSKeyAndRHSValue() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); SuffixExpression suffixExpn = new SuffixExpression(); suffixExpn.setLimitExpn(null); suffixExpn.setSortExpn(null); @@ -293,7 +295,7 @@ @Test public void canPatchBasicLimit() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); parsedStmt.setSetList(new SetList()); SuffixExpression suffixExpn = new SuffixExpression(); LimitExpression limitExpnToPatch = new LimitExpression(); @@ -354,7 +356,7 @@ public void canPatchBasicSetListAdd() throws IllegalPatchException { // create the parsedStatementImpl we are going to use DataModifyingStatement<TestPojo> stmt = new TestAdd<>(); - ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class); + ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); SetList setList = buildSetList(); suffixExpn.setLimitExpn(null); @@ -371,11 +373,10 @@ Add<TestPojo> add = (Add<TestPojo>)parsedStmt.patchStatement(params); assertTrue(add instanceof TestAdd); TestAdd<TestPojo> q = (TestAdd<TestPojo>)add; - Pojo testPojo = q.pojo; - assertTrue(testPojo instanceof TestPojo); - TestPojo tPojo = (TestPojo)testPojo; - assertEquals("foo-writer", tPojo.getWriterId()); - assertEquals(Long.MAX_VALUE, tPojo.getFooTimeStamp()); + Map<String, Object> vals = q.values; + assertEquals(2, vals.keySet().size()); + assertEquals("foo-writer", vals.get("writerId")); + assertEquals(Long.MAX_VALUE, vals.get("fooTimeStamp")); } /* @@ -386,7 +387,7 @@ public void canPatchSetListAddWithPojoList() throws IllegalPatchException { // create the parsedStatementImpl we are going to use DataModifyingStatement<FancyPojo> stmt = new TestAdd<>(); - ParsedStatementImpl<FancyPojo> parsedStmt = new ParsedStatementImpl<>(stmt, FancyPojo.class); + ParsedStatementImpl<FancyPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); SetList setList = new SetList(); parsedStmt.setSetList(setList); @@ -424,14 +425,16 @@ Add<FancyPojo> add = (Add<FancyPojo>)parsedStmt.patchStatement(params); assertTrue(add instanceof TestAdd); TestAdd<FancyPojo> q = (TestAdd<FancyPojo>)add; - Pojo testPojo = q.pojo; - assertTrue(testPojo instanceof FancyPojo); - FancyPojo tPojo = (FancyPojo)testPojo; - assertEquals(null, tPojo.getWriterId()); - assertNotNull(tPojo.getSomeList()); - assertEquals(2, tPojo.getSomeList().length); - TestPojo first = tPojo.getSomeList()[0]; - TestPojo second = tPojo.getSomeList()[1]; + Map<String, Object> vals = q.values; + assertEquals(1, vals.keySet().size()); + assertEquals(null, vals.get("writerId")); + assertNotNull(vals.get("someList")); + Object someList = vals.get("someList"); + assertTrue(someList instanceof TestPojo[]); + TestPojo[] tPojo = (TestPojo[])someList; + assertEquals(2, tPojo.length); + TestPojo first = tPojo[0]; + TestPojo second = tPojo[1]; assertEquals(elem1, first); assertEquals(elem2, second); assertEquals("elem1", first.getWriterId()); @@ -447,7 +450,7 @@ @Test public void canPatchBasicSetListReplace() throws IllegalPatchException { DataModifyingStatement<TestPojo> stmt = new TestReplace(); - ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class); + ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); // Build this set list, which corresponds to the TestPojo below @@ -509,11 +512,10 @@ Replace<TestPojo> replace = (Replace<TestPojo>)parsedStmt.patchStatement(params); assertTrue(replace instanceof TestReplace); TestReplace q = (TestReplace)replace; - Pojo testPojo = q.pojo; - assertTrue(testPojo instanceof TestPojo); - TestPojo tPojo = (TestPojo)testPojo; - assertEquals("foo-bar", tPojo.getWriterId()); - assertEquals(Long.MAX_VALUE, tPojo.getFooTimeStamp()); + Map<String, Object> vals = q.values; + assertEquals(2, vals.keySet().size()); + assertEquals("foo-bar", vals.get("writerId")); + assertEquals(Long.MAX_VALUE, vals.get("fooTimeStamp")); ExpressionFactory factory = new ExpressionFactory(); Expression expectedExpression = factory.equalTo(new Key<>("foo"), -400); @@ -527,7 +529,7 @@ @Test public void canPatchBasicSetListUpdate() throws IllegalPatchException { DataModifyingStatement<TestPojo> stmt = new TestUpdate(); - ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class); + ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); // Build this set list, which corresponds to the TestPojo below @@ -579,7 +581,7 @@ List<Pair<Object, Object>> updates = q.updates; assertEquals(1, updates.size()); Pair<Object, Object> update = updates.get(0); - assertEquals(new Key<>("writerId"), update.getFirst()); + assertEquals("writerId", update.getFirst()); assertEquals("foobar-writer-id", update.getSecond()); ExpressionFactory factory = new ExpressionFactory(); @@ -590,7 +592,7 @@ @Test public void canPatchBasicSort() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); parsedStmt.setSetList(new SetList()); SuffixExpression suffixExpn = new SuffixExpression(); // SORT ? ASC, b DSC @@ -635,7 +637,7 @@ public void failPatchSetListAddWrongType() throws IllegalPatchException { // create the parsedStatementImpl we are going to use DataModifyingStatement<TestPojo> stmt = new TestAdd<>(); - ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class); + ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); SetList setList = buildSetList(); suffixExpn.setLimitExpn(null); @@ -663,7 +665,7 @@ public void failPatchSetListAddInsufficientParams() throws IllegalPatchException { // create the parsedStatementImpl we are going to use DataModifyingStatement<TestPojo> stmt = new TestAdd<>(); - ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt, TestPojo.class); + ParsedStatementImpl<TestPojo> parsedStmt = new ParsedStatementImpl<>(stmt); SuffixExpression suffixExpn = new SuffixExpression(); SetList setList = buildSetList(); suffixExpn.setLimitExpn(null); @@ -687,7 +689,7 @@ @Test public void failPatchWithWrongType() throws IllegalPatchException { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); parsedStmt.setSetList(new SetList()); SuffixExpression suffixExpn = new SuffixExpression(); suffixExpn.setLimitExpn(null); @@ -745,7 +747,7 @@ @Test public void failPatchBasicEqualsIfIndexOutofBounds() { // create the parsedStatementImpl we are going to use - ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement, null); + ParsedStatementImpl<Pojo> parsedStmt = new ParsedStatementImpl<>(statement); SuffixExpression suffixExpn = new SuffixExpression(); suffixExpn.setLimitExpn(null); suffixExpn.setSortExpn(null); @@ -821,11 +823,11 @@ private static class TestAdd<T extends Pojo> implements Add<T> { - private Pojo pojo; + private Map<String, Object> values = new HashMap<>(); @Override - public void setPojo(Pojo pojo) { - this.pojo = pojo; + public void set(String key, Object value) { + values.put(key, value); } @Override @@ -839,11 +841,11 @@ private static class TestReplace implements Replace<TestPojo> { private Expression where; - private Pojo pojo; + private Map<String, Object> values = new HashMap<>(); @Override - public void setPojo(Pojo pojo) { - this.pojo = pojo; + public void set(String key, Object value) { + values.put(key, value); } @Override @@ -871,7 +873,7 @@ @SuppressWarnings({ "rawtypes", "unchecked" }) @Override - public <S> void set(Key<S> key, S value) { + public void set(String key, Object value) { Pair update = new Pair<>(key, value); updates.add(update); }
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PatchedSetListPojoConverterTest.java Fri Oct 04 14:23:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +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.storage.internal.statement; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Test; - -import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.internal.statement.PatchedSetListPojoConverter.IllegalPojoException; -import com.redhat.thermostat.storage.model.Pojo; - -public class PatchedSetListPojoConverterTest { - - @Test - public void testBasicConversion() throws IllegalPojoException { - PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("foo"), "foo-val"); - PatchedSetListMember mem2 = new PatchedSetListMember(new Key<>("barKey"), Long.MAX_VALUE); - PatchedSetListMember[] members = new PatchedSetListMember[] { - mem1, - mem2 - }; - PatchedSetList setList = mock(PatchedSetList.class); - when(setList.getSetListMembers()).thenReturn(members); - PatchedSetListPojoConverter<TestMe> converter = new PatchedSetListPojoConverter<>(setList, TestMe.class); - TestMe instance = converter.convertToPojo(); - assertEquals("foo-val", instance.getFoo()); - assertEquals(Long.MAX_VALUE, instance.getBarKey()); - } - - @Test - public void testConversionWithLists() throws IllegalPojoException { - PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("foo"), "foo-val"); - PatchedSetListMember mem2 = new PatchedSetListMember(new Key<>("barKey"), Long.MAX_VALUE); - double[] list = new double[] {Math.PI, 3.3}; - PatchedSetListMember mem3 = new PatchedSetListMember(new Key<>("doubleList"), list); - PatchedSetListMember[] members = new PatchedSetListMember[] { - mem1, - mem2, - mem3 - }; - PatchedSetList setList = mock(PatchedSetList.class); - when(setList.getSetListMembers()).thenReturn(members); - PatchedSetListPojoConverter<ListPojo> converter = new PatchedSetListPojoConverter<>(setList, ListPojo.class); - ListPojo instance = converter.convertToPojo(); - assertEquals("foo-val", instance.getFoo()); - assertEquals(Long.MAX_VALUE, instance.getBarKey()); - double[] values = instance.getDoubleList(); - assertEquals(2, values.length); - double delta = 0.002; - assertEquals(Math.PI, values[0], delta); - assertEquals(3.3, values[1], delta); - } - - @Test - public void testConversionFailBasic() { - PatchedSetListMember mem1 = new PatchedSetListMember(new Key<>("wrong-Prop"), "foo-val"); - PatchedSetListMember[] members = new PatchedSetListMember[] { - mem1 - }; - PatchedSetList setList = mock(PatchedSetList.class); - when(setList.getSetListMembers()).thenReturn(members); - PatchedSetListPojoConverter<TestMe> converter = new PatchedSetListPojoConverter<>(setList, TestMe.class); - try { - converter.convertToPojo(); - fail("Should not convert, property not present in Pojo"); - } catch (IllegalPojoException e) { - // pass - assertTrue(e.getMessage().contains("Property wrong-Prop not found in Pojo:")); - } - } - - public static class TestMe implements Pojo { - - private String foo; - private long barKey; - - public String getFoo() { - return foo; - } - public void setFoo(String foo) { - this.foo = foo; - } - public long getBarKey() { - return barKey; - } - public void setBarKey(long barKey) { - this.barKey = barKey; - } - } - - public static class ListPojo extends TestMe { - - private double[] doubleList; - - public double[] getDoubleList() { - return doubleList; - } - public void setDoubleList(double[] doubleList) { - this.doubleList = doubleList; - } - - } -}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PreparedStatementImplTest.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/PreparedStatementImplTest.java Mon Sep 30 17:12:26 2013 +0200 @@ -44,7 +44,9 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.Test; @@ -147,11 +149,10 @@ } catch (StatementExecutionException e) { fail(e.getMessage()); } - assertTrue(add.pojo != null); - assertTrue(add.pojo instanceof FooPojo); + assertFalse(add.values.isEmpty()); assertTrue(add.executed); - FooPojo fooPojo = (FooPojo)add.pojo; - assertEquals("foo-val", fooPojo.getFoo()); + assertEquals(1, add.values.keySet().size()); + assertEquals("foo-val", add.values.get("foo")); } @Test @@ -184,13 +185,13 @@ } catch (StatementExecutionException e) { fail(e.getMessage()); } - assertTrue(add.pojo != null); - assertTrue(add.pojo instanceof FancyFoo); + assertFalse(add.values.isEmpty()); + assertEquals(1, add.values.keySet().size()); assertTrue(add.executed); - FancyFoo fooPojo = (FancyFoo)add.pojo; - assertEquals(2, fooPojo.getFancyFoo().length); - FooPojo first = fooPojo.getFancyFoo()[0]; - FooPojo second = fooPojo.getFancyFoo()[1]; + FooPojo[] fancyFoo = (FooPojo[])add.values.get("fancyFoo"); + assertEquals(2, fancyFoo.length); + FooPojo first = fancyFoo[0]; + FooPojo second = fancyFoo[1]; assertEquals("one", first.getFoo()); assertEquals("two", second.getFoo()); } @@ -221,8 +222,8 @@ } assertTrue(update.executed); assertEquals(1, update.updates.size()); - Pair<Key<Object>, Object> item = update.updates.get(0); - assertEquals(new Key<>("foo"), item.getFirst()); + Pair<String, Object> item = update.updates.get(0); + assertEquals("foo", item.getFirst()); assertEquals("foo-val", item.getSecond()); LiteralExpression<Key<String>> o1 = new LiteralExpression<>(new Key<String>("foo")); LiteralExpression<String> o2 = new LiteralExpression<>("nice"); @@ -255,11 +256,9 @@ } catch (StatementExecutionException e) { fail(e.getMessage()); } - assertTrue(replace.pojo != null); - assertTrue(replace.pojo instanceof FooPojo); + assertFalse(replace.values.isEmpty()); assertTrue(replace.executed); - FooPojo fooPojo = (FooPojo)replace.pojo; - assertEquals("foo-val", fooPojo.getFoo()); + assertEquals("foo-val", replace.values.get("foo")); LiteralExpression<Key<String>> o1 = new LiteralExpression<>(new Key<String>("foo")); LiteralExpression<String> o2 = new LiteralExpression<>("bar"); BinaryComparisonExpression<String> binComp = new BinaryComparisonExpression<>( @@ -324,12 +323,12 @@ private static class TestAdd<T extends Pojo> implements Add<T> { - private Pojo pojo; + private Map<String, Object> values = new HashMap<>(); private boolean executed = false; @Override - public void setPojo(Pojo pojo) { - this.pojo = pojo; + public void set(String key, Object value) { + values.put(key, value); } @Override @@ -342,13 +341,13 @@ private static class TestReplace implements Replace<FooPojo> { - private Pojo pojo; + private Map<String, Object> values = new HashMap<>(); private boolean executed = false; private Expression where; @Override - public void setPojo(Pojo pojo) { - this.pojo = pojo; + public void set(String key, Object value) { + values.put(key, value); } @Override @@ -367,7 +366,7 @@ private static class TestUpdate implements Update<FooPojo> { private Expression where; - private List<Pair<Key<Object>, Object>> updates = new ArrayList<>(); + private List<Pair<String, Object>> updates = new ArrayList<>(); private boolean executed = false; @Override @@ -376,9 +375,8 @@ } @Override - public <S> void set(Key<S> key, S value) { - @SuppressWarnings("unchecked") - Pair<Key<Object>, Object> item = new Pair<>((Key<Object>) key, (Object)value); + public void set(String key, Object value) { + Pair<String, Object> item = new Pair<>(key, value); updates.add(item); }
--- a/storage/mongo/pom.xml Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/mongo/pom.xml Mon Sep 30 17:12:26 2013 +0200 @@ -87,6 +87,18 @@ <artifactId>org.apache.felix.framework</artifactId> </dependency> <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> </dependency>
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java Mon Sep 30 17:12:26 2013 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.storage.mongodb.internal; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -58,7 +59,6 @@ import com.redhat.thermostat.storage.core.AggregateQuery; import com.redhat.thermostat.storage.core.AggregateQuery.AggregateFunction; import com.redhat.thermostat.storage.core.BackingStorage; -import com.redhat.thermostat.storage.core.AddReplaceHelper; import com.redhat.thermostat.storage.core.Category; import com.redhat.thermostat.storage.core.Connection; import com.redhat.thermostat.storage.core.Connection.ConnectionListener; @@ -67,7 +67,6 @@ import com.redhat.thermostat.storage.core.DescriptorParsingException; import com.redhat.thermostat.storage.core.Key; import com.redhat.thermostat.storage.core.PreparedStatement; -import com.redhat.thermostat.storage.core.PreparedStatementFactory; import com.redhat.thermostat.storage.core.Query; import com.redhat.thermostat.storage.core.Remove; import com.redhat.thermostat.storage.core.Replace; @@ -99,26 +98,70 @@ return executeGetCount(category, (MongoQuery<T>)this.queryToAggregate); } } + + private static abstract class MongoSetter<T extends Pojo> { + + protected final DBObject values; + protected final Category<T> category; + + private MongoSetter(Category<T> category) { + this.category = category; + this.values = new BasicDBObject(); + } + + private Object convertPojo(Object value) { + // convert pojo values to mongo DB objects if need be + if (value instanceof Pojo) { + Pojo pojo = (Pojo)value; + MongoPojoConverter converter = new MongoPojoConverter(); + value = converter.convertPojoToMongo(pojo); + } else if (value instanceof Pojo[]) { + List<DBObject> pojos = new ArrayList<>(); + MongoPojoConverter converter = new MongoPojoConverter(); + Pojo[] list = (Pojo[])value; + for (Pojo p: list) { + DBObject converted = converter.convertPojoToMongo(p); + pojos.add(converted); + } + value = pojos; + } + return value; + } + + protected void set(String key, Object value) { + // convert Pojo/list of Pojos to DBObject/list of DBObjects + // if need be + value = convertPojo(value); + values.put(key, value); + } + } - private class MongoAdd<T extends Pojo> extends AddReplaceHelper implements Add<T> { - - private MongoAdd(Category<?> category) { + private class MongoAdd<T extends Pojo> extends MongoSetter<T> + implements Add<T> { + + private MongoAdd(Category<T> category) { super(category); } @Override public int apply() { - return addImpl(getCategory(), getPojo()); + return addImpl(category, values); + } + + @Override + public void set(String key, Object value) { + super.set(key, value); } } - private class MongoReplace<T extends Pojo> extends AddReplaceHelper implements Replace<T> { + private class MongoReplace<T extends Pojo> extends MongoSetter<T> + implements Replace<T> { private DBObject query; private final MongoExpressionParser parser; - private MongoReplace(Category<?> category) { + private MongoReplace(Category<T> category) { super(category); this.parser = new MongoExpressionParser(); } @@ -130,28 +173,62 @@ "Please call where() before apply()."; throw new IllegalStateException(msg); } - return replaceImpl(getCategory(), getPojo(), query); + return replaceImpl(category, values, query); } @Override public void where(Expression expression) { this.query = parser.parse(Objects.requireNonNull(expression)); } + + @Override + public void set(String key, Object value) { + super.set(key, value); + } } + private class MongoUpdate<T extends Pojo> extends MongoSetter<T> + implements Update<T> { + + private static final String SET_MODIFIER = "$set"; + + private DBObject query; + private final MongoExpressionParser parser; + + private MongoUpdate(Category<T> category) { + super(category); + this.parser = new MongoExpressionParser(); + } + + @Override + public void where(Expression expr) { + query = parser.parse(expr); + } + + @Override + public void set(String key, Object value) { + super.set(key, value); + } + + @Override + public int apply() { + DBObject setValues = new BasicDBObject(SET_MODIFIER, values); + return updateImpl(category, setValues, query); + } + } + private class MongoRemove<T extends Pojo> implements Remove<T> { - @SuppressWarnings("rawtypes") - private final Category category; + private final Category<T> category; private DBObject query; private final MongoExpressionParser parser; - private MongoRemove(Category<?> category) { + private MongoRemove(Category<T> category) { this(category, new MongoExpressionParser()); } - private MongoRemove(Category<?> category, MongoExpressionParser parser) { + private MongoRemove(Category<T> category, MongoExpressionParser parser) { this.parser = parser; this.category = category; } @@ -229,17 +306,17 @@ return replace; } - private int addImpl(final Category<?> cat, final Pojo pojo) { + private <T extends Pojo> int addImpl(final Category<T> cat, final DBObject values) { DBCollection coll = getCachedCollection(cat); - DBObject toInsert = preparePut(pojo); - WriteResult result = coll.insert(toInsert); + assertContainsWriterID(values); + WriteResult result = coll.insert(values); return numAffectedRecords(result); } - private int replaceImpl(final Category<?> cat, final Pojo pojo, final DBObject query) { + private <T extends Pojo> int replaceImpl(final Category<T> cat, final DBObject values, final DBObject query) { DBCollection coll = getCachedCollection(cat); - DBObject toInsert = preparePut(pojo); - WriteResult result = coll.update(query, toInsert, true, false); + assertContainsWriterID(values); + WriteResult result = coll.update(query, values, true, false); return numAffectedRecords(result); } @@ -249,21 +326,14 @@ return responseCode; } - private DBObject preparePut(final Pojo pojo) { - MongoPojoConverter converter = new MongoPojoConverter(); - DBObject toInsert = converter.convertPojoToMongo(pojo); - if (toInsert.get(Key.AGENT_ID.getName()) == null) { - // FIXME: Remove - throw new AssertionError("agentID must be set"); + private void assertContainsWriterID(final DBObject values) { + if (values.get(Key.AGENT_ID.getName()) == null) { + throw new AssertionError("agentId must be set"); } - return toInsert; } - int updatePojo(MongoUpdate<?> mongoUpdate) { - Category<?> cat = mongoUpdate.getCategory(); - DBCollection coll = getCachedCollection(cat); - DBObject query = mongoUpdate.getQuery(); - DBObject values = mongoUpdate.getValues(); + private <T extends Pojo> int updateImpl(Category<T> category, DBObject values, DBObject query) { + DBCollection coll = getCachedCollection(category); WriteResult result = coll.update(query, values); return numAffectedRecords(result); } @@ -339,7 +409,7 @@ @Override public <T extends Pojo> Update<T> createUpdate(Category<T> category) { - return new MongoUpdate<>(this, category); + return new MongoUpdate<>(category); } @Override
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoUpdate.java Fri Oct 04 14:23:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +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.storage.mongodb.internal; - -import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; -import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.core.Update; -import com.redhat.thermostat.storage.model.Pojo; -import com.redhat.thermostat.storage.query.Expression; - -class MongoUpdate<T extends Pojo> implements Update<T> { - - private static final String SET_MODIFIER = "$set"; - - private MongoStorage storage; - private DBObject query; - private DBObject values; - private Category<?> category; - private MongoExpressionParser parser; - - public MongoUpdate(MongoStorage storage, Category<?> category) { - this(storage, category, new MongoExpressionParser()); - } - - MongoUpdate(MongoStorage storage, Category<?> category, MongoExpressionParser parser) { - this.storage = storage; - this.category = category; - this.parser = parser; - } - - Category<?> getCategory() { - return category; - } - - @Override - public void where(Expression expr) { - query = parser.parse(expr); - } - - DBObject getQuery() { - return query; - } - - @Override - public <S> void set(Key<S> key, S value) { - if (values == null) { - values = new BasicDBObject(); - } - values.put(key.getName(), value); - } - - DBObject getValues() { - return new BasicDBObject(SET_MODIFIER, values); - } - - @Override - public int apply() { - return storage.updatePojo(this); - } -} -
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java Fri Oct 04 14:23:39 2013 +0200 +++ b/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java Mon Sep 30 17:12:26 2013 +0200 @@ -56,6 +56,7 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -168,7 +169,7 @@ private static final Key<String> key4 = new Key<>("key4"); private static final Key<String> key5 = new Key<>("key5"); private static final Category<TestClass> testCategory = new Category<>("MongoStorageTest", TestClass.class, key1, key2, key3, key4, key5); - private static final Category<TestClass> emptyTestCategory = new Category("MongoEmptyCategory", TestClass.class); + private static final Category<TestClass> emptyTestCategory = new Category<>("MongoEmptyCategory", TestClass.class); private StartupConfiguration conf; private Mongo m; @@ -264,7 +265,7 @@ @Test public void verifyFindAllReturnsCursor() throws Exception { MongoStorage storage = makeStorage(); - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); Cursor<TestClass> cursor = query.execute(); assertNotNull(cursor); } @@ -272,7 +273,7 @@ @Test public void verifyFindAllCallsDBCollectionFind() throws Exception { MongoStorage storage = makeStorage(); - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); ExpressionFactory factory = new ExpressionFactory(); Expression expr = factory.equalTo(key1, "fluff"); query.where(expr); @@ -284,7 +285,8 @@ public void verifyFindAllCallsDBCollectionFindWithCorrectQuery() throws Exception { MongoStorage storage = makeStorage(); - MongoQuery query = mock(MongoQuery.class); + @SuppressWarnings("unchecked") + MongoQuery<TestClass> query = mock(MongoQuery.class); when(query.hasClauses()).thenReturn(true); DBObject generatedQuery = mock(DBObject.class); when(query.getGeneratedQuery()).thenReturn(generatedQuery); @@ -300,7 +302,7 @@ MongoStorage storage = makeStorage(); // TODO find a way to test this that isn't just testing MongoCursor // Because we mock the DBCollection, the contents of this query don't actually determine the result. - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); Cursor<TestClass> cursor = query.execute(); verifyDefaultCursor(cursor); @@ -311,7 +313,7 @@ MongoStorage storage = makeStorage(); // TODO find a way to test this that isn't just testing MongoCursor // Because we mock the DBCollection, the contents of this query don't actually determine the result. - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); query.sort(key1, Query.SortDirection.ASCENDING); query.limit(3); @@ -328,7 +330,7 @@ @Test public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception { MongoStorage storage = makeStorage(); - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); query.execute(); verify(testCollection).find(); } @@ -336,7 +338,7 @@ @Test public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception { MongoStorage storage = makeStorage(); - Query query = storage.createQuery(testCategory); + Query<TestClass> query = storage.createQuery(testCategory); Cursor<TestClass> cursor = query.execute(); verifyDefaultCursor(cursor); @@ -377,31 +379,76 @@ MongoStorage storage = makeStorage(); TestClass pojo = new TestClass(); pojo.setAgentId("123"); - Add add = storage.createAdd(testCategory); - add.setPojo(pojo); + Add<TestClass> add = storage.createAdd(testCategory); + add.set(Key.AGENT_ID.getName(), pojo.getAgentId()); add.apply(); ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class); verify(testCollection).insert(dbobj.capture()); DBObject val = dbobj.getValue(); assertEquals("123", val.get("agentId")); } + + /* + * This test verifies if pojo types get converted correctly. This + * add isn't really using the correct type parameter. It should be using + * a pojo which has itself Pojo properties defined. For the sake of this + * test this "hack" should be sufficient. + */ + @Test + public void verifyPojoTypeGetsConverted() throws Exception { + MongoStorage storage = makeStorage(); + TestClass pojo = new TestClass(); + pojo.setKey1("val1"); + pojo.setKey3("val3"); + Add<?> add = storage.createAdd(testCategory); + add.set("agentId", "ignored"); + add.set("foo-pojo-key", pojo); + add.apply(); + ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class); + verify(testCollection).insert(dbobj.capture()); + DBObject val = dbobj.getValue(); + assertTrue(val.get("foo-pojo-key") instanceof DBObject); + DBObject pojoVal = (DBObject)val.get("foo-pojo-key"); + assertEquals("val1", pojoVal.get("key1")); + assertEquals("val3", pojoVal.get("key3")); + } + + @Test + public void verifyPojoListGetsConverted() throws Exception { + MongoStorage storage = makeStorage(); + TestClass pojo = new TestClass(); + pojo.setKey1("val1"); + pojo.setKey3("val3"); + TestClass[] list = new TestClass[] { pojo }; + Add<?> add = storage.createAdd(testCategory); + add.set("agentId", "ignored"); + add.set("foo-pojo-key", list); + add.apply(); + ArgumentCaptor<DBObject> dbobj = ArgumentCaptor.forClass(DBObject.class); + verify(testCollection).insert(dbobj.capture()); + DBObject val = dbobj.getValue(); + assertTrue(val.get("foo-pojo-key") instanceof List); + @SuppressWarnings("unchecked") + List<DBObject> result = (List<DBObject>)val.get("foo-pojo-key"); + assertEquals(1, result.size()); + DBObject pojoVal = result.get(0); + assertEquals("val1", pojoVal.get("key1")); + assertEquals("val3", pojoVal.get("key3")); + } @Test public void verifyPutChunkDoesNotUseGlobalAgent() throws Exception { MongoStorage storage = makeStorage(); - TestClass pojo = new TestClass(); - Add add = storage.createAdd(testCategory); - add.setPojo(pojo); + Add<TestClass> add = storage.createAdd(testCategory); try { add.apply(); fail("We do not allow null agentId"); } catch (AssertionError e) { // pass } - Replace replace = storage.createReplace(testCategory); + Replace<TestClass> replace = storage.createReplace(testCategory); ExpressionFactory factory = new ExpressionFactory(); Expression whereExp = factory.equalTo(Key.AGENT_ID, "foobar"); - replace.setPojo(pojo); replace.where(whereExp); try { replace.apply(); @@ -431,10 +478,10 @@ @Test public void verifySimpleUpdate() { MongoStorage storage = makeStorage(); - Update update = storage.createUpdate(testCategory); + Update<TestClass> update = storage.createUpdate(testCategory); Expression expr = factory.equalTo(Key.AGENT_ID, "test1"); update.where(expr); - update.set(key2, "test2"); + update.set(key2.getName(), "test2"); update.apply(); ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class); @@ -457,11 +504,11 @@ @Test public void verifyMultiFieldUpdate() { MongoStorage storage = makeStorage(); - Update update = storage.createUpdate(testCategory); + Update<TestClass> update = storage.createUpdate(testCategory); Expression expr = factory.equalTo(Key.AGENT_ID, "test1"); update.where(expr); - update.set(key2, "test2"); - update.set(key3, "test3"); + update.set(key2.getName(), "test2"); + update.set(key3.getName(), "test3"); update.apply(); ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class); @@ -492,13 +539,18 @@ pojo.setKey5("test5"); MongoStorage storage = makeStorage(); - Replace replace = storage.createReplace(testCategory); + Replace<TestClass> 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.set("key1", pojo.getKey1()); + replace.set("key2", pojo.getKey2()); + replace.set("key3", pojo.getKey3()); + replace.set("key4", pojo.getKey4()); + replace.set("key5", pojo.getKey5()); + replace.set(Key.AGENT_ID.getName(), pojo.getAgentId()); replace.apply(); ArgumentCaptor<DBObject> queryCaptor = ArgumentCaptor.forClass(DBObject.class);