/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hmsonline.storm.cassandra.bolt; import static com.hmsonline.storm.cassandra.bolt.AstyanaxUtil.createColumnFamily; import static com.hmsonline.storm.cassandra.bolt.AstyanaxUtil.newClusterContext; import static com.hmsonline.storm.cassandra.bolt.AstyanaxUtil.newContext; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.thrift.transport.TTransportException; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.astyanax.AstyanaxContext; import com.netflix.astyanax.Cluster; import com.netflix.astyanax.Keyspace; import com.netflix.astyanax.MutationBatch; import com.netflix.astyanax.model.AbstractComposite.ComponentEquality; import com.netflix.astyanax.model.Column; import com.netflix.astyanax.model.ColumnFamily; import com.netflix.astyanax.model.ColumnList; import com.netflix.astyanax.model.Composite; import com.netflix.astyanax.query.ColumnFamilyQuery; import com.netflix.astyanax.serializers.CompositeSerializer; import com.netflix.astyanax.serializers.StringSerializer; public class AstyanaxComposites { private static final Logger LOG = LoggerFactory.getLogger(AstyanaxComposites.class); private static String KEYSPACE = AstyanaxComposites.class.getSimpleName(); @BeforeClass public static void setupCassandra() throws TTransportException, IOException, InterruptedException, ConfigurationException, Exception { SingletonEmbeddedCassandra.getInstance(); try { AstyanaxContext<Cluster> clusterContext = newClusterContext("localhost:9160"); createColumnFamily(clusterContext, KEYSPACE, "composite", "CompositeType(UTF8Type, UTF8Type)", "UTF8Type", "UTF8Type"); createColumnFamily(clusterContext, KEYSPACE, "composite2", "CompositeType(UTF8Type, UTF8Type, UTF8Type)", "UTF8Type", "UTF8Type"); } catch (Exception e) { LOG.warn("Couldn't setup cassandra.", e); throw e; } } // @Test @SuppressWarnings("unchecked") public void simpleReadWriteCompositeTest() { boolean fail = false; try { AstyanaxContext<Keyspace> context = newContext("localhost:9160", KEYSPACE); Keyspace ks = context.getEntity(); ColumnFamily<String, Composite> cf = new ColumnFamily<String, Composite>("composite", StringSerializer.get(), CompositeSerializer.get()); MutationBatch mutation = ks.prepareMutationBatch(); mutation.withRow(cf, "mykey").putColumn(makeStringComposite("foo", "bar"), "Hello Composite Column Range Query"); mutation.withRow(cf, "mykey").putColumn(makeStringComposite("foo", "baz"), "My dog has fleas"); mutation.withRow(cf, "mykey").putColumn(makeStringComposite("fzz", "baz"), "It is snowing"); mutation.execute(); // simple column fetch ColumnFamilyQuery<String, Composite> query = ks.prepareQuery(cf); Column<Composite> result = query.getKey("mykey").getColumn(makeStringComposite("foo", "bar")).execute() .getResult(); LOG.debug(result.getStringValue()); // build up a composite range query Composite start = makeStringEqualityComposite(new String[] { "foo" }, new ComponentEquality[] { ComponentEquality.EQUAL }); // Composite end = new Composite(); // end.addComponent("fyy", StringSerializer.get(), // ComponentEquality.GREATER_THAN_EQUAL); Composite end = makeStringEqualityComposite(new String[] { "fyy" }, new ComponentEquality[] { ComponentEquality.GREATER_THAN_EQUAL }); ColumnList<Composite> results = query.getKey("mykey") .withColumnRange(start.serialize(), end.serialize(), false, 100).execute().getResult(); LOG.debug("Query matched {} results.", results.size()); for (Composite columnKey : results.getColumnNames()) { LOG.debug("Component(0): {}", columnKey.getComponent(0).getValue(StringSerializer.get())); LOG.debug("Component(1): {}", columnKey.getComponent(1).getValue(StringSerializer.get())); LOG.debug("Value: {}", results.getValue(columnKey, StringSerializer.get(), "")); if (results.getValue(columnKey, StringSerializer.get(), "").equals("It is snowing")) { fail = true; } } } catch (Exception e) { e.printStackTrace(); fail(); } assertFalse("unexpected result", fail); } @Test public void twoDimensionalCompositeRangeTest() { boolean fail = false; try { final String rowkey = "mykey2"; AstyanaxContext<Keyspace> context = newContext("localhost:9160", KEYSPACE); Keyspace ks = context.getEntity(); ColumnFamily<String, Composite> cf = new ColumnFamily<String, Composite>("composite2", StringSerializer.get(), CompositeSerializer.get()); MutationBatch mutation = ks.prepareMutationBatch(); List<String> combinations = combinationsWithRepitition("abcdef", 3); for(String str : combinations){ LOG.debug("Will insert '{}'", str); mutation.withRow(cf, rowkey).putColumn(makeStringComposite(str.substring(0,1), str.substring(1,2), str.substring(2,3)), str); } mutation.execute(); // build up a composite range query Composite start = makeStringEqualityComposite(new String[] { "a", "a", "a"}, new ComponentEquality[] { ComponentEquality.EQUAL,ComponentEquality.EQUAL, ComponentEquality.EQUAL }); Composite end = makeStringEqualityComposite(new String[] { "a", "a", "b"}, new ComponentEquality[] { ComponentEquality.EQUAL,ComponentEquality.EQUAL, ComponentEquality.EQUAL }); ColumnFamilyQuery<String, Composite> query = ks.prepareQuery(cf); ColumnList<Composite> results = query.getKey(rowkey) .withColumnRange(start.serialize(), end.serialize(), false, 100).execute().getResult(); LOG.debug("Query matched {} results.", results.size()); for (Composite columnKey : results.getColumnNames()) { // LOG.debug("Component(0): {}", columnKey.getComponent(0).getValue(StringSerializer.get())); // LOG.debug("Component(1): {}", columnKey.getComponent(1).getValue(StringSerializer.get())); // LOG.debug("Component(2): {}", columnKey.getComponent(2).getValue(StringSerializer.get())); LOG.debug("Value: {}", results.getValue(columnKey, StringSerializer.get(), "")); } } catch (Exception e) { e.printStackTrace(); fail(); } assertFalse("unexpected result", fail); } public static Composite makeStringComposite(String... values) { Composite comp = new Composite(); for (String value : values) { comp.addComponent(value, StringSerializer.get()); } return comp; } public static Composite makeStringEqualityComposite(String[] values, ComponentEquality[] equalities) { if (values.length != equalities.length) { throw new IllegalArgumentException("Number of values and equalities must match."); } Composite comp = new Composite(); for (int i = 0; i < values.length; i++) { comp.addComponent(values[i], StringSerializer.get(), equalities[i]); } return comp; } public static void main(String[] args) throws Exception { List<String> perms = permutaions("aaa"); System.out.println("Found " + perms.size() + " permutatons."); for(String perm : perms){ System.out.println(perm); } } public static List<String> combinationsWithRepitition(String input){ return combinationsWithRepitition(input, input.length()); } public static List<String> combinationsWithRepitition(String input, int depth){ return combinationWithRepitition(new ArrayList<String>(), input, depth, new StringBuffer()); } static List<String> combinationWithRepitition(List<String> result, String input, int depth, StringBuffer output) { if (depth == 0) { result.add(output.toString()); } else { for (int i = 0; i < input.length(); i++) { output.append(input.charAt(i)); combinationWithRepitition(result, input, depth - 1, output); output.deleteCharAt(output.length() - 1); } } return result; } public static List<String> permutaions(String input) { return permutaions("", input, new ArrayList<String>()); } public static List<String> permutaions(String prefix, String input, List<String> result) { int n = input.length(); if (n == 0) { result.add(prefix); } else { for (int i = 0; i < n; i++){ permutaions(prefix + input.charAt(i), input.substring(0, i) + input.substring(i + 1, n), result); } } return result; } }