From 883073e8eab9e0d258dcdc525eac68aa288cbc27 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 25 Mar 2011 12:22:56 +0000 Subject: [PATCH 001/764] Incorporate Coda Hale's suggestions into a new API --- .gitignore | 4 + pom.xml | 37 +++++ .../java/com/basho/riak/client/Bucket.java | 57 +++++++ src/main/java/com/basho/riak/client/CAP.java | 23 +++ .../com/basho/riak/client/ClobberMutator.java | 32 ++++ .../basho/riak/client/ConflictResolver.java | 26 ++++ .../basho/riak/client/DeleteOperation.java | 44 ++++++ .../basho/riak/client/DoNothingResolver.java | 28 ++++ .../basho/riak/client/DummyRiakObject.java | 96 ++++++++++++ .../com/basho/riak/client/FetchBucket.java | 45 ++++++ .../com/basho/riak/client/FetchOperation.java | 44 ++++++ .../java/com/basho/riak/client/Mutation.java | 24 +++ .../riak/client/NamedErlangFunction.java | 53 +++++++ .../com/basho/riak/client/NamedFunction.java | 24 +++ .../com/basho/riak/client/RiakClient.java | 32 ++++ .../com/basho/riak/client/RiakException.java | 27 ++++ .../com/basho/riak/client/RiakFactory.java | 38 +++++ .../java/com/basho/riak/client/RiakLink.java | 22 +++ .../com/basho/riak/client/RiakObject.java | 44 ++++++ .../com/basho/riak/client/RiakOperation.java | 24 +++ .../riak/client/RiakRetryFailedException.java | 22 +++ .../com/basho/riak/client/StoreOperation.java | 79 ++++++++++ .../com/basho/riak/client/TakeTheFirst.java | 35 +++++ .../client/UnresolvedConflictException.java | 51 +++++++ .../java/com/basho/riak/client/VClock.java | 22 +++ .../com/basho/riak/client/WriteBucket.java | 140 ++++++++++++++++++ .../basho/riak/client/BasicOperations.java | 93 ++++++++++++ .../megacorp/kv/exceptions/BailException.java | 28 ++++ .../MyCheckedBusinessException.java | 30 ++++ 29 files changed, 1224 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/basho/riak/client/Bucket.java create mode 100644 src/main/java/com/basho/riak/client/CAP.java create mode 100644 src/main/java/com/basho/riak/client/ClobberMutator.java create mode 100644 src/main/java/com/basho/riak/client/ConflictResolver.java create mode 100644 src/main/java/com/basho/riak/client/DeleteOperation.java create mode 100644 src/main/java/com/basho/riak/client/DoNothingResolver.java create mode 100644 src/main/java/com/basho/riak/client/DummyRiakObject.java create mode 100644 src/main/java/com/basho/riak/client/FetchBucket.java create mode 100644 src/main/java/com/basho/riak/client/FetchOperation.java create mode 100644 src/main/java/com/basho/riak/client/Mutation.java create mode 100644 src/main/java/com/basho/riak/client/NamedErlangFunction.java create mode 100644 src/main/java/com/basho/riak/client/NamedFunction.java create mode 100644 src/main/java/com/basho/riak/client/RiakClient.java create mode 100644 src/main/java/com/basho/riak/client/RiakException.java create mode 100644 src/main/java/com/basho/riak/client/RiakFactory.java create mode 100644 src/main/java/com/basho/riak/client/RiakLink.java create mode 100644 src/main/java/com/basho/riak/client/RiakObject.java create mode 100644 src/main/java/com/basho/riak/client/RiakOperation.java create mode 100644 src/main/java/com/basho/riak/client/RiakRetryFailedException.java create mode 100644 src/main/java/com/basho/riak/client/StoreOperation.java create mode 100644 src/main/java/com/basho/riak/client/TakeTheFirst.java create mode 100644 src/main/java/com/basho/riak/client/UnresolvedConflictException.java create mode 100644 src/main/java/com/basho/riak/client/VClock.java create mode 100644 src/main/java/com/basho/riak/client/WriteBucket.java create mode 100644 src/test/java/com/basho/riak/client/BasicOperations.java create mode 100644 src/test/java/com/megacorp/kv/exceptions/BailException.java create mode 100644 src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..ecfc415e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.classpath +.settings/ +.project +target/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..2ec443afc --- /dev/null +++ b/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + com.basho.riak + riak-api + 0.1-SNAPSHOT + jar + + api + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + 4.4 + test + + + + + + + maven-compiler-plugin + + 1.5 + 1.5 + + + + + diff --git a/src/main/java/com/basho/riak/client/Bucket.java b/src/main/java/com/basho/riak/client/Bucket.java new file mode 100644 index 000000000..8af374475 --- /dev/null +++ b/src/main/java/com/basho/riak/client/Bucket.java @@ -0,0 +1,57 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; +import java.util.Iterator; + +/** + * @author russell + * + */ +public interface Bucket { + + StoreOperation store(String key, String value); + + StoreOperation store(RiakObject o); + + FetchOperation fetch(String key); + + FetchOperation fetch(RiakObject o); + + DeleteOperation delete(RiakObject o); + + + String getName(); + boolean isAllowSiblings(); + boolean isLastWriteWins(); + int getNVal(); + String getBackend(); + int getSmallVClock(); + int getBigVClock(); + long getYoungVClock(); + long getOldVClock(); + Collection getPrecommitHooks(); + Collection getPostCommitHooks(); + NamedErlangFunction getChashKeyFunction(); + NamedErlangFunction getLinkWalkFunction(); + int getR(); + int getW(); + int getDW(); + int getRW(); + + // iterate the keys + Iterator iterator(); + +} diff --git a/src/main/java/com/basho/riak/client/CAP.java b/src/main/java/com/basho/riak/client/CAP.java new file mode 100644 index 000000000..5fa4fef1f --- /dev/null +++ b/src/main/java/com/basho/riak/client/CAP.java @@ -0,0 +1,23 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public enum CAP { + ALL, ONE, QUORUM; + +} diff --git a/src/main/java/com/basho/riak/client/ClobberMutator.java b/src/main/java/com/basho/riak/client/ClobberMutator.java new file mode 100644 index 000000000..9cfce8487 --- /dev/null +++ b/src/main/java/com/basho/riak/client/ClobberMutator.java @@ -0,0 +1,32 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class ClobberMutator implements Mutation { + + private final String newValue; + + public ClobberMutator(String newValue) { + this.newValue = newValue; + } + + public String apply(String v) { + return newValue; + } + +} diff --git a/src/main/java/com/basho/riak/client/ConflictResolver.java b/src/main/java/com/basho/riak/client/ConflictResolver.java new file mode 100644 index 000000000..24bcdc394 --- /dev/null +++ b/src/main/java/com/basho/riak/client/ConflictResolver.java @@ -0,0 +1,26 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; + +/** + * @author russell + * + */ +public interface ConflictResolver { + + RiakObject resolve(final Collection siblings) throws UnresolvedConflictException; + +} diff --git a/src/main/java/com/basho/riak/client/DeleteOperation.java b/src/main/java/com/basho/riak/client/DeleteOperation.java new file mode 100644 index 000000000..4e6be2325 --- /dev/null +++ b/src/main/java/com/basho/riak/client/DeleteOperation.java @@ -0,0 +1,44 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class DeleteOperation implements RiakOperation { + + private Integer rw; + private int retries = 0; + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.RiakOperation#execute() + */ + public Boolean execute() throws RiakRetryFailedException { + return true; + } + + public DeleteOperation rw(int rw) { + this.rw = rw; + return this; + } + + public DeleteOperation retry(int times) { + this.retries = times; + return this; + } + +} diff --git a/src/main/java/com/basho/riak/client/DoNothingResolver.java b/src/main/java/com/basho/riak/client/DoNothingResolver.java new file mode 100644 index 000000000..eccedcb4c --- /dev/null +++ b/src/main/java/com/basho/riak/client/DoNothingResolver.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; + +/** + * @author russell + * + */ +public class DoNothingResolver implements ConflictResolver { + + public RiakObject resolve(final Collection siblings) throws UnresolvedConflictException { + throw new UnresolvedConflictException("meh", siblings); + } + +} diff --git a/src/main/java/com/basho/riak/client/DummyRiakObject.java b/src/main/java/com/basho/riak/client/DummyRiakObject.java new file mode 100644 index 000000000..fcb9e490b --- /dev/null +++ b/src/main/java/com/basho/riak/client/DummyRiakObject.java @@ -0,0 +1,96 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Date; +import java.util.Iterator; +import java.util.Map; + +/** + * @author russell + * + */ +public class DummyRiakObject implements RiakObject { + + /* (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getBucket() + */ + public Bucket getBucket() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getVClock() + */ + public VClock getVClock() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getKey() + */ + public String getKey() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getVtag() + */ + public String getVtag() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getLastModified() + */ + public Date getLastModified() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getContentType() + */ + public String getContentType() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getMeta() + */ + public Map getMeta() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getBucketName() + */ + public String getBucketName() { + return null; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakObject#getValue() + */ + public String getValue() { + return null; + } + +} diff --git a/src/main/java/com/basho/riak/client/FetchBucket.java b/src/main/java/com/basho/riak/client/FetchBucket.java new file mode 100644 index 000000000..94c299a47 --- /dev/null +++ b/src/main/java/com/basho/riak/client/FetchBucket.java @@ -0,0 +1,45 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class FetchBucket implements RiakOperation { + + private int retry = 0; + private boolean fetchKeys = false; + private boolean fetchProperties = true; + + public Bucket execute() { + return null; + } + + public FetchBucket retry(int i) { + this.retry = i; + return this; + } + + public FetchBucket fetchKeys(boolean fetchKeys) { + this.fetchKeys = fetchKeys; + return this; + } + + public FetchBucket fetchProperties(boolean fetchProperties) { + this.fetchProperties = fetchProperties; + return this; + } + +} diff --git a/src/main/java/com/basho/riak/client/FetchOperation.java b/src/main/java/com/basho/riak/client/FetchOperation.java new file mode 100644 index 000000000..79fec1bad --- /dev/null +++ b/src/main/java/com/basho/riak/client/FetchOperation.java @@ -0,0 +1,44 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Arrays; + +/** + * @author russell + * + */ +public class FetchOperation implements RiakOperation { + + private Integer r; + private ConflictResolver resolver = new DoNothingResolver(); + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakOperation#execute() + */ + public RiakObject execute() throws UnresolvedConflictException, RiakRetryFailedException { + return resolver.resolve(Arrays.asList(new RiakObject[] {})); + } + + public FetchOperation withResolver(ConflictResolver resolver) { + this.resolver = resolver; + return this; + } + + public FetchOperation r(int r) { + this.r = r; + return this; + } + +} diff --git a/src/main/java/com/basho/riak/client/Mutation.java b/src/main/java/com/basho/riak/client/Mutation.java new file mode 100644 index 000000000..7e837b9ac --- /dev/null +++ b/src/main/java/com/basho/riak/client/Mutation.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public interface Mutation { + + T apply(T value); + +} diff --git a/src/main/java/com/basho/riak/client/NamedErlangFunction.java b/src/main/java/com/basho/riak/client/NamedErlangFunction.java new file mode 100644 index 000000000..1ac6ea514 --- /dev/null +++ b/src/main/java/com/basho/riak/client/NamedErlangFunction.java @@ -0,0 +1,53 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * Models a named erlang function. + * + * Immutable. + * + * @author russell + * + */ +public class NamedErlangFunction implements NamedFunction { + private final String mod; + private final String fun; + + /** + * @param mod + * the module that contains the function. + * @param fun + * the function name. + */ + public NamedErlangFunction(String mod, String fun) { + this.mod = mod; + this.fun = fun; + } + + /** + * @return the erlang module that contains the function. + */ + public String getMod() { + return mod; + } + + /** + * @return the function name. + */ + public String getFun() { + return fun; + } + +} diff --git a/src/main/java/com/basho/riak/client/NamedFunction.java b/src/main/java/com/basho/riak/client/NamedFunction.java new file mode 100644 index 000000000..15e8a9122 --- /dev/null +++ b/src/main/java/com/basho/riak/client/NamedFunction.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * Tag interface. + * + * @author russell + * + */ +public interface NamedFunction { + +} diff --git a/src/main/java/com/basho/riak/client/RiakClient.java b/src/main/java/com/basho/riak/client/RiakClient.java new file mode 100644 index 000000000..2e172ebce --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakClient.java @@ -0,0 +1,32 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public interface RiakClient { + + FetchBucket fetchBucket(String bucketName); + + WriteBucket updateBucket(Bucket b); + + /** + * @param string + * @return + */ + WriteBucket createBucket(String string); + +} diff --git a/src/main/java/com/basho/riak/client/RiakException.java b/src/main/java/com/basho/riak/client/RiakException.java new file mode 100644 index 000000000..6b70d52c4 --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakException.java @@ -0,0 +1,27 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class RiakException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -570192397144432757L; + +} diff --git a/src/main/java/com/basho/riak/client/RiakFactory.java b/src/main/java/com/basho/riak/client/RiakFactory.java new file mode 100644 index 000000000..2954edf9f --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakFactory.java @@ -0,0 +1,38 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class RiakFactory { + + public static RiakClient defaultClient() { + return new RiakClient() { + public FetchBucket fetchBucket(String bucketName) { + return new FetchBucket(); + } + + public WriteBucket updateBucket(Bucket b) { + return new WriteBucket(b); + } + + public WriteBucket createBucket(String bucketName) { + return new WriteBucket(bucketName); + } + }; + } + +} diff --git a/src/main/java/com/basho/riak/client/RiakLink.java b/src/main/java/com/basho/riak/client/RiakLink.java new file mode 100644 index 000000000..fdd96ebeb --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakLink.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public interface RiakLink { + +} diff --git a/src/main/java/com/basho/riak/client/RiakObject.java b/src/main/java/com/basho/riak/client/RiakObject.java new file mode 100644 index 000000000..9b4d04684 --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakObject.java @@ -0,0 +1,44 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +/** + * @author russell + * + */ +public interface RiakObject extends Iterable { + + Bucket getBucket(); + + VClock getVClock(); + + String getKey(); + + String getVtag(); + + Date getLastModified(); + + String getContentType(); + + Map getMeta(); + + String getBucketName(); + + String getValue(); + +} diff --git a/src/main/java/com/basho/riak/client/RiakOperation.java b/src/main/java/com/basho/riak/client/RiakOperation.java new file mode 100644 index 000000000..8c2bb8a97 --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakOperation.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public interface RiakOperation { + + T execute() throws RiakException; + +} diff --git a/src/main/java/com/basho/riak/client/RiakRetryFailedException.java b/src/main/java/com/basho/riak/client/RiakRetryFailedException.java new file mode 100644 index 000000000..fb5e44833 --- /dev/null +++ b/src/main/java/com/basho/riak/client/RiakRetryFailedException.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class RiakRetryFailedException extends RiakException { + +} diff --git a/src/main/java/com/basho/riak/client/StoreOperation.java b/src/main/java/com/basho/riak/client/StoreOperation.java new file mode 100644 index 000000000..94c47e162 --- /dev/null +++ b/src/main/java/com/basho/riak/client/StoreOperation.java @@ -0,0 +1,79 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Date; +import java.util.Iterator; +import java.util.Map; + +/** + * @author russell + * + */ +public class StoreOperation implements RiakOperation { + + private Integer w; + private Integer dw; + private boolean returnBody = false; + private int retries = 0; + private Mutation mutation; + private ConflictResolver resolver; + + /** + * @return null if returnBody is false + */ + public RiakObject execute() { + // fetch, resolve, mutate, put + return new DummyRiakObject(); + } + + public StoreOperation w(int w) { + this.w = w; + return this; + } + + public StoreOperation dw(int dw) { + this.dw = dw; + return this; + } + + public StoreOperation returnBody(boolean returnBody) { + this.returnBody = returnBody; + return this; + } + + public StoreOperation retry(int times) { + this.retries = times; + return this; + } + + public StoreOperation withMutator(Mutation mutation) { + this.mutation = mutation; + return this; + } + + public StoreOperation withResolver(ConflictResolver resolver) { + this.resolver = resolver; + return this; + } + + /** + * @param string + * @return + */ + public StoreOperation withValue(String newValue) { + this.mutation = new ClobberMutator(newValue); + return this; + } +} diff --git a/src/main/java/com/basho/riak/client/TakeTheFirst.java b/src/main/java/com/basho/riak/client/TakeTheFirst.java new file mode 100644 index 000000000..7f7d4cf16 --- /dev/null +++ b/src/main/java/com/basho/riak/client/TakeTheFirst.java @@ -0,0 +1,35 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; + +/** + * @author russell + * + */ +public class TakeTheFirst implements ConflictResolver { + + /* (non-Javadoc) + * @see com.basho.riak.client.ConflictResolver#resolve(java.util.Collection) + */ + public RiakObject resolve(final Collection siblings) throws UnresolvedConflictException { + RiakObject result = null; + if(siblings != null && !siblings.isEmpty()) { + result = siblings.iterator().next(); + } + return result; + } + +} diff --git a/src/main/java/com/basho/riak/client/UnresolvedConflictException.java b/src/main/java/com/basho/riak/client/UnresolvedConflictException.java new file mode 100644 index 000000000..37fe5c52e --- /dev/null +++ b/src/main/java/com/basho/riak/client/UnresolvedConflictException.java @@ -0,0 +1,51 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.util.Collection; + +/** + * @author russell + * + */ +public class UnresolvedConflictException extends RiakException { + + /** + * eclipse generated id + */ + private static final long serialVersionUID = -219858468775752064L; + + private final String reason; + private final Collection siblings; + + public UnresolvedConflictException(String reason, Collection siblings) { + this.reason = reason; + this.siblings = siblings; + } + + /** + * @return the reason + */ + public String getReason() { + return reason; + } + + /** + * @return the siblings + */ + public Collection getSiblings() { + return siblings; + } + +} diff --git a/src/main/java/com/basho/riak/client/VClock.java b/src/main/java/com/basho/riak/client/VClock.java new file mode 100644 index 000000000..6177f060d --- /dev/null +++ b/src/main/java/com/basho/riak/client/VClock.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public interface VClock { + +} diff --git a/src/main/java/com/basho/riak/client/WriteBucket.java b/src/main/java/com/basho/riak/client/WriteBucket.java new file mode 100644 index 000000000..c7328b56c --- /dev/null +++ b/src/main/java/com/basho/riak/client/WriteBucket.java @@ -0,0 +1,140 @@ +/* + * This file is provided 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.basho.riak.client; + +/** + * @author russell + * + */ +public class WriteBucket implements RiakOperation { + + private Bucket bucket; + private String name; + + private Quorum r; + private Quorum w; + private Quorum dw; + private Quorum rw; + private Integer nval; + private Boolean allowSiblings; + private NamedErlangFunction chashKeyFunction; + private int retries = 0; + + public WriteBucket(Bucket b) { + this.bucket = b; + } + + public WriteBucket(String name) { + this.name = name; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.RiakOperation#execute() + */ + public Bucket execute() throws RiakException { + // TODO Auto-generated method stub + return null; + } + + public WriteBucket r(CAP quorum) { + this.r = new Quorum(quorum); + return this; + } + + public WriteBucket r(int quorum) { + this.r = new Quorum(quorum); + return this; + } + + public WriteBucket w(CAP quorum) { + this.w = new Quorum(quorum); + return this; + } + + public WriteBucket w(int quorum) { + this.w = new Quorum(quorum); + return this; + } + + public WriteBucket dw(CAP quorum) { + this.dw = new Quorum(quorum); + return this; + } + + public WriteBucket dw(int quorum) { + this.dw = new Quorum(quorum); + return this; + } + + public WriteBucket rw(CAP quorum) { + this.rw = new Quorum(quorum); + return this; + } + + public WriteBucket rw(int quorum) { + this.rw = new Quorum(quorum); + return this; + } + + public WriteBucket nval(int nval) { + this.nval = nval; + return this; + } + + public WriteBucket allowSiblings(boolean allowSiblings) { + this.allowSiblings = allowSiblings; + return this; + } + + /** + * @param times + * @return + */ + public WriteBucket retry(int times) { + this.retries = times; + return this; + } + + /** + * @param namedErlangFunction + * @return + */ + public WriteBucket chashKeyFunction(NamedErlangFunction chashKeyFunction) { + this.chashKeyFunction = chashKeyFunction; + return this; + } + + private static final class Quorum { + private Integer i; + private CAP cap; + + public Quorum(int i) { + this.i = i; + } + + public Quorum(CAP cap) { + this.cap = cap; + } + + boolean isCAP() { + return cap != null; + } + + boolean isInt() { + return i != null; + } + } +} diff --git a/src/test/java/com/basho/riak/client/BasicOperations.java b/src/test/java/com/basho/riak/client/BasicOperations.java new file mode 100644 index 000000000..3e8f3cd80 --- /dev/null +++ b/src/test/java/com/basho/riak/client/BasicOperations.java @@ -0,0 +1,93 @@ +/* + * This file is provided 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.basho.riak.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import com.megacorp.kv.exceptions.BailException; +import com.megacorp.kv.exceptions.MyCheckedBusinessException; + +/** + * @author russell + * + */ +public class BasicOperations { + + @Test public void basicOpertaions() throws Exception { + final RiakClient c = RiakFactory.defaultClient(); + + c.createBucket("testBucket").retry(2).nval(3).execute(); + + Bucket b = c.fetchBucket("bucket").retry(1).fetchKeys(false).fetchProperties(true).execute(); + + assertEquals(3, b.getNVal()); + assertEquals("bucket", b.getName()); + + b = c.updateBucket(b).r(CAP.QUORUM).w(CAP.ALL).dw(CAP.ONE).rw(2) + .nval(5) + .allowSiblings(true) + .chashKeyFunction(new NamedErlangFunction("keys", "hash")) + .execute(); + + assertEquals(5, b.getNVal()); + assertTrue(b.isAllowSiblings()); + assertEquals(2, b.getRW()); + + // most simple store + b.store("k", "v").execute(); + + // most simple fetch + RiakObject o = b.fetch("k").execute(); + + assertEquals("v", o.getValue()); + + try { + b.fetch("k").r(1).withResolver(new DoNothingResolver()).execute(); + fail("Expected UnresolvedConflictException"); + } catch (UnresolvedConflictException e) { + assertEquals("meh", e.getReason()); + throw new MyCheckedBusinessException(e); + } catch(RiakRetryFailedException e) { + throw new BailException(e); + } + + // update value + o = b.store(o) + .w(3).dw(1) + .returnBody(true) + .retry(3) + .withMutator(new ClobberMutator("new value")) + .withResolver(new TakeTheFirst()) + .execute(); + + + assertEquals("new value", o.getValue()); + + o = b.fetch(o).execute(); + + //with default mutator + b.store(o).withValue("new value").execute(); + + b.delete(o).rw(3).retry(2).execute(); + + o = b.fetch(o).execute(); + + assertNull(o); + } +} diff --git a/src/test/java/com/megacorp/kv/exceptions/BailException.java b/src/test/java/com/megacorp/kv/exceptions/BailException.java new file mode 100644 index 000000000..1218eadb1 --- /dev/null +++ b/src/test/java/com/megacorp/kv/exceptions/BailException.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.megacorp.kv.exceptions; + +/** + * @author russell + * + */ +public class BailException extends Exception { + + private static final long serialVersionUID = -5108005628109579300L; + + public BailException(Exception e) { + super(e); + } + +} diff --git a/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java new file mode 100644 index 000000000..d7c833940 --- /dev/null +++ b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java @@ -0,0 +1,30 @@ +/* + * This file is provided 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.megacorp.kv.exceptions; + +import com.basho.riak.client.UnresolvedConflictException; + +/** + * @author russell + * + */ +public class MyCheckedBusinessException extends Exception { + + private static final long serialVersionUID = 6815472644307051262L; + + public MyCheckedBusinessException(UnresolvedConflictException e) { + super(e); + } + +} From 1c7a70c5ebace9f35ca3dd821318554fd6651439 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 29 Mar 2011 17:40:05 +0100 Subject: [PATCH 002/764] Some implementation of a fluid API. --- pom.xml | 7 +- .../java/com/basho/riak/client/Bucket.java | 57 --- .../basho/riak/client/DummyRiakObject.java | 96 ---- .../com/basho/riak/client/RiakFactory.java | 38 -- .../com/basho/riak/client/StoreOperation.java | 79 ---- .../com/basho/riak/client/WriteBucket.java | 140 ------ .../{RiakClient.java => raw/Command.java} | 18 +- .../basho/riak/client/raw/DefaultRetrier.java | 45 ++ .../com/basho/riak/client/raw/RawClient.java | 57 +++ .../com/basho/riak/client/raw/Retrier.java | 25 + .../com/basho/riak/client/raw/StoreMeta.java | 64 +++ .../basho/riak/client/raw/pbc/PBClient.java | 227 ++++++++++ .../query/LinkWalkSpec.java} | 4 +- .../query/MapReduceTimeoutException.java} | 14 +- .../basho/riak/newapi/DefaultRiakObject.java | 313 +++++++++++++ .../RiakClient.java} | 33 +- .../{client => newapi}/RiakException.java | 13 +- .../com/basho/riak/newapi/RiakFactory.java | 66 +++ .../riak/{client => newapi}/RiakLink.java | 2 +- .../com/basho/riak/newapi/RiakObject.java | 100 ++++ .../riak/newapi/RiakRetryFailedException.java | 34 ++ .../com/basho/riak/newapi/bucket/Bucket.java | 44 ++ .../riak/newapi/bucket/BucketProperties.java | 117 +++++ .../riak/newapi/bucket/DefaultBucket.java | 291 ++++++++++++ .../bucket/DefaultBucketProperties.java | 428 ++++++++++++++++++ .../basho/riak/newapi/bucket/FetchBucket.java | 71 +++ .../basho/riak/newapi/bucket/WriteBucket.java | 190 ++++++++ .../newapi/builders/RiakObjectBuilder.java | 95 ++++ .../basho/riak/newapi/cap/BasicVClock.java | 31 ++ .../riak/{client => newapi/cap}/CAP.java | 3 +- .../cap}/ConflictResolver.java | 6 +- .../riak/{client => newapi/cap}/Mutation.java | 5 +- .../com/basho/riak/newapi/cap/Quorum.java | 28 ++ .../cap}/UnresolvedConflictException.java | 7 +- .../riak/{client => newapi/cap}/VClock.java | 2 +- .../convert/Converter.java} | 29 +- .../operations/DeleteObject.java} | 14 +- .../operations/FetchObject.java} | 25 +- .../operations}/RiakOperation.java | 4 +- .../riak/newapi/operations/StoreObject.java | 157 +++++++ .../query/LinkWalk.java} | 42 +- .../basho/riak/newapi/query/MapReduce.java | 33 ++ .../riak/newapi/query/MapReduceResult.java | 48 ++ .../riak/newapi/query/MapReduceSpec.java | 25 + .../query}/NamedErlangFunction.java | 2 +- .../query}/NamedFunction.java | 2 +- .../query/WalkResult.java} | 12 +- .../basho/riak/client/BasicOperations.java | 46 +- .../client/itest/ITestBucketOperations.java | 77 ++++ .../MyCheckedBusinessException.java | 2 +- 50 files changed, 2730 insertions(+), 538 deletions(-) delete mode 100644 src/main/java/com/basho/riak/client/Bucket.java delete mode 100644 src/main/java/com/basho/riak/client/DummyRiakObject.java delete mode 100644 src/main/java/com/basho/riak/client/RiakFactory.java delete mode 100644 src/main/java/com/basho/riak/client/StoreOperation.java delete mode 100644 src/main/java/com/basho/riak/client/WriteBucket.java rename src/main/java/com/basho/riak/client/{RiakClient.java => raw/Command.java} (71%) create mode 100644 src/main/java/com/basho/riak/client/raw/DefaultRetrier.java create mode 100644 src/main/java/com/basho/riak/client/raw/RawClient.java create mode 100644 src/main/java/com/basho/riak/client/raw/Retrier.java create mode 100644 src/main/java/com/basho/riak/client/raw/StoreMeta.java create mode 100644 src/main/java/com/basho/riak/client/raw/pbc/PBClient.java rename src/main/java/com/basho/riak/client/{RiakRetryFailedException.java => raw/query/LinkWalkSpec.java} (86%) rename src/main/java/com/basho/riak/client/{ClobberMutator.java => raw/query/MapReduceTimeoutException.java} (69%) create mode 100644 src/main/java/com/basho/riak/newapi/DefaultRiakObject.java rename src/main/java/com/basho/riak/{client/RiakObject.java => newapi/RiakClient.java} (53%) rename src/main/java/com/basho/riak/{client => newapi}/RiakException.java (80%) create mode 100644 src/main/java/com/basho/riak/newapi/RiakFactory.java rename src/main/java/com/basho/riak/{client => newapi}/RiakLink.java (95%) create mode 100644 src/main/java/com/basho/riak/newapi/RiakObject.java create mode 100644 src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/Bucket.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java create mode 100644 src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java create mode 100644 src/main/java/com/basho/riak/newapi/cap/BasicVClock.java rename src/main/java/com/basho/riak/{client => newapi/cap}/CAP.java (94%) rename src/main/java/com/basho/riak/{client => newapi/cap}/ConflictResolver.java (79%) rename src/main/java/com/basho/riak/{client => newapi/cap}/Mutation.java (94%) create mode 100644 src/main/java/com/basho/riak/newapi/cap/Quorum.java rename src/main/java/com/basho/riak/{client => newapi/cap}/UnresolvedConflictException.java (89%) rename src/main/java/com/basho/riak/{client => newapi/cap}/VClock.java (94%) rename src/main/java/com/basho/riak/{client/TakeTheFirst.java => newapi/convert/Converter.java} (54%) rename src/main/java/com/basho/riak/{client/DeleteOperation.java => newapi/operations/DeleteObject.java} (73%) rename src/main/java/com/basho/riak/{client/FetchOperation.java => newapi/operations/FetchObject.java} (53%) rename src/main/java/com/basho/riak/{client => newapi/operations}/RiakOperation.java (88%) create mode 100644 src/main/java/com/basho/riak/newapi/operations/StoreObject.java rename src/main/java/com/basho/riak/{client/FetchBucket.java => newapi/query/LinkWalk.java} (52%) create mode 100644 src/main/java/com/basho/riak/newapi/query/MapReduce.java create mode 100644 src/main/java/com/basho/riak/newapi/query/MapReduceResult.java create mode 100644 src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java rename src/main/java/com/basho/riak/{client => newapi/query}/NamedErlangFunction.java (97%) rename src/main/java/com/basho/riak/{client => newapi/query}/NamedFunction.java (94%) rename src/main/java/com/basho/riak/{client/DoNothingResolver.java => newapi/query/WalkResult.java} (70%) create mode 100644 src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java diff --git a/pom.xml b/pom.xml index 2ec443afc..f18ca1d2e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,11 @@ + + com.basho.riak + riak-client + 0.14.1-SNAPSHOT + junit junit @@ -22,7 +27,7 @@ test - + diff --git a/src/main/java/com/basho/riak/client/Bucket.java b/src/main/java/com/basho/riak/client/Bucket.java deleted file mode 100644 index 8af374475..000000000 --- a/src/main/java/com/basho/riak/client/Bucket.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import java.util.Collection; -import java.util.Iterator; - -/** - * @author russell - * - */ -public interface Bucket { - - StoreOperation store(String key, String value); - - StoreOperation store(RiakObject o); - - FetchOperation fetch(String key); - - FetchOperation fetch(RiakObject o); - - DeleteOperation delete(RiakObject o); - - - String getName(); - boolean isAllowSiblings(); - boolean isLastWriteWins(); - int getNVal(); - String getBackend(); - int getSmallVClock(); - int getBigVClock(); - long getYoungVClock(); - long getOldVClock(); - Collection getPrecommitHooks(); - Collection getPostCommitHooks(); - NamedErlangFunction getChashKeyFunction(); - NamedErlangFunction getLinkWalkFunction(); - int getR(); - int getW(); - int getDW(); - int getRW(); - - // iterate the keys - Iterator iterator(); - -} diff --git a/src/main/java/com/basho/riak/client/DummyRiakObject.java b/src/main/java/com/basho/riak/client/DummyRiakObject.java deleted file mode 100644 index fcb9e490b..000000000 --- a/src/main/java/com/basho/riak/client/DummyRiakObject.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import java.util.Date; -import java.util.Iterator; -import java.util.Map; - -/** - * @author russell - * - */ -public class DummyRiakObject implements RiakObject { - - /* (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - public Iterator iterator() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getBucket() - */ - public Bucket getBucket() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getVClock() - */ - public VClock getVClock() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getKey() - */ - public String getKey() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getVtag() - */ - public String getVtag() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getLastModified() - */ - public Date getLastModified() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getContentType() - */ - public String getContentType() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getMeta() - */ - public Map getMeta() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getBucketName() - */ - public String getBucketName() { - return null; - } - - /* (non-Javadoc) - * @see com.basho.riak.client.RiakObject#getValue() - */ - public String getValue() { - return null; - } - -} diff --git a/src/main/java/com/basho/riak/client/RiakFactory.java b/src/main/java/com/basho/riak/client/RiakFactory.java deleted file mode 100644 index 2954edf9f..000000000 --- a/src/main/java/com/basho/riak/client/RiakFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -/** - * @author russell - * - */ -public class RiakFactory { - - public static RiakClient defaultClient() { - return new RiakClient() { - public FetchBucket fetchBucket(String bucketName) { - return new FetchBucket(); - } - - public WriteBucket updateBucket(Bucket b) { - return new WriteBucket(b); - } - - public WriteBucket createBucket(String bucketName) { - return new WriteBucket(bucketName); - } - }; - } - -} diff --git a/src/main/java/com/basho/riak/client/StoreOperation.java b/src/main/java/com/basho/riak/client/StoreOperation.java deleted file mode 100644 index 94c47e162..000000000 --- a/src/main/java/com/basho/riak/client/StoreOperation.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import java.util.Date; -import java.util.Iterator; -import java.util.Map; - -/** - * @author russell - * - */ -public class StoreOperation implements RiakOperation { - - private Integer w; - private Integer dw; - private boolean returnBody = false; - private int retries = 0; - private Mutation mutation; - private ConflictResolver resolver; - - /** - * @return null if returnBody is false - */ - public RiakObject execute() { - // fetch, resolve, mutate, put - return new DummyRiakObject(); - } - - public StoreOperation w(int w) { - this.w = w; - return this; - } - - public StoreOperation dw(int dw) { - this.dw = dw; - return this; - } - - public StoreOperation returnBody(boolean returnBody) { - this.returnBody = returnBody; - return this; - } - - public StoreOperation retry(int times) { - this.retries = times; - return this; - } - - public StoreOperation withMutator(Mutation mutation) { - this.mutation = mutation; - return this; - } - - public StoreOperation withResolver(ConflictResolver resolver) { - this.resolver = resolver; - return this; - } - - /** - * @param string - * @return - */ - public StoreOperation withValue(String newValue) { - this.mutation = new ClobberMutator(newValue); - return this; - } -} diff --git a/src/main/java/com/basho/riak/client/WriteBucket.java b/src/main/java/com/basho/riak/client/WriteBucket.java deleted file mode 100644 index c7328b56c..000000000 --- a/src/main/java/com/basho/riak/client/WriteBucket.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -/** - * @author russell - * - */ -public class WriteBucket implements RiakOperation { - - private Bucket bucket; - private String name; - - private Quorum r; - private Quorum w; - private Quorum dw; - private Quorum rw; - private Integer nval; - private Boolean allowSiblings; - private NamedErlangFunction chashKeyFunction; - private int retries = 0; - - public WriteBucket(Bucket b) { - this.bucket = b; - } - - public WriteBucket(String name) { - this.name = name; - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.client.RiakOperation#execute() - */ - public Bucket execute() throws RiakException { - // TODO Auto-generated method stub - return null; - } - - public WriteBucket r(CAP quorum) { - this.r = new Quorum(quorum); - return this; - } - - public WriteBucket r(int quorum) { - this.r = new Quorum(quorum); - return this; - } - - public WriteBucket w(CAP quorum) { - this.w = new Quorum(quorum); - return this; - } - - public WriteBucket w(int quorum) { - this.w = new Quorum(quorum); - return this; - } - - public WriteBucket dw(CAP quorum) { - this.dw = new Quorum(quorum); - return this; - } - - public WriteBucket dw(int quorum) { - this.dw = new Quorum(quorum); - return this; - } - - public WriteBucket rw(CAP quorum) { - this.rw = new Quorum(quorum); - return this; - } - - public WriteBucket rw(int quorum) { - this.rw = new Quorum(quorum); - return this; - } - - public WriteBucket nval(int nval) { - this.nval = nval; - return this; - } - - public WriteBucket allowSiblings(boolean allowSiblings) { - this.allowSiblings = allowSiblings; - return this; - } - - /** - * @param times - * @return - */ - public WriteBucket retry(int times) { - this.retries = times; - return this; - } - - /** - * @param namedErlangFunction - * @return - */ - public WriteBucket chashKeyFunction(NamedErlangFunction chashKeyFunction) { - this.chashKeyFunction = chashKeyFunction; - return this; - } - - private static final class Quorum { - private Integer i; - private CAP cap; - - public Quorum(int i) { - this.i = i; - } - - public Quorum(CAP cap) { - this.cap = cap; - } - - boolean isCAP() { - return cap != null; - } - - boolean isInt() { - return i != null; - } - } -} diff --git a/src/main/java/com/basho/riak/client/RiakClient.java b/src/main/java/com/basho/riak/client/raw/Command.java similarity index 71% rename from src/main/java/com/basho/riak/client/RiakClient.java rename to src/main/java/com/basho/riak/client/raw/Command.java index 2e172ebce..9a884556b 100644 --- a/src/main/java/com/basho/riak/client/RiakClient.java +++ b/src/main/java/com/basho/riak/client/raw/Command.java @@ -11,22 +11,16 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.raw; + +import java.io.IOException; /** * @author russell * */ -public interface RiakClient { - - FetchBucket fetchBucket(String bucketName); - - WriteBucket updateBucket(Bucket b); - - /** - * @param string - * @return - */ - WriteBucket createBucket(String string); +public interface Command { + T execute() throws IOException; + } diff --git a/src/main/java/com/basho/riak/client/raw/DefaultRetrier.java b/src/main/java/com/basho/riak/client/raw/DefaultRetrier.java new file mode 100644 index 000000000..14790043d --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/DefaultRetrier.java @@ -0,0 +1,45 @@ +/* + * This file is provided 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.basho.riak.client.raw; + +import java.io.IOException; + +import com.basho.riak.newapi.RiakRetryFailedException; + +/** + * @author russell + * + */ +public class DefaultRetrier implements Retrier { + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.spi.Retrier#attempt(com.basho.riak.client.spi.Command + * ) + */ + public T attempt(Command command, int times) throws RiakRetryFailedException { + try { + return command.execute(); + } catch (IOException e) { + if (times == 0) { + throw new RiakRetryFailedException(e); + } else { + return attempt(command, times--); + } + } + } + +} diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java new file mode 100644 index 000000000..0e1a6fe3c --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -0,0 +1,57 @@ +/* + * This file is provided 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.basho.riak.client.raw; + +import java.io.IOException; +import java.util.Iterator; + +import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.MapReduceSpec; +import com.basho.riak.newapi.query.WalkResult; + +/** + * @author russell + * + */ +public interface RawClient { + + // RiakObject + + RiakObject[] fetch(Bucket bucket, String key) throws IOException; + + RiakObject store(RiakObject object, StoreMeta storeMeta) throws IOException; + + void store(RiakObject object) throws IOException; + + void delete(RiakObject object) throws IOException; + + // Bucket + Iterator listBuckets() throws IOException; + + BucketProperties fetchBucket(String bucketName) throws IOException; + + void updateBucket(String name, BucketProperties bucketProperties) throws IOException; + + Iterator fetchBucketKeys(String bucketName) throws IOException; + + // Query + WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException; + + MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException; +} diff --git a/src/main/java/com/basho/riak/client/raw/Retrier.java b/src/main/java/com/basho/riak/client/raw/Retrier.java new file mode 100644 index 000000000..59a25a7d2 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/Retrier.java @@ -0,0 +1,25 @@ +/* + * This file is provided 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.basho.riak.client.raw; + +import com.basho.riak.newapi.RiakRetryFailedException; + +/** + * @author russell + * + */ +public interface Retrier { + + T attempt(Command command, int times) throws RiakRetryFailedException; +} diff --git a/src/main/java/com/basho/riak/client/raw/StoreMeta.java b/src/main/java/com/basho/riak/client/raw/StoreMeta.java new file mode 100644 index 000000000..50499ee84 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/StoreMeta.java @@ -0,0 +1,64 @@ +/* + * This file is provided 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.basho.riak.client.raw; + + +/** + * @author russell + * + */ +public class StoreMeta { + private final Integer w; + private final Integer dw; + private final Boolean returnBody; + + public StoreMeta(Integer w, Integer dw, Boolean returnBody) { + this.w = w; + this.dw = dw; + this.returnBody = returnBody; + } + + /** + * @return + * @see com.basho.riak.client.newapi.cap.StoreCAP#getW() + */ + public Integer getW() { + return w; + } + + public boolean hasW() { + return w != null; + } + + /** + * @return + * @see com.basho.riak.client.newapi.cap.StoreCAP#getDW() + */ + public Integer getDw() { + return dw; + } + + public boolean hasDW() { + return dw != null; + } + + /** + * @return the returnBody + */ + public Boolean getReturnBody() { + return returnBody; + } + + +} diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java new file mode 100644 index 000000000..2f56dce31 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java @@ -0,0 +1,227 @@ +/* + * This file is provided 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.basho.riak.client.raw.pbc; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.bucket.DefaultBucketProperties; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.MapReduceSpec; +import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.pbc.RiakClient; +import com.google.protobuf.ByteString; + +/** + * @author russell + * + */ +public class PBClient implements RawClient { + + private final RiakClient client; + + /** + * @param client + * @throws IOException + */ + public PBClient(String host, int port) throws IOException { + this.client = new RiakClient(host, port); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#fetch(java.lang.String, + * java.lang.String) + */ + public RiakObject[] fetch(Bucket bucket, String key) throws IOException { + if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + throw new IllegalArgumentException( + "bucket must not be null and bucket.getName() must not be null or empty or just whitespace."); + } + + if (key == null || key.trim().equals("")) { + throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); + } + return convert(client.fetch(bucket.getName(), key), bucket); + } + + /** + * @param fetch + * @return + */ + private RiakObject[] convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { + Collection converted = new ArrayList(); + + if (pbcObjects != null) { + for (com.basho.riak.pbc.RiakObject o : pbcObjects) { + converted.add(convert(o, bucket)); + } + } + + return converted.toArray(new RiakObject[converted.size()]); + } + + /** + * @param o + * @return + */ + private RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) { + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + + builder.withValue(nullSafeToStringUtf8(o.getValue())); + builder.withVClock(nullSafeToStringUtf8(o.getVclock())); + + Date lastModified = o.getLastModified(); + + if (lastModified != null) { + builder.withLastModified(lastModified.getTime()); + } + + return builder.build(); + } + + /** + * @param value + * @return + */ + private String nullSafeToStringUtf8(ByteString value) { + return value == null ? null : value.toStringUtf8(); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject + * , com.basho.riak.client.raw.StoreMeta) + */ + public RiakObject store(RiakObject object, StoreMeta storeMeta) throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject + * ) + */ + public void store(RiakObject object) throws IOException {} + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.client.RiakObject + * ) + */ + public void delete(RiakObject object) throws IOException {} + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#listBuckets() + */ + public Iterator listBuckets() throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#fetchBucket(java.lang.String) + */ + public BucketProperties fetchBucket(String bucketName) throws IOException { + if (bucketName == null || bucketName.trim().equals("")) { + throw new IllegalArgumentException("bucketName cannot be null, empty or all whitespace"); + } + com.basho.riak.pbc.BucketProperties properties = client.getBucketProperties(ByteString.copyFromUtf8(bucketName)); + + return convert(properties); + } + + /** + * @param properties + * @return + */ + private BucketProperties convert(com.basho.riak.pbc.BucketProperties properties) { + return new DefaultBucketProperties.Builder().allowSiblings(properties.getAllowMult()).nVal(properties.getNValue()).build(); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#updateBucketProperties(com.basho. + * riak.client.bucket.BucketProperties) + */ + public void updateBucket(final String name, final BucketProperties bucketProperties) throws IOException { + com.basho.riak.pbc.BucketProperties properties = convert(bucketProperties); + client.setBucketProperties(ByteString.copyFromUtf8(name), properties); + + } + + /** + * @param bucketProperties + * @return + */ + private com.basho.riak.pbc.BucketProperties convert(BucketProperties p) { + return new com.basho.riak.pbc.BucketProperties().nValue(p.getNVal()).allowMult(p.getAllowSiblings()); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#fetchBucketKeys(java.lang.String) + */ + public Iterator fetchBucketKeys(String bucketName) throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.client.RiakObject + * , com.basho.riak.client.raw.query.LinkWalkSpec) + */ + public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#mapReduce(com.basho.riak.client.query + * .MapReduceSpec) + */ + public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException { + return null; + } + +} diff --git a/src/main/java/com/basho/riak/client/RiakRetryFailedException.java b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java similarity index 86% rename from src/main/java/com/basho/riak/client/RiakRetryFailedException.java rename to src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java index fb5e44833..15aaf745c 100644 --- a/src/main/java/com/basho/riak/client/RiakRetryFailedException.java +++ b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java @@ -11,12 +11,12 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.raw.query; /** * @author russell * */ -public class RiakRetryFailedException extends RiakException { +public interface LinkWalkSpec { } diff --git a/src/main/java/com/basho/riak/client/ClobberMutator.java b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java similarity index 69% rename from src/main/java/com/basho/riak/client/ClobberMutator.java rename to src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java index 9cfce8487..ed243a6a6 100644 --- a/src/main/java/com/basho/riak/client/ClobberMutator.java +++ b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java @@ -11,22 +11,18 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.raw.query; /** * @author russell * */ -public class ClobberMutator implements Mutation { +public class MapReduceTimeoutException extends Exception { - private final String newValue; + private static final long serialVersionUID = -1293682325413369755L; - public ClobberMutator(String newValue) { - this.newValue = newValue; - } - - public String apply(String v) { - return newValue; + private MapReduceTimeoutException() { + super(); } } diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java new file mode 100644 index 000000000..298e8c078 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -0,0 +1,313 @@ +/* + * This file is provided 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.basho.riak.newapi; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; + +/** + * @author russell + * + */ +public class DefaultRiakObject implements RiakObject { + private final Bucket bucket; + private final String key; + private final VClock vclock; + private final String vtag; + private final long lastModified; + + private final Object linksLock = new Object(); + private final Collection links; + private final Object userMetaLock = new Object(); + private final Map userMeta; + + private volatile String contentType; + private volatile String value; + + /** + * Use the builder. + * + * @param bucket + * @param key + * @param vclock + * @param conflict + * @param vtag + * @param lastModified + * @param contentType + * @param value + * @param siblings + * @param links + * @param userMeta + */ + public DefaultRiakObject(Bucket bucket, String key, VClock vclock, String vtag, final Date lastModified, + String contentType, String value, final Collection links, + final Map userMeta) { + + if (bucket == null) { + throw new IllegalArgumentException("Bucket cannot be null"); + } + + if(key == null) { + throw new IllegalArgumentException("Key cannot be null"); + } + + this.bucket = bucket; + this.key = key; + this.vclock = vclock; + this.vtag = vtag; + this.lastModified = lastModified == null ? 0 : lastModified.getTime(); + safeSetContentType(contentType); + this.value = value; + this.links = copy(links); + this.userMeta = copy(userMeta); + } + + private Map copy(Map userMeta) { + Map copy; + + if (userMeta == null) { + copy = new HashMap(); + } else { + copy = new HashMap(userMeta); + } + + return copy; + } + + private Collection copy(Collection links) { + Collection copy; + if (links == null) { + copy = new ArrayList(); + } else { + copy = new ArrayList(links); + } + return copy; + } + + private void safeSetContentType(String contentType) { + if (contentType == null) { + this.contentType = ""; + } else { + this.contentType = contentType; + } + } + + private Collection deepCopy(final Collection siblings) { + final ArrayList copy = new ArrayList(); + + if (siblings != null && siblings.size() == 0) { + for (RiakObject o : siblings) { + copy.add(RiakObjectBuilder.from(o).build()); + } + } + + return copy; + } + + public Iterator iterator() { + return links.iterator(); + } + + public Bucket getBucket() { + return bucket; + } + + public VClock getVClock() { + return vclock; + } + + public String getKey() { + return key; + } + + public String getVtag() { + return vtag; + } + + public Date getLastModified() { + Date lastModified = null; + + if (this.lastModified != 0) { + lastModified = new Date(this.lastModified); + } + + return lastModified; + } + + public String getContentType() { + return contentType; + } + + public Map getMeta() { + return new HashMap(userMeta); + } + + public String getBucketName() { + return bucket.getName(); + } + + public String getValue() { + return value; + } + + // mutate + + public RiakObject setValue(String value) { + this.value = value; + return this; + } + + public RiakObject setContentType(String contentType) { + this.contentType = contentType; + return this; + } + + /** + * Add link to this RiakObject's links. + * + * @param link + * a {@link RiakLink} to add. + * @return this RiakObject. + */ + public RiakObject addLink(RiakLink link) { + if (link != null) { + synchronized (linksLock) { + links.add(link); + } + } + return this; + } + + /** + * Remove a {@link RiakLink} from this RiakObject. + * + * @param link + * the {@link RiakLink} to remove + * @return this RiakObject + */ + public RiakObject removeLink(final RiakLink link) { + synchronized (linksLock) { + this.links.remove(link); + } + return this; + } + + /** + * Does this RiakObject has any {@link RiakLink}s? + * + * @return true if there are links, false otherwise + */ + public boolean hasLinks() { + synchronized (linksLock) { + return !links.isEmpty(); + } + } + + /** + * How many {@link RiakLink}s does this RiakObject have? + * + * @return the number of {@link RiakLink}s this object has. + */ + public int numLinks() { + synchronized (linksLock) { + return links.size(); + } + } + + public Collection getLinks() { + synchronized (linksLock) { + return new ArrayList(links); + } + } + + /** + * Checks if the collection of RiakLinks contains the one passed in. + * + * @param riakLink + * a RiakLink + * @return true if the RiakObject's link collection contains riakLink. + */ + public boolean hasLink(final RiakLink riakLink) { + synchronized (linksLock) { + return links.contains(riakLink); + } + } + + /** + * Adds the key, value to the collection of user meta for this object. + * + * @param key + * @param value + * @return this RiakObject. + */ + public RiakObject addUsermeta(String key, String value) { + synchronized (userMetaLock) { + userMeta.put(key, value); + } + return this; + } + + /** + * @return true if there are any user meta data set on this RiakObject. + */ + public boolean hasUsermeta() { + synchronized (userMetaLock) { + return !userMeta.isEmpty(); + } + } + + /** + * @param key + * @return + */ + public boolean hasUsermeta(String key) { + synchronized (userMetaLock) { + return userMeta.containsKey(key); + } + } + + /** + * Get an item of user meta data. + * + * @param key + * the user meta data item key + * @return The value for the given key or null. + */ + public String getUsermeta(String key) { + synchronized (userMetaLock) { + return userMeta.get(key); + } + + } + + /** + * @param key + * the key of the item to remove + */ + public RiakObject removeUsermeta(String key) { + synchronized (userMetaLock) { + userMeta.remove(key); + } + return this; + } + +} diff --git a/src/main/java/com/basho/riak/client/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakClient.java similarity index 53% rename from src/main/java/com/basho/riak/client/RiakObject.java rename to src/main/java/com/basho/riak/newapi/RiakClient.java index 9b4d04684..6573e2cf4 100644 --- a/src/main/java/com/basho/riak/client/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakClient.java @@ -11,34 +11,29 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi; -import java.util.Collection; -import java.util.Date; -import java.util.Map; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.FetchBucket; +import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.query.LinkWalk; +import com.basho.riak.newapi.query.MapReduce; /** * @author russell * */ -public interface RiakObject extends Iterable { +public interface RiakClient { - Bucket getBucket(); + FetchBucket fetchBucket(String bucketName); - VClock getVClock(); + WriteBucket updateBucket(Bucket b); - String getKey(); + WriteBucket createBucket(String string); - String getVtag(); - - Date getLastModified(); - - String getContentType(); - - Map getMeta(); - - String getBucketName(); - - String getValue(); + // query - links + LinkWalk walk(final RiakObject startObject); + // query - m/r + MapReduce mapReduce(); } diff --git a/src/main/java/com/basho/riak/client/RiakException.java b/src/main/java/com/basho/riak/newapi/RiakException.java similarity index 80% rename from src/main/java/com/basho/riak/client/RiakException.java rename to src/main/java/com/basho/riak/newapi/RiakException.java index 6b70d52c4..f15a59c58 100644 --- a/src/main/java/com/basho/riak/client/RiakException.java +++ b/src/main/java/com/basho/riak/newapi/RiakException.java @@ -11,17 +11,22 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi; /** * @author russell - * + * */ public class RiakException extends Exception { /** - * + * @param e */ - private static final long serialVersionUID = -570192397144432757L; + public RiakException(Exception e) { + super(e); + } + public RiakException() { + super(); + } } diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java new file mode 100644 index 000000000..e78b69a16 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -0,0 +1,66 @@ +/* + * This file is provided 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.basho.riak.newapi; + +import java.io.IOException; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.pbc.PBClient; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.FetchBucket; +import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.query.LinkWalk; +import com.basho.riak.newapi.query.MapReduce; + +/** + * @author russell + * + */ +public class RiakFactory { + + public static RiakClient defaultClient() throws RiakException { + + try { + final RawClient client = new PBClient("127.0.0.1", 8087); + + return new RiakClient() { + public LinkWalk walk(RiakObject startObject) { + return null; + } + + public WriteBucket updateBucket(Bucket b) { + WriteBucket op = new WriteBucket(client, b); + return op; + } + + public MapReduce mapReduce() { + return null; + } + + public FetchBucket fetchBucket(String bucketName) { + FetchBucket op = new FetchBucket(client, bucketName); + return op; + } + + public WriteBucket createBucket(String bucketName) { + WriteBucket op = new WriteBucket(client, bucketName); + return op; + } + }; + } catch (IOException e) { + throw new RiakException(e); + } + } + +} diff --git a/src/main/java/com/basho/riak/client/RiakLink.java b/src/main/java/com/basho/riak/newapi/RiakLink.java similarity index 95% rename from src/main/java/com/basho/riak/client/RiakLink.java rename to src/main/java/com/basho/riak/newapi/RiakLink.java index fdd96ebeb..497f1f0d5 100644 --- a/src/main/java/com/basho/riak/client/RiakLink.java +++ b/src/main/java/com/basho/riak/newapi/RiakLink.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java new file mode 100644 index 000000000..f3c84a146 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -0,0 +1,100 @@ +/* + * This file is provided 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.basho.riak.newapi; + +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.VClock; + +/** + * @author russell + * + */ +public interface RiakObject extends Iterable { + + Bucket getBucket(); + + String getBucketName(); + + String getValue(); + + VClock getVClock(); + + String getKey(); + + String getVtag(); + + Date getLastModified(); + + String getContentType(); + + // links + boolean hasLinks(); + + int numLinks(); + + boolean hasLink(final RiakLink riakLink); + + // user meta + Map getMeta(); + + boolean hasUsermeta(); + + boolean hasUsermeta(String key); + + String getUsermeta(String key); + + // Mutate + + RiakObject setValue(String value); + + RiakObject setContentType(String contentType); + + /** + * Add link to this RiakObject's links. + * + * @param link + * a {@link RiakLink} to add. + * @return this RiakObject. + */ + RiakObject addLink(RiakLink link); + + /** + * Remove a {@link RiakLink} from this RiakObject. + * + * @param link + * the {@link RiakLink} to remove + * @return this RiakObject + */ + RiakObject removeLink(final RiakLink link); + + /** + * Adds the key, value to the collection of user meta for this object. + * + * @param key + * @param value + * @return this RiakObject. + */ + RiakObject addUsermeta(String key, String value); + + /** + * @param key + * the key of the item to remove + */ + RiakObject removeUsermeta(String key); + +} diff --git a/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java b/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java new file mode 100644 index 000000000..4f586ca8b --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.newapi; + +/** + * @author russell + * + */ +public class RiakRetryFailedException extends RiakException { + + /** + * + */ + private static final long serialVersionUID = -3306642055623535202L; + + /** + * @param e + */ + public RiakRetryFailedException(Exception e) { + super(e); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java new file mode 100644 index 000000000..f8df458df --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java @@ -0,0 +1,44 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.util.Iterator; + +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.operations.DeleteObject; +import com.basho.riak.newapi.operations.FetchObject; +import com.basho.riak.newapi.operations.StoreObject; + + +/** + * @author russell + * + */ +public interface Bucket extends BucketProperties { + + String getName(); + + StoreObject store(String key, String value); + + StoreObject store(T o); + + FetchObject fetch(String key, Class type); + + FetchObject fetch(T o); + + DeleteObject delete(T o); + + Iterator keys() throws RiakException; +} diff --git a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java new file mode 100644 index 000000000..855b2bdfe --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java @@ -0,0 +1,117 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.util.Collection; + +import com.basho.riak.newapi.cap.Quorum; +import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.NamedFunction; + +/** + * @author russell + * + */ +public interface BucketProperties { + + + /** + * @return the allowSiblings if set, or null if not + */ + Boolean getAllowSiblings(); + + /** + * @return the lastWriteWins if set or null if not + */ + Boolean getLastWriteWins(); + + /** + * @return the nVal if set or null if not + */ + Integer getNVal(); + + /** + * @return the backend if set, or null. + */ + String getBackend(); + + /** + * + * @return the small vclock pruning property if set, or null. + */ + int getSmallVClock(); + + /** + * + * @return the big vclock pruning size property if set, or null. + */ + int getBigVClock(); + + /** + * + * @return the young vclock prune property if set, or null. + */ + long getYoungVClock(); + + /** + * + * @return the old vclock prune property if set, or null + */ + long getOldVClock(); + + /** + * @return the pre commit hooks, if any, or an empty collection. + */ + Collection getPrecommitHooks(); + + /** + * @return the post commit hooks, if ant, or an empty collection. + */ + Collection getPostcommitHooks(); + + /** + * + * @return the default CAP read quorum for this bucket, or null. + */ + Quorum getR(); + + /** + * + * @return the default CAP write quorum for this bucket, or null. + */ + Quorum getW(); + + /** + * + * @return the default CAP RW (delete) quorum for this bucket, or null. + */ + Quorum getRW(); + + /** + * + * @return the default CAP durable write quorum for this bucket, or null. + */ + Quorum getDW(); + + /** + * @return the key hashing function for the bucket, or null. + */ + NamedErlangFunction getChashKeyFunction(); + + /** + * @return the link walking function for the bucket, or null. + */ + NamedErlangFunction getLinkWalkFunction(); + +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java new file mode 100644 index 000000000..2dc0e1995 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -0,0 +1,291 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.Mutation; +import com.basho.riak.newapi.cap.Quorum; +import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.newapi.operations.DeleteObject; +import com.basho.riak.newapi.operations.FetchObject; +import com.basho.riak.newapi.operations.StoreObject; +import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.NamedFunction; + +/** + * @author russell + * + */ +public class DefaultBucket implements Bucket { + + private final String name; + private final BucketProperties properties; + private final RawClient client; + + /** + * @param properties + * @param client + */ + protected DefaultBucket(String name, BucketProperties properties, RawClient client) { + this.name = name; + this.properties = properties; + this.client = client; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#getName() + */ + public String getName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getAllowSiblings() + */ + public Boolean getAllowSiblings() { + return properties.getAllowSiblings(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getLastWriteWins() + */ + public Boolean getLastWriteWins() { + return properties.getLastWriteWins(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getNVal() + */ + public Integer getNVal() { + return properties.getNVal(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getBackend() + */ + public String getBackend() { + return properties.getBackend(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getSmallVClock() + */ + public int getSmallVClock() { + return properties.getSmallVClock(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getBigVClock() + */ + public int getBigVClock() { + return properties.getBigVClock(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getYoungVClock() + */ + public long getYoungVClock() { + return properties.getYoungVClock(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getOldVClock() + */ + public long getOldVClock() { + return properties.getOldVClock(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getPrecommitHooks() + */ + public Collection getPrecommitHooks() { + return properties.getPrecommitHooks(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getPostcommitHooks() + */ + public Collection getPostcommitHooks() { + return properties.getPostcommitHooks(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getR() + */ + public Quorum getR() { + return properties.getR(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getW() + */ + public Quorum getW() { + return properties.getW(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getRW() + */ + public Quorum getRW() { + return properties.getRW(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getDW() + */ + public Quorum getDW() { + return properties.getDW(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getChashKeyFunction() + */ + public NamedErlangFunction getChashKeyFunction() { + return properties.getChashKeyFunction(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.BucketProperties#getLinkWalkFunction() + */ + public NamedErlangFunction getLinkWalkFunction() { + return properties.getLinkWalkFunction(); + } + + /** + * Iterate over the keys for this bucket (Expensive, are you sure?) + */ + public Iterator keys() throws RiakException { + try { + return client.fetchBucketKeys(name); + } catch (IOException e) { + throw new RiakException(e); + } + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, + * java.lang.String) + */ + public StoreObject store(final String key, final String value) { + final Bucket b = this; + + return new StoreObject(client, b, key).withMutator(new Mutation() { + public RiakObject apply(RiakObject original) { + return original.setValue(value); + } + }).withResolver(new ConflictResolver() { + + public RiakObject resolve(Collection siblings) throws UnresolvedConflictException { + if (siblings.size() > 1) { + throw new UnresolvedConflictException("Siblings found", siblings); + } else if (siblings.size() == 1) { + return siblings.iterator().next(); + } else { + return RiakObjectBuilder.newBuilder(b, key).build(); + } + } + }).withConverter(new Converter() { + + public RiakObject toDomain(RiakObject riakObject) { + return riakObject; + } + + public RiakObject fromDomain(RiakObject domainObject) { + return domainObject; + } + }); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.Object) + */ + public StoreObject store(T o) { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String, + * java.lang.Class) + */ + public FetchObject fetch(String key, Class type) { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.Object) + */ + public FetchObject fetch(T o) { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.Object) + */ + public DeleteObject delete(T o) { + return null; + } +} diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java new file mode 100644 index 000000000..2317bb2f3 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java @@ -0,0 +1,428 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.util.ArrayList; +import java.util.Collection; + +import com.basho.riak.newapi.cap.CAP; +import com.basho.riak.newapi.cap.Quorum; +import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.NamedFunction; + +/** + * Since not all interfaces to Riak are equal in terms of what they provide not + * all RawClients can be expected to set all values. Which means that *any* of + * the getters may return null. + * + * @author russell + */ +public class DefaultBucketProperties implements BucketProperties { + + private final Boolean allowSiblings; + private final Boolean lastWriteWins; + private final Integer nVal; + private final String backend; + private final Integer smallVClock; + private final Integer bigVClock; + private final Long youngVClock; + private final Long oldVClock; + private final Collection precommitHooks; + private final Collection postcommitHooks; + private final Quorum r; + private final Quorum w; + private final Quorum dw; + private final Quorum rw; + private final NamedErlangFunction chashKeyFunction; + private final NamedErlangFunction linkWalkFunction; + + /** + * @param allowSiblings + * @param lastWriteWins + * @param nVal + * @param backend + * @param smallVClock + * @param bigVClock + * @param youngVClock + * @param oldVClock + * @param precommitHooks + * @param postcommitHooks + * @param r + * @param w + * @param dw + * @param rw + * @param chashKeyFunction + * @param linkWalkFunction + */ + private DefaultBucketProperties(Builder builder) { + this.allowSiblings = builder.allowSiblings; + this.lastWriteWins = builder.lastWriteWins; + this.nVal = builder.nVal; + this.backend = builder.backend; + this.smallVClock = builder.smallVClock; + this.bigVClock = builder.bigVClock; + this.youngVClock = builder.youngVClock; + this.oldVClock = builder.oldVClock; + this.precommitHooks = builder.precommitHooks; + this.postcommitHooks = builder.postcommitHooks; + this.r = builder.r; + this.w = builder.w; + this.dw = builder.dw; + this.rw = builder.rw; + this.chashKeyFunction = builder.chashKeyFunction; + this.linkWalkFunction = builder.linkWalkFunction; + } + + /** + * @return the allowSiblings if set, or null if not + */ + public Boolean getAllowSiblings() { + return allowSiblings; + } + + /** + * @return the lastWriteWins if set or null if not + */ + public Boolean getLastWriteWins() { + return lastWriteWins; + } + + /** + * @return the nVal if set or null if not + */ + public Integer getNVal() { + return nVal; + } + + /** + * @return the backend if set, or null. + */ + public String getBackend() { + return backend; + } + + /** + * + * @return the small vclock pruning property if set, or null. + */ + public int getSmallVClock() { + return smallVClock; + } + + /** + * + * @return the big vclock pruning size property if set, or null. + */ + public int getBigVClock() { + return bigVClock; + } + + /** + * + * @return the young vclock prune property if set, or null. + */ + public long getYoungVClock() { + return youngVClock; + } + + /** + * + * @return the old vclock prune property if set, or null + */ + public long getOldVClock() { + return oldVClock; + } + + /** + * @return the pre commit hooks, if any, or an empty collection. + */ + public Collection getPrecommitHooks() { + return precommitHooks; + } + + /** + * @return the post commit hooks, if ant, or an empty collection. + */ + public Collection getPostcommitHooks() { + return postcommitHooks; + } + + /** + * + * @return the default CAP read quorum for this bucket, or null. + */ + public Quorum getR() { + return r; + } + + /** + * + * @return the default CAP write quorum for this bucket, or null. + */ + public Quorum getW() { + return w; + } + + /** + * + * @return the default CAP RW (delete) quorum for this bucket, or null. + */ + public Quorum getRW() { + return rw; + } + + /** + * + * @return the default CAP durable write quorum for this bucket, or null. + */ + public Quorum getDW() { + return dw; + } + + /** + * @return the key hashing function for the bucket, or null. + */ + public NamedErlangFunction getChashKeyFunction() { + return chashKeyFunction; + } + + /** + * @return the link walking function for the bucket, or null. + */ + public NamedErlangFunction getLinkWalkFunction() { + return linkWalkFunction; + } + + /** + * + * @return a Builder populated from this BucketProperties' values. + */ + public DefaultBucketProperties.Builder fromMe() { + return DefaultBucketProperties.from(this); + } + + /** + * + * @param properties + * @return a Builder populated with properties values. + */ + public static DefaultBucketProperties.Builder from(DefaultBucketProperties properties) { + return DefaultBucketProperties.Builder.from(properties); + } + + /** + * Use to create instances of BucketProperties. + * + * @author russell + * + */ + public static final class Builder { + + public NamedErlangFunction linkWalkFunction; + public NamedErlangFunction chashKeyFunction; + public Quorum rw; + public Quorum dw; + public Quorum w; + public Quorum r; + public Collection postcommitHooks = new ArrayList(); + public Collection precommitHooks = new ArrayList(); + public Long oldVClock; + public Long youngVClock; + public Integer bigVClock; + public Integer smallVClock; + public String backend; + public int nVal; + public Boolean lastWriteWins; + public Boolean allowSiblings; + + public BucketProperties build() { + return new DefaultBucketProperties(this); + } + + /** + * @param p + * the BucketProperties to copy to the builder + * @return a builder with all values set from p + */ + public static Builder from(DefaultBucketProperties p) { + Builder b = new Builder(); + b.allowSiblings = p.getAllowSiblings(); + b.lastWriteWins = p.getLastWriteWins(); + b.nVal = p.getNVal(); + b.backend = p.getBackend(); + b.smallVClock = p.getSmallVClock(); + b.bigVClock = p.getBigVClock(); + b.youngVClock = p.getYoungVClock(); + b.oldVClock = p.getOldVClock(); + b.postcommitHooks.addAll(p.getPostcommitHooks()); + b.precommitHooks.addAll(p.getPrecommitHooks()); + b.r = p.getR(); + b.w = p.getW(); + b.dw = p.getDW(); + b.rw = p.getRW(); + b.chashKeyFunction = p.getChashKeyFunction(); + b.linkWalkFunction = p.getLinkWalkFunction(); + return b; + } + + public Builder allowSiblings(boolean allowSiblings) { + this.allowSiblings = allowSiblings; + return this; + } + + public Builder lastWriteWins(boolean lastWriteWins) { + this.lastWriteWins = lastWriteWins; + return this; + } + + public Builder nVal(int nVal) { + this.nVal = nVal; + return this; + } + + public Builder backend(String backend) { + this.backend = backend; + return this; + } + + public Builder precommitHooks(Collection precommitHooks) { + this.precommitHooks = new ArrayList(precommitHooks); + return this; + } + + public Builder addPrecommitHook(NamedFunction preCommitHook) { + if (this.precommitHooks == null) { + this.precommitHooks = new ArrayList(); + } + this.precommitHooks.add(preCommitHook); + return this; + } + + public Builder postcommitHooks(Collection postCommitHooks) { + this.postcommitHooks = new ArrayList(postCommitHooks); + return this; + } + + public Builder addPostcommitHook(NamedErlangFunction postcommitHook) { + if (this.postcommitHooks == null) { + this.postcommitHooks = new ArrayList(); + } + this.precommitHooks.add(postcommitHook); + return this; + } + + public Builder chashKeyFunction(NamedErlangFunction chashKeyFunction) { + this.chashKeyFunction = chashKeyFunction; + return this; + } + + public Builder linkWalkFunction(NamedErlangFunction linkWalkFunction) { + this.linkWalkFunction = linkWalkFunction; + return this; + } + + /** + * @param smallVClock + * @return + */ + public Builder smallVClock(int smallVClock) { + this.smallVClock = smallVClock; + return this; + } + + /** + * @param bigVClock + * @return + */ + public Builder bigVClock(int bigVClock) { + this.bigVClock = bigVClock; + return this; + } + + /** + * @param youngVClock + * @return + */ + public Builder youngVClock(long youngVClock) { + this.youngVClock = youngVClock; + return this; + } + + /** + * @param oldVClock + * @return + */ + public Builder oldVClock(long oldVClock) { + this.oldVClock = oldVClock; + return this; + } + + /** + * @param r + * @return + */ + public Builder r(CAP r) { + this.r = new Quorum(r); + return this; + } + + public Builder r(int r) { + this.r = new Quorum(r); + return this; + } + + /** + * @param w + * @return + */ + public Builder w(CAP w) { + this.w = new Quorum(w); + return this; + } + + public Builder w(int w) { + this.w = new Quorum(w); + return this; + } + + /** + * @param rw + * @return + */ + public Builder rw(CAP rw) { + this.rw = new Quorum(rw); + return this; + } + + public Builder rw(int rw) { + this.rw = new Quorum(rw); + return this; + } + + /** + * @param dw + * @return + */ + public Builder dw(CAP dw) { + this.dw = new Quorum(dw); + return this; + } + + public Builder dw(int dw) { + this.dw = new Quorum(dw); + return this; + } + + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java b/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java new file mode 100644 index 000000000..577bf4c13 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java @@ -0,0 +1,71 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.io.IOException; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.operations.RiakOperation; + +/** + * @author russell + * + */ +public class FetchBucket implements RiakOperation { + + private final RawClient client; + private final String bucket; + + private int retry = 0; + private boolean fetchKeys = false; + private boolean fetchProperties = true; + + /** + * @param client + * @param bucket + */ + public FetchBucket(RawClient client, String bucket) { + this.client = client; + this.bucket = bucket; + } + + public Bucket execute() throws RiakRetryFailedException { + BucketProperties properties = new DefaultRetrier().attempt(new Command() { + public BucketProperties execute() throws IOException { + return client.fetchBucket(bucket); + } + }, retry); + + return new DefaultBucket(bucket, properties, client); + } + + public FetchBucket retry(int i) { + this.retry = i; + return this; + } + + public FetchBucket fetchKeys(boolean fetchKeys) { + this.fetchKeys = fetchKeys; + return this; + } + + public FetchBucket fetchProperties(boolean fetchProperties) { + this.fetchProperties = fetchProperties; + return this; + } + +} diff --git a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java new file mode 100644 index 000000000..055d63953 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java @@ -0,0 +1,190 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import java.io.IOException; +import java.util.Collection; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.DefaultBucketProperties.Builder; +import com.basho.riak.newapi.cap.CAP; +import com.basho.riak.newapi.operations.RiakOperation; +import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.NamedFunction; + +/** + * @author russell + * + */ +public class WriteBucket implements RiakOperation { + + private final RawClient client; + private String name; + + private Builder builder = new Builder(); + private int retries = 0; + + public WriteBucket(final RawClient client, Bucket b) { + this.name = b.getName(); + this.client = client; + } + + public WriteBucket(final RawClient client, String name) { + this.name = name; + this.client = client; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.RiakOperation#execute() + */ + public Bucket execute() throws RiakRetryFailedException { + final BucketProperties propsToStore = builder.build(); + + new DefaultRetrier().attempt(new Command() { + public Boolean execute() throws IOException { + client.updateBucket(name, propsToStore); + return true; + } + }, retries); + + BucketProperties properties = new DefaultRetrier().attempt(new Command() { + public BucketProperties execute() throws IOException { + return client.fetchBucket(name); + } + }, retries); + + return new DefaultBucket(name, properties, client); + } + + public WriteBucket allowSiblings(boolean allowSiblings) { + builder.allowSiblings(allowSiblings); + return this; + } + + public WriteBucket lastWriteWins(boolean lastWriteWins) { + builder.lastWriteWins(lastWriteWins); + return this; + } + + public WriteBucket nVal(int nVal) { + builder.nVal(nVal); + return this; + } + + public WriteBucket backend(String backend) { + builder.backend(backend); + return this; + } + + public WriteBucket precommitHooks(Collection precommitHooks) { + builder.precommitHooks(precommitHooks); + return this; + } + + public WriteBucket addPrecommitHook(NamedFunction preCommitHook) { + builder.addPrecommitHook(preCommitHook); + return this; + } + + public WriteBucket postcommitHooks(Collection postCommitHooks) { + builder.postcommitHooks(postCommitHooks); + return this; + } + + public WriteBucket addPostcommitHook(NamedErlangFunction postcommitHook) { + builder.addPostcommitHook(postcommitHook); + return this; + } + + public WriteBucket chashKeyFunction(NamedErlangFunction chashKeyFunction) { + builder.chashKeyFunction(chashKeyFunction); + return this; + } + + public WriteBucket linkWalkFunction(NamedErlangFunction linkWalkFunction) { + builder.linkWalkFunction(linkWalkFunction); + return this; + } + + public WriteBucket smallVClock(int smallVClock) { + builder.smallVClock(smallVClock); + return this; + } + + public WriteBucket bigVClock(int bigVClock) { + builder.bigVClock(bigVClock); + return this; + } + + public WriteBucket youngVClock(long youngVClock) { + builder.youngVClock(youngVClock); + return this; + } + + public WriteBucket oldVClock(long oldVClock) { + builder.oldVClock(oldVClock); + return this; + } + + public WriteBucket r(CAP r) { + builder.r(r); + return this; + } + + public WriteBucket r(int r) { + builder.r(r); + return this; + } + + public WriteBucket w(CAP w) { + builder.w(w); + return this; + } + + public WriteBucket w(int w) { + builder.w(w); + return this; + } + + public WriteBucket rw(CAP rw) { + builder.rw(rw); + return this; + } + + public WriteBucket rw(int rw) { + builder.rw(rw); + return this; + } + + public WriteBucket dw(CAP dw) { + builder.dw(dw); + return this; + } + + public WriteBucket dw(int dw) { + builder.dw(dw); + return this; + } + + public WriteBucket retry(int n) { + this.retries = n; + return this; + } + +} diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java new file mode 100644 index 000000000..aa09eca16 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -0,0 +1,95 @@ +/* + * This file is provided 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.basho.riak.newapi.builders; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import com.basho.riak.newapi.DefaultRiakObject; +import com.basho.riak.newapi.RiakLink; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.BasicVClock; +import com.basho.riak.newapi.cap.VClock; + +/** + * @author russell + * + */ +public class RiakObjectBuilder { + private final Bucket bucket; + private final String key; + private String value; + private VClock vclock; + private String vtag; + private Date lastModified; + private Collection links = new ArrayList(); + private Map userMeta = new HashMap(); + private String contentType; + + private RiakObjectBuilder(Bucket bucket, String key) { + this.bucket = bucket; + this.key = key; + } + + public static RiakObjectBuilder newBuilder(Bucket bucket, String key) { + return new RiakObjectBuilder(bucket, key); + } + + public static RiakObjectBuilder from(RiakObject o) { + return new RiakObjectBuilder(o.getBucket(), o.getKey()); + } + + public RiakObject build() { + return new DefaultRiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); + } + + public RiakObjectBuilder withValue(String value) { + this.value = value; + return this; + } + + public RiakObjectBuilder withVClock(String value) { + this.vclock = new BasicVClock(value); + return this; + } + + public RiakObjectBuilder withVtag(String vtag) { + this.vtag = vtag; + return this; + } + + public RiakObjectBuilder withLastModified(long lastModified) { + this.lastModified = new Date(lastModified); + return this; + } + + public RiakObjectBuilder withLinks(Collection links) { + this.links = new ArrayList(links); + return this; + } + + public RiakObjectBuilder withUsermeta(Map usermeta) { + this.userMeta = new HashMap(usermeta); + return this; + } + + public RiakObjectBuilder withContentType(String contentType) { + this.contentType = contentType; + return this; + } +} diff --git a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java new file mode 100644 index 000000000..20c806394 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java @@ -0,0 +1,31 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + +/** + * @author russell + * + */ +public class BasicVClock implements VClock { + + private final String value; + + public BasicVClock(final String value) { + if (value == null) { + throw new IllegalArgumentException("VClock value cannot be null"); + } + this.value = value; + } + +} diff --git a/src/main/java/com/basho/riak/client/CAP.java b/src/main/java/com/basho/riak/newapi/cap/CAP.java similarity index 94% rename from src/main/java/com/basho/riak/client/CAP.java rename to src/main/java/com/basho/riak/newapi/cap/CAP.java index 5fa4fef1f..6c79a4b91 100644 --- a/src/main/java/com/basho/riak/client/CAP.java +++ b/src/main/java/com/basho/riak/newapi/cap/CAP.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.cap; /** * @author russell @@ -19,5 +19,4 @@ */ public enum CAP { ALL, ONE, QUORUM; - } diff --git a/src/main/java/com/basho/riak/client/ConflictResolver.java b/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java similarity index 79% rename from src/main/java/com/basho/riak/client/ConflictResolver.java rename to src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java index 24bcdc394..5f418c543 100644 --- a/src/main/java/com/basho/riak/client/ConflictResolver.java +++ b/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.cap; import java.util.Collection; @@ -19,8 +19,8 @@ * @author russell * */ -public interface ConflictResolver { +public interface ConflictResolver { - RiakObject resolve(final Collection siblings) throws UnresolvedConflictException; + T resolve(final Collection siblings) throws UnresolvedConflictException; } diff --git a/src/main/java/com/basho/riak/client/Mutation.java b/src/main/java/com/basho/riak/newapi/cap/Mutation.java similarity index 94% rename from src/main/java/com/basho/riak/client/Mutation.java rename to src/main/java/com/basho/riak/newapi/cap/Mutation.java index 7e837b9ac..cfd7af060 100644 --- a/src/main/java/com/basho/riak/client/Mutation.java +++ b/src/main/java/com/basho/riak/newapi/cap/Mutation.java @@ -11,14 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.cap; + /** * @author russell * */ public interface Mutation { - T apply(T value); - } diff --git a/src/main/java/com/basho/riak/newapi/cap/Quorum.java b/src/main/java/com/basho/riak/newapi/cap/Quorum.java new file mode 100644 index 000000000..ddcf34196 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/Quorum.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + + +public final class Quorum { + private Integer i; + private CAP cap; + + public Quorum(int i) { + this.i = i; + } + + public Quorum(CAP cap) { + this.cap = cap; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/UnresolvedConflictException.java b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java similarity index 89% rename from src/main/java/com/basho/riak/client/UnresolvedConflictException.java rename to src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java index 37fe5c52e..2e76280b8 100644 --- a/src/main/java/com/basho/riak/client/UnresolvedConflictException.java +++ b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java @@ -11,12 +11,16 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.cap; import java.util.Collection; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; + /** * @author russell + * @param * */ public class UnresolvedConflictException extends RiakException { @@ -42,6 +46,7 @@ public String getReason() { } /** + * @param * @return the siblings */ public Collection getSiblings() { diff --git a/src/main/java/com/basho/riak/client/VClock.java b/src/main/java/com/basho/riak/newapi/cap/VClock.java similarity index 94% rename from src/main/java/com/basho/riak/client/VClock.java rename to src/main/java/com/basho/riak/newapi/cap/VClock.java index 6177f060d..9468e5823 100644 --- a/src/main/java/com/basho/riak/client/VClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/VClock.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.cap; /** * @author russell diff --git a/src/main/java/com/basho/riak/client/TakeTheFirst.java b/src/main/java/com/basho/riak/newapi/convert/Converter.java similarity index 54% rename from src/main/java/com/basho/riak/client/TakeTheFirst.java rename to src/main/java/com/basho/riak/newapi/convert/Converter.java index 7f7d4cf16..6f012ec53 100644 --- a/src/main/java/com/basho/riak/client/TakeTheFirst.java +++ b/src/main/java/com/basho/riak/newapi/convert/Converter.java @@ -11,25 +11,28 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.convert; -import java.util.Collection; +import com.basho.riak.newapi.RiakObject; /** * @author russell - * + * */ -public class TakeTheFirst implements ConflictResolver { +public interface Converter { + + /** + * Convert from domain specific type to RiakObject + * @param domainObject + * @return a RiakObject populated from domainObject + */ + RiakObject fromDomain(T domainObject); - /* (non-Javadoc) - * @see com.basho.riak.client.ConflictResolver#resolve(java.util.Collection) + /** + * Convert from a riakObject to a domain specific instance + * @param riakObject the RiakObject to convert + * @return an instance of type T */ - public RiakObject resolve(final Collection siblings) throws UnresolvedConflictException { - RiakObject result = null; - if(siblings != null && !siblings.isEmpty()) { - result = siblings.iterator().next(); - } - return result; - } + T toDomain(RiakObject riakObject); } diff --git a/src/main/java/com/basho/riak/client/DeleteOperation.java b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java similarity index 73% rename from src/main/java/com/basho/riak/client/DeleteOperation.java rename to src/main/java/com/basho/riak/newapi/operations/DeleteObject.java index 4e6be2325..673ea5a63 100644 --- a/src/main/java/com/basho/riak/client/DeleteOperation.java +++ b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java @@ -11,13 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.operations; + +import com.basho.riak.newapi.RiakRetryFailedException; /** * @author russell * */ -public class DeleteOperation implements RiakOperation { +public class DeleteObject implements RiakOperation { private Integer rw; private int retries = 0; @@ -27,16 +29,16 @@ public class DeleteOperation implements RiakOperation { * * @see com.basho.riak.client.RiakOperation#execute() */ - public Boolean execute() throws RiakRetryFailedException { - return true; + public T execute() throws RiakRetryFailedException { + return null; } - public DeleteOperation rw(int rw) { + public DeleteObject rw(int rw) { this.rw = rw; return this; } - public DeleteOperation retry(int times) { + public DeleteObject retry(int times) { this.retries = times; return this; } diff --git a/src/main/java/com/basho/riak/client/FetchOperation.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java similarity index 53% rename from src/main/java/com/basho/riak/client/FetchOperation.java rename to src/main/java/com/basho/riak/newapi/operations/FetchObject.java index 79fec1bad..c001c075a 100644 --- a/src/main/java/com/basho/riak/client/FetchOperation.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -11,34 +11,43 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.operations; -import java.util.Arrays; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.Converter; /** * @author russell * */ -public class FetchOperation implements RiakOperation { +public class FetchObject implements RiakOperation { private Integer r; - private ConflictResolver resolver = new DoNothingResolver(); + private ConflictResolver resolver; + private Converter converter; /* (non-Javadoc) * @see com.basho.riak.client.RiakOperation#execute() */ - public RiakObject execute() throws UnresolvedConflictException, RiakRetryFailedException { - return resolver.resolve(Arrays.asList(new RiakObject[] {})); + public T execute() throws UnresolvedConflictException, RiakRetryFailedException { + return null; } - public FetchOperation withResolver(ConflictResolver resolver) { + public FetchObject withResolver(ConflictResolver resolver) { this.resolver = resolver; return this; } - public FetchOperation r(int r) { + public FetchObject r(int r) { this.r = r; return this; } + + public FetchObject withConverter(Converter converter) { + this.converter = converter; + return this; + } } diff --git a/src/main/java/com/basho/riak/client/RiakOperation.java b/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java similarity index 88% rename from src/main/java/com/basho/riak/client/RiakOperation.java rename to src/main/java/com/basho/riak/newapi/operations/RiakOperation.java index 8c2bb8a97..7aa3521b6 100644 --- a/src/main/java/com/basho/riak/client/RiakOperation.java +++ b/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java @@ -11,7 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.operations; + +import com.basho.riak.newapi.RiakException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java new file mode 100644 index 000000000..878a77733 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -0,0 +1,157 @@ +/* + * This file is provided 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.basho.riak.newapi.operations; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.Mutation; +import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.Converter; + +/** + * @author russell + * + */ +public class StoreObject implements RiakOperation { + + private final RawClient client; + private final Bucket bucket; + + private Integer w; + private Integer dw; + private boolean returnBody = false; + + private int retries = 0; + private Mutation mutation; + private ConflictResolver resolver; + private Converter converter; + + private String key; + + /** + * Create a StoreObject to use the given RawClient to talk to riak. + * + * @param client + * The configured client to use. + */ + public StoreObject(final RawClient client, Bucket bucket) { + this.client = client; + this.bucket = bucket; + } + + public StoreObject(final RawClient client, Bucket bucket, String key) { + this(client, bucket); + this.key = key; + } + + /** + * @return null if returnBody is false + * @throws RiakException + */ + public T execute() throws RiakRetryFailedException, UnresolvedConflictException { + // fetch, resolve, mutate, put + final RiakObject[] ros = new DefaultRetrier().attempt(new Command() { + public RiakObject[] execute() throws IOException { + return client.fetch(bucket, key); + } + }, retries); + + final Collection siblings = new ArrayList(ros.length); + + for (RiakObject o : ros) { + siblings.add(converter.toDomain(o)); + } + + final T resolved = resolver.resolve(siblings); + final T mutated = mutation.apply(resolved); + + final RiakObject o = converter.fromDomain(mutated); + + final RiakObject stored = new DefaultRetrier().attempt(new Command() { + public RiakObject execute() throws IOException { + return client.store(o, generateStoreMeta()); + } + }, retries); + + return converter.toDomain(stored); + } + + /** + * @return + */ + private StoreMeta generateStoreMeta() { + return new StoreMeta(w, dw, returnBody); + } + + public StoreObject w(int w) { + this.w = w; + return this; + } + + public StoreObject dw(int dw) { + this.dw = dw; + return this; + } + + public StoreObject returnBody(boolean returnBody) { + this.returnBody = returnBody; + return this; + } + + public StoreObject retry(int times) { + this.retries = times; + return this; + } + + public StoreObject withMutator(Mutation mutation) { + this.mutation = mutation; + return this; + } + + public StoreObject withResolver(ConflictResolver resolver) { + this.resolver = resolver; + return this; + } + + public StoreObject withConverter(Converter converter) { + this.converter = converter; + return this; + } + + /** + * default clobber mutator. Beware. + * + * @param value new value + * @return this StoreObject + */ + public StoreObject withValue(final T value) { + this.mutation = new Mutation() { + public T apply(T in) { + return value; + } + }; + return this; + } +} diff --git a/src/main/java/com/basho/riak/client/FetchBucket.java b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java similarity index 52% rename from src/main/java/com/basho/riak/client/FetchBucket.java rename to src/main/java/com/basho/riak/newapi/query/LinkWalk.java index 94c299a47..2839269cd 100644 --- a/src/main/java/com/basho/riak/client/FetchBucket.java +++ b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java @@ -11,35 +11,35 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.query; + +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.operations.RiakOperation; /** + * * @author russell - * + * */ -public class FetchBucket implements RiakOperation { - - private int retry = 0; - private boolean fetchKeys = false; - private boolean fetchProperties = true; - - public Bucket execute() { - return null; - } +public class LinkWalk implements RiakOperation { - public FetchBucket retry(int i) { - this.retry = i; - return this; - } + private final RiakObject startObject; - public FetchBucket fetchKeys(boolean fetchKeys) { - this.fetchKeys = fetchKeys; - return this; + /** + * @param startObject + */ + public LinkWalk(final RiakObject startObject) { + this.startObject = startObject; } - public FetchBucket fetchProperties(boolean fetchProperties) { - this.fetchProperties = fetchProperties; - return this; + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.RiakOperation#execute() + */ + public WalkResult execute() throws RiakException { + return null; } } diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduce.java b/src/main/java/com/basho/riak/newapi/query/MapReduce.java new file mode 100644 index 000000000..0df9d279c --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/MapReduce.java @@ -0,0 +1,33 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.operations.RiakOperation; + + +/** + * @author russell + * + */ +public class MapReduce implements RiakOperation{ + + /* (non-Javadoc) + * @see com.basho.riak.client.RiakOperation#execute() + */ + public MapReduceResult execute() throws RiakException { + return null; + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java new file mode 100644 index 000000000..e388d5641 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java @@ -0,0 +1,48 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import java.util.Collection; +import java.util.Map; + +/** + * @author russell + * + */ +public interface MapReduceResult { + + /** + * Mapped results to a simple java type + * + * @param + * @param resultType A Java type to map the result too. + * @return a Collection of T. + */ + Collection getResult(T resultType); + + /** + * A Collection of results bound to Map where each result is + * like a C Struct. + * + * @return + */ + Collection> getResult(); + + /** + * The raw JSON string of the result + * + * @return + */ + String getResultRaw(); +} diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java b/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java new file mode 100644 index 000000000..071f20dd3 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java @@ -0,0 +1,25 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + + +/** + * A Map Reduce Query run it via {@link RiakClient#mapReduce(MapReduceSpec)} + * + * @author russell + * + */ +public class MapReduceSpec { + +} diff --git a/src/main/java/com/basho/riak/client/NamedErlangFunction.java b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java similarity index 97% rename from src/main/java/com/basho/riak/client/NamedErlangFunction.java rename to src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java index 1ac6ea514..ce92e6db8 100644 --- a/src/main/java/com/basho/riak/client/NamedErlangFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.query; /** * Models a named erlang function. diff --git a/src/main/java/com/basho/riak/client/NamedFunction.java b/src/main/java/com/basho/riak/newapi/query/NamedFunction.java similarity index 94% rename from src/main/java/com/basho/riak/client/NamedFunction.java rename to src/main/java/com/basho/riak/newapi/query/NamedFunction.java index 15e8a9122..6827726e7 100644 --- a/src/main/java/com/basho/riak/client/NamedFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/NamedFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.query; /** * Tag interface. diff --git a/src/main/java/com/basho/riak/client/DoNothingResolver.java b/src/main/java/com/basho/riak/newapi/query/WalkResult.java similarity index 70% rename from src/main/java/com/basho/riak/client/DoNothingResolver.java rename to src/main/java/com/basho/riak/newapi/query/WalkResult.java index eccedcb4c..b3b3256f4 100644 --- a/src/main/java/com/basho/riak/client/DoNothingResolver.java +++ b/src/main/java/com/basho/riak/newapi/query/WalkResult.java @@ -11,18 +11,16 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.newapi.query; import java.util.Collection; +import com.basho.riak.newapi.RiakObject; + /** + * * @author russell * */ -public class DoNothingResolver implements ConflictResolver { - - public RiakObject resolve(final Collection siblings) throws UnresolvedConflictException { - throw new UnresolvedConflictException("meh", siblings); - } - +public interface WalkResult extends Iterable>{ } diff --git a/src/test/java/com/basho/riak/client/BasicOperations.java b/src/test/java/com/basho/riak/client/BasicOperations.java index 3e8f3cd80..3d83a61c7 100644 --- a/src/test/java/com/basho/riak/client/BasicOperations.java +++ b/src/test/java/com/basho/riak/client/BasicOperations.java @@ -18,8 +18,21 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.Collection; + import org.junit.Test; +import com.basho.riak.client.raw.pbc.PBClient; +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.CAP; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.Mutation; +import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.query.NamedErlangFunction; import com.megacorp.kv.exceptions.BailException; import com.megacorp.kv.exceptions.MyCheckedBusinessException; @@ -32,33 +45,36 @@ public class BasicOperations { @Test public void basicOpertaions() throws Exception { final RiakClient c = RiakFactory.defaultClient(); - c.createBucket("testBucket").retry(2).nval(3).execute(); + c.createBucket("testBucket").retry(2).nVal(3).execute(); Bucket b = c.fetchBucket("bucket").retry(1).fetchKeys(false).fetchProperties(true).execute(); - assertEquals(3, b.getNVal()); + assertEquals(new Integer(3), b.getNVal()); assertEquals("bucket", b.getName()); b = c.updateBucket(b).r(CAP.QUORUM).w(CAP.ALL).dw(CAP.ONE).rw(2) - .nval(5) + .nVal(5) .allowSiblings(true) .chashKeyFunction(new NamedErlangFunction("keys", "hash")) .execute(); - assertEquals(5, b.getNVal()); - assertTrue(b.isAllowSiblings()); + assertEquals(new Integer(5), b.getNVal()); + assertTrue(b.getAllowSiblings()); assertEquals(2, b.getRW()); // most simple store b.store("k", "v").execute(); // most simple fetch - RiakObject o = b.fetch("k").execute(); + RiakObject o = b.fetch("k", RiakObject.class).execute(); assertEquals("v", o.getValue()); try { - b.fetch("k").r(1).withResolver(new DoNothingResolver()).execute(); + b.fetch("k", RiakObject.class).r(1).withResolver(new ConflictResolver() { + public RiakObject resolve(Collection siblings) throws UnresolvedConflictException { + throw new UnresolvedConflictException("meh", siblings); + }}).execute(); fail("Expected UnresolvedConflictException"); } catch (UnresolvedConflictException e) { assertEquals("meh", e.getReason()); @@ -72,8 +88,16 @@ public class BasicOperations { .w(3).dw(1) .returnBody(true) .retry(3) - .withMutator(new ClobberMutator("new value")) - .withResolver(new TakeTheFirst()) + .withMutator(new Mutation() { + public RiakObject apply(RiakObject value) { + return value.setValue("my new value"); + }}) + .withResolver(new ConflictResolver() { + + public RiakObject resolve(Collection siblings) + throws UnresolvedConflictException { + return siblings.iterator().next(); + }}) .execute(); @@ -81,8 +105,8 @@ public class BasicOperations { o = b.fetch(o).execute(); - //with default mutator - b.store(o).withValue("new value").execute(); + //with default clobber mutator + b.store(o).withValue(o.setValue("new value")).execute(); b.delete(o).rw(3).retry(2).execute(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java b/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java new file mode 100644 index 000000000..011785cd2 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java @@ -0,0 +1,77 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.*; + +import java.util.UUID; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.bucket.Bucket; + +/** + * @author russell + * + */ +public class ITestBucketOperations { + + @Test public void fetchBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.defaultClient(); + + Bucket b = c.fetchBucket(bucketName).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(3), b.getNVal()); + assertFalse(b.getAllowSiblings()); + } + + @Test public void updateBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.defaultClient(); + + Bucket b = c.fetchBucket(bucketName).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(3), b.getNVal()); + assertFalse(b.getAllowSiblings()); + + b = c.updateBucket(b).nVal(4).allowSiblings(true).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(4), b.getNVal()); + assertTrue(b.getAllowSiblings()); + } + + + @Test public void createBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.defaultClient(); + + Bucket b = c.createBucket(bucketName).nVal(1).allowSiblings(true).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(1), b.getNVal()); + assertTrue(b.getAllowSiblings()); + } + +} diff --git a/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java index d7c833940..1a5e7fab1 100644 --- a/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java +++ b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java @@ -13,7 +13,7 @@ */ package com.megacorp.kv.exceptions; -import com.basho.riak.client.UnresolvedConflictException; +import com.basho.riak.newapi.cap.UnresolvedConflictException; /** * @author russell From f8601bc14bfb259d33c6a60fc81cab01dd990977 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 1 Apr 2011 16:37:17 +0100 Subject: [PATCH 003/764] Safety commit. --- pom.xml | 2 +- .../com/basho/riak/client/raw/RawClient.java | 12 +- .../com/basho/riak/client/raw/StoreMeta.java | 10 +- .../basho/riak/client/raw/pbc/PBClient.java | 129 +++++++++++++++++- .../basho/riak/newapi/DefaultRiakObject.java | 18 ++- .../com/basho/riak/newapi/RiakClient.java | 6 + .../com/basho/riak/newapi/RiakException.java | 4 + .../com/basho/riak/newapi/RiakFactory.java | 39 +++++- .../java/com/basho/riak/newapi/RiakLink.java | 8 +- .../com/basho/riak/newapi/RiakObject.java | 3 + .../riak/newapi/bucket/DefaultBucket.java | 9 +- .../bucket/DefaultBucketProperties.java | 2 +- .../newapi/builders/RiakObjectBuilder.java | 4 +- .../basho/riak/newapi/cap/BasicVClock.java | 9 +- .../com/basho/riak/newapi/cap/VClock.java | 7 +- .../riak/newapi/operations/StoreObject.java | 21 ++- .../basho/riak/client/BasicOperations.java | 3 +- .../client/itest/ITestBucketOperations.java | 77 ----------- 18 files changed, 253 insertions(+), 110 deletions(-) delete mode 100644 src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java diff --git a/pom.xml b/pom.xml index f18ca1d2e..dc968afcb 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ com.basho.riak riak-client - 0.14.1-SNAPSHOT + 0.14.2-SNAPSHOT junit diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index 0e1a6fe3c..41f9b8ef9 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -35,7 +35,7 @@ public interface RawClient { RiakObject[] fetch(Bucket bucket, String key) throws IOException; - RiakObject store(RiakObject object, StoreMeta storeMeta) throws IOException; + RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOException; void store(RiakObject object) throws IOException; @@ -54,4 +54,14 @@ public interface RawClient { WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException; MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException; + + /** + * If you don't set a client id explicitly at least call this to set one. + * It generates the 4 byte ID and sets that Id on the client + * IE you *don't* need to call setClientId() with the result of generate. + * @return the generated clientId for the client + */ + byte[] generateAndSetClientId() throws IOException; + void setClientId(byte[] clientId) throws IOException; + byte[] getClientId() throws IOException; } diff --git a/src/main/java/com/basho/riak/client/raw/StoreMeta.java b/src/main/java/com/basho/riak/client/raw/StoreMeta.java index 50499ee84..033f72abe 100644 --- a/src/main/java/com/basho/riak/client/raw/StoreMeta.java +++ b/src/main/java/com/basho/riak/client/raw/StoreMeta.java @@ -13,10 +13,9 @@ */ package com.basho.riak.client.raw; - /** * @author russell - * + * */ public class StoreMeta { private final Integer w; @@ -53,12 +52,15 @@ public boolean hasDW() { return dw != null; } + public boolean hasReturnBody() { + return returnBody != null; + } + /** * @return the returnBody */ public Boolean getReturnBody() { return returnBody; } - - + } diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java index 2f56dce31..51b031a92 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java @@ -18,19 +18,23 @@ import java.util.Collection; import java.util.Date; import java.util.Iterator; +import java.util.Map.Entry; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.MapReduceSpec; import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.RiakClient; import com.google.protobuf.ByteString; @@ -92,7 +96,8 @@ private RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); builder.withValue(nullSafeToStringUtf8(o.getValue())); - builder.withVClock(nullSafeToStringUtf8(o.getVclock())); + builder.withVClock(nullSafeToBytes(o.getVclock())); + builder.withVtag(o.getVtag()); Date lastModified = o.getLastModified(); @@ -103,6 +108,14 @@ private RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) return builder.build(); } + /** + * @param vclock + * @return + */ + private byte[] nullSafeToBytes(ByteString value) { + return value == null ? null : value.toByteArray(); + } + /** * @param value * @return @@ -111,6 +124,10 @@ private String nullSafeToStringUtf8(ByteString value) { return value == null ? null : value.toStringUtf8(); } + private ByteString nullSafeToByteString(String value) { + return value == null ? null : ByteString.copyFromUtf8(value); + } + /* * (non-Javadoc) * @@ -118,8 +135,79 @@ private String nullSafeToStringUtf8(ByteString value) { * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ - public RiakObject store(RiakObject object, StoreMeta storeMeta) throws IOException { - return null; + public RiakObject[] store(RiakObject riakObject, StoreMeta storeMeta) throws IOException { + if (riakObject == null || riakObject.getKey() == null || riakObject.getBucket() == null) { + throw new IllegalArgumentException( + "object cannot be null, object's key cannot be null, object's bucket cannot be null"); + } + + return convert(client.store(convert(riakObject), convert(storeMeta, riakObject)), riakObject.getBucket()); + } + + /** + * Convert a {@link StoreMeta} to a pbc {@link RequestMeta} + * + * @param storeMeta + * a {@link StoreMeta} for the store operation. + * @return a {@link RequestMeta} populated from the storeMeta's values. + */ + private RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { + RequestMeta requestMeta = new RequestMeta(); + if (storeMeta.hasW()) { + requestMeta.w(storeMeta.getW()); + } + if (storeMeta.hasDW()) { + requestMeta.dw(storeMeta.getDw()); + } + if (storeMeta.hasReturnBody()) { + requestMeta.returnBody(storeMeta.getReturnBody()); + } + String contentType = riakObject.getContentType(); + if (contentType != null) { + requestMeta.contentType(contentType); + } + return requestMeta; + } + + /** + * Convert a {@link RiakObject} to a pbc + * {@link com.basho.riak.pbc.RiakObject} + * + * @param riakObject + * the RiakObject to convert + * @return a {@link com.basho.riak.pbc.RiakObject} populated from riakObject + */ + private com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { + VClock vc = riakObject.getVClock(); + ByteString bucketName = nullSafeToByteString(riakObject.getBucketName()); + ByteString key = nullSafeToByteString(riakObject.getKey()); + ByteString content = nullSafeToByteString(riakObject.getValue()); + + ByteString vclock = null; + if (vc != null) { + vclock = nullSafeFromBytes(vc.getBytes()); + } + + com.basho.riak.pbc.RiakObject result = new com.basho.riak.pbc.RiakObject(vclock, bucketName, key, content); + + for (RiakLink link : riakObject) { + result.addLink(link.getTag(), link.getBucket(), link.getKey()); + } + + for (Entry metaDataItem : riakObject.usermetaKeys()) { + result.addUsermetaItem(metaDataItem.getKey(), metaDataItem.getValue()); + } + + result.setContentType(riakObject.getContentType()); + return result; + } + + /** + * @param bytes + * @return + */ + private ByteString nullSafeFromBytes(byte[] bytes) { + return ByteString.copyFrom(bytes); } /* @@ -224,4 +312,39 @@ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapRedu return null; } + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#generateClientId() + */ + public byte[] generateAndSetClientId() throws IOException { + client.prepareClientID(); + return client.getClientID().getBytes(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#setClientId() + */ + public void setClientId(byte[] clientId) throws IOException { + if (clientId == null || clientId.length != 4) { + throw new IllegalArgumentException("clientId must be 4 bytes.generateClientId() can do this for you"); + } + client.setClientID(ByteString.copyFrom(clientId)); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.raw.RawClient#getClientId() + */ + public byte[] getClientId() throws IOException { + final String clientId = client.getClientID(); + + if(clientId != null) { + return clientId.getBytes(); + } else { + throw new IOException("null clientId returned by client"); + } + } + } diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java index 298e8c078..568054eca 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -26,7 +27,7 @@ /** * @author russell - * + * */ public class DefaultRiakObject implements RiakObject { private final Bucket bucket; @@ -59,17 +60,16 @@ public class DefaultRiakObject implements RiakObject { * @param userMeta */ public DefaultRiakObject(Bucket bucket, String key, VClock vclock, String vtag, final Date lastModified, - String contentType, String value, final Collection links, - final Map userMeta) { + String contentType, String value, final Collection links, final Map userMeta) { if (bucket == null) { throw new IllegalArgumentException("Bucket cannot be null"); } - if(key == null) { + if (key == null) { throw new IllegalArgumentException("Key cannot be null"); } - + this.bucket = bucket; this.key = key; this.vclock = vclock; @@ -310,4 +310,12 @@ public RiakObject removeUsermeta(String key) { return this; } + /** + * return an unmodifiable view of the user meta entries. Attempts to modify + * will throw UnsupportedOperationException. + */ + public Iterable> usermetaKeys() { + return Collections.unmodifiableCollection(userMeta.entrySet()); + } + } diff --git a/src/main/java/com/basho/riak/newapi/RiakClient.java b/src/main/java/com/basho/riak/newapi/RiakClient.java index 6573e2cf4..866d04d41 100644 --- a/src/main/java/com/basho/riak/newapi/RiakClient.java +++ b/src/main/java/com/basho/riak/newapi/RiakClient.java @@ -24,6 +24,12 @@ * */ public interface RiakClient { + + RiakClient setClientId(byte[] clientId) throws RiakException; + + byte[] generateAndSetClientId() throws RiakException; + + byte[] getClientId() throws RiakException; FetchBucket fetchBucket(String bucketName); diff --git a/src/main/java/com/basho/riak/newapi/RiakException.java b/src/main/java/com/basho/riak/newapi/RiakException.java index f15a59c58..6e8cf80e8 100644 --- a/src/main/java/com/basho/riak/newapi/RiakException.java +++ b/src/main/java/com/basho/riak/newapi/RiakException.java @@ -29,4 +29,8 @@ public RiakException(Exception e) { public RiakException() { super(); } + + public RiakException(String message) { + super(message); + } } diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java index e78b69a16..9ba1a3914 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -15,6 +15,8 @@ import java.io.IOException; +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.pbc.PBClient; import com.basho.riak.newapi.bucket.Bucket; @@ -29,7 +31,7 @@ */ public class RiakFactory { - public static RiakClient defaultClient() throws RiakException { + public static RiakClient pbcClient() throws RiakException { try { final RawClient client = new PBClient("127.0.0.1", 8087); @@ -57,6 +59,41 @@ public WriteBucket createBucket(String bucketName) { WriteBucket op = new WriteBucket(client, bucketName); return op; } + + public RiakClient setClientId(final byte[] clientId) throws RiakException { + if (clientId == null || clientId.length != 4) { + throw new IllegalArgumentException("Client Id must be 4 bytes long"); + } + final byte[] cloned = clientId.clone(); + new DefaultRetrier().attempt(new Command() { + public Boolean execute() throws IOException { + client.setClientId(cloned); + return true; + } + }, 3); + + return this; + } + + public byte[] generateAndSetClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.generateAndSetClientId(); + } + }, 3); + + return clientId; + } + + public byte[] getClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.getClientId(); + } + }, 3); + + return clientId; + } }; } catch (IOException e) { throw new RiakException(e); diff --git a/src/main/java/com/basho/riak/newapi/RiakLink.java b/src/main/java/com/basho/riak/newapi/RiakLink.java index 497f1f0d5..50d8d0116 100644 --- a/src/main/java/com/basho/riak/newapi/RiakLink.java +++ b/src/main/java/com/basho/riak/newapi/RiakLink.java @@ -15,8 +15,14 @@ /** * @author russell - * + * */ public interface RiakLink { + String getTag(); + + String getBucket(); + + String getKey(); + } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java index f3c84a146..87ef032f6 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -16,6 +16,7 @@ import java.util.Collection; import java.util.Date; import java.util.Map; +import java.util.Map.Entry; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.VClock; @@ -57,6 +58,8 @@ public interface RiakObject extends Iterable { boolean hasUsermeta(String key); String getUsermeta(String key); + + Iterable> usermetaKeys(); // Mutate diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 2dc0e1995..2efddf198 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -227,7 +227,12 @@ public StoreObject store(final String key, final String value) { return new StoreObject(client, b, key).withMutator(new Mutation() { public RiakObject apply(RiakObject original) { - return original.setValue(value); + if(original == null) { + return RiakObjectBuilder.newBuilder(b, key).withValue(value).build(); + } else { + System.out.println(Thread.currentThread().getName() + " mutating existing value " + original.getValue() + " to " + value); + return original.setValue(value); + } } }).withResolver(new ConflictResolver() { @@ -237,7 +242,7 @@ public RiakObject resolve(Collection siblings) throws UnresolvedConf } else if (siblings.size() == 1) { return siblings.iterator().next(); } else { - return RiakObjectBuilder.newBuilder(b, key).build(); + return null; } } }).withConverter(new Converter() { diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java index 2317bb2f3..73102c274 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java @@ -242,7 +242,7 @@ public static final class Builder { public Integer bigVClock; public Integer smallVClock; public String backend; - public int nVal; + public int nVal = 3; public Boolean lastWriteWins; public Boolean allowSiblings; diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java index aa09eca16..94c76b785 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -63,8 +63,8 @@ public RiakObjectBuilder withValue(String value) { return this; } - public RiakObjectBuilder withVClock(String value) { - this.vclock = new BasicVClock(value); + public RiakObjectBuilder withVClock(byte[] vclock) { + this.vclock = new BasicVClock(vclock); return this; } diff --git a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java index 20c806394..83ef57c52 100644 --- a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java @@ -19,13 +19,16 @@ */ public class BasicVClock implements VClock { - private final String value; + private final byte[] value; - public BasicVClock(final String value) { + public BasicVClock(final byte[] value) { if (value == null) { throw new IllegalArgumentException("VClock value cannot be null"); } - this.value = value; + this.value = value.clone(); } + public byte[] getBytes() { + return value.clone(); + } } diff --git a/src/main/java/com/basho/riak/newapi/cap/VClock.java b/src/main/java/com/basho/riak/newapi/cap/VClock.java index 9468e5823..6a2f0a684 100644 --- a/src/main/java/com/basho/riak/newapi/cap/VClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/VClock.java @@ -13,10 +13,15 @@ */ package com.basho.riak.newapi.cap; + /** * @author russell - * + * */ public interface VClock { + /** + * @return + */ + byte[] getBytes(); } diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index 878a77733..ab458d85d 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -42,7 +42,7 @@ public class StoreObject implements RiakOperation { private Integer w; private Integer dw; private boolean returnBody = false; - + private int retries = 0; private Mutation mutation; private ConflictResolver resolver; @@ -83,19 +83,27 @@ public RiakObject[] execute() throws IOException { for (RiakObject o : ros) { siblings.add(converter.toDomain(o)); } + + System.out.println("Siblings length is " + siblings.size()); final T resolved = resolver.resolve(siblings); final T mutated = mutation.apply(resolved); final RiakObject o = converter.fromDomain(mutated); - final RiakObject stored = new DefaultRetrier().attempt(new Command() { - public RiakObject execute() throws IOException { + final RiakObject[] stored = new DefaultRetrier().attempt(new Command() { + public RiakObject[] execute() throws IOException { return client.store(o, generateStoreMeta()); } }, retries); - return converter.toDomain(stored); + final Collection storedSiblings = new ArrayList(ros.length); + + for (RiakObject s : stored) { + siblings.add(converter.toDomain(s)); + } + + return resolver.resolve(storedSiblings); } /** @@ -134,7 +142,7 @@ public StoreObject withResolver(ConflictResolver resolver) { this.resolver = resolver; return this; } - + public StoreObject withConverter(Converter converter) { this.converter = converter; return this; @@ -143,7 +151,8 @@ public StoreObject withConverter(Converter converter) { /** * default clobber mutator. Beware. * - * @param value new value + * @param value + * new value * @return this StoreObject */ public StoreObject withValue(final T value) { diff --git a/src/test/java/com/basho/riak/client/BasicOperations.java b/src/test/java/com/basho/riak/client/BasicOperations.java index 3d83a61c7..9a8dcaea4 100644 --- a/src/test/java/com/basho/riak/client/BasicOperations.java +++ b/src/test/java/com/basho/riak/client/BasicOperations.java @@ -22,7 +22,6 @@ import org.junit.Test; -import com.basho.riak.client.raw.pbc.PBClient; import com.basho.riak.newapi.RiakClient; import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.RiakObject; @@ -43,7 +42,7 @@ public class BasicOperations { @Test public void basicOpertaions() throws Exception { - final RiakClient c = RiakFactory.defaultClient(); + final RiakClient c = RiakFactory.pbcClient(); c.createBucket("testBucket").retry(2).nVal(3).execute(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java b/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java deleted file mode 100644 index 011785cd2..000000000 --- a/src/test/java/com/basho/riak/client/itest/ITestBucketOperations.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is provided 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.basho.riak.client.itest; - -import static org.junit.Assert.*; - -import java.util.UUID; - -import org.junit.Test; - -import com.basho.riak.newapi.RiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.bucket.Bucket; - -/** - * @author russell - * - */ -public class ITestBucketOperations { - - @Test public void fetchBucket() throws RiakException { - final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.defaultClient(); - - Bucket b = c.fetchBucket(bucketName).execute(); - - assertNotNull(b); - assertEquals(bucketName, b.getName()); - assertEquals(new Integer(3), b.getNVal()); - assertFalse(b.getAllowSiblings()); - } - - @Test public void updateBucket() throws RiakException { - final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.defaultClient(); - - Bucket b = c.fetchBucket(bucketName).execute(); - - assertNotNull(b); - assertEquals(bucketName, b.getName()); - assertEquals(new Integer(3), b.getNVal()); - assertFalse(b.getAllowSiblings()); - - b = c.updateBucket(b).nVal(4).allowSiblings(true).execute(); - - assertNotNull(b); - assertEquals(bucketName, b.getName()); - assertEquals(new Integer(4), b.getNVal()); - assertTrue(b.getAllowSiblings()); - } - - - @Test public void createBucket() throws RiakException { - final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.defaultClient(); - - Bucket b = c.createBucket(bucketName).nVal(1).allowSiblings(true).execute(); - - assertNotNull(b); - assertEquals(bucketName, b.getName()); - assertEquals(new Integer(1), b.getNVal()); - assertTrue(b.getAllowSiblings()); - } - -} From 52c244b95cb2cc1977f6752086225156584eb0aa Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 1 Apr 2011 18:12:16 +0100 Subject: [PATCH 004/764] Start driving out API from itests. --- .../basho/riak/client/itest/ITestBucket.java | 116 ++++++++++++++++++ .../basho/riak/client/itest/ITestClient.java | 87 +++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 src/test/java/com/basho/riak/client/itest/ITestBucket.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestClient.java diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java new file mode 100644 index 000000000..0ab1baf88 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -0,0 +1,116 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import java.util.UUID; +import java.util.concurrent.CountDownLatch; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.UnresolvedConflictException; + +/** + * @author russell + * + */ +public class ITestBucket { + + @Test public void basicStore() throws Exception { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.pbcClient(); + + Bucket b = c.fetchBucket(bucketName).execute(); + RiakObject o = b.store("k", "v").execute(); + assertNull(o); + } + + @Test public void siblings() throws Exception { + final CountDownLatch cdl = new CountDownLatch(1); + final String bucketName = UUID.randomUUID().toString(); + + RiakFactory.pbcClient().createBucket(bucketName).allowSiblings(true).execute(); + + final int numThreads = 2; + final Thread[] threads = new Thread[numThreads]; + + CountDownLatch el = new CountDownLatch(numThreads); + + for (int i = 0; i < numThreads; i++) { + RiakClient c = RiakFactory.pbcClient(); + c.generateAndSetClientId(); + threads[i] = new Thread(new Storer(cdl, el, c.fetchBucket(bucketName).execute(), "k", "v")); + threads[i].start(); + } + + cdl.countDown(); + + el.await(); + System.out.println(bucketName); + } + + private static final class Storer implements Runnable { + private final CountDownLatch startLatch; + private final CountDownLatch endLatch; + private final Bucket bucket; + private final String key; + private final String value; + + /** + * @param startLatch + * @param bucket + * @param key + * @param value + */ + private Storer(CountDownLatch startLatch, CountDownLatch endLatch, Bucket bucket, String key, String value) { + this.startLatch = startLatch; + this.endLatch = endLatch; + this.bucket = bucket; + this.key = key; + this.value = value; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + public void run() { + try { + startLatch.await(); + for (int i = 0; i < 5; i++) { + System.out.println(Thread.currentThread().getName() + " doing run " + i); + bucket.store(key, Thread.currentThread().getName() + value + i).execute(); + Thread.sleep(10); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (RiakException e) { + System.out.println(Thread.currentThread().getName() + " just barfed"); + throw new RuntimeException(e); + } finally { + endLatch.countDown(); + } + } + + } + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestClient.java b/src/test/java/com/basho/riak/client/itest/ITestClient.java new file mode 100644 index 000000000..33f2f25ed --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestClient.java @@ -0,0 +1,87 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.*; + +import java.util.UUID; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.bucket.Bucket; + +/** + * @author russell + * + */ +public class ITestClient { + + @Test public void fetchBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.pbcClient(); + + Bucket b = c.fetchBucket(bucketName).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(3), b.getNVal()); + assertFalse(b.getAllowSiblings()); + } + + @Test public void updateBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.pbcClient(); + + Bucket b = c.fetchBucket(bucketName).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(3), b.getNVal()); + assertFalse(b.getAllowSiblings()); + + b = c.updateBucket(b).nVal(4).allowSiblings(true).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(4), b.getNVal()); + assertTrue(b.getAllowSiblings()); + } + + + @Test public void createBucket() throws RiakException { + final String bucketName = UUID.randomUUID().toString(); + RiakClient c = RiakFactory.pbcClient(); + + Bucket b = c.createBucket(bucketName).nVal(1).allowSiblings(true).execute(); + + assertNotNull(b); + assertEquals(bucketName, b.getName()); + assertEquals(new Integer(1), b.getNVal()); + assertTrue(b.getAllowSiblings()); + } + + @Test public void clientIds() throws Exception { + final byte[] clientId = "abcd".getBytes("UTF-8"); + RiakClient c = RiakFactory.pbcClient(); + c.setClientId(clientId.clone()); + assertArrayEquals(clientId, c.getClientId()); + + byte[] newId = c.generateAndSetClientId(); + + assertArrayEquals(newId, c.getClientId()); + } +} From 3619eb6e88c5132825cf90587474fbb07fb9a575 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 14 Apr 2011 17:27:40 +0100 Subject: [PATCH 005/764] First cut of a higher level riak client API Create a fluid API that addresses the realities of working with an eventually consistent, dynamo style db. Include mutation, conflict resolution and simple type converstion. There is a lot to do. --- pom.xml | 41 ++ .../com/basho/riak/client/raw/RawClient.java | 8 +- .../com/basho/riak/client/raw/Retrier.java | 1 - .../client/raw/http/HTTPClientAdapter.java | 525 ++++++++++++++++++ .../basho/riak/client/raw/http/KeySource.java | 117 ++++ .../{PBClient.java => PBClientAdapter.java} | 91 ++- .../com/basho/riak/newapi/DefaultClient.java | 88 +++ .../basho/riak/newapi/DefaultRiakLink.java | 129 +++++ .../basho/riak/newapi/DefaultRiakObject.java | 22 +- .../com/basho/riak/newapi/RiakException.java | 7 +- .../com/basho/riak/newapi/RiakFactory.java | 87 +-- .../com/basho/riak/newapi/RiakObject.java | 8 +- .../com/basho/riak/newapi/bucket/Bucket.java | 12 +- .../riak/newapi/bucket/DefaultBucket.java | 132 ++++- .../riak/newapi/bucket/DomainBucket.java | 106 ++++ .../basho/riak/newapi/bucket/WriteBucket.java | 6 +- .../newapi/builders/DomainBucketBuilder.java | 135 +++++ .../basho/riak/newapi/cap/BasicVClock.java | 4 + .../com/basho/riak/newapi/cap/ClientId.java | 36 ++ .../riak/newapi/cap/ClobberMutation.java | 42 ++ .../riak/newapi/cap/DefaultResolver.java | 23 + .../com/basho/riak/newapi/cap/Mutation.java | 9 +- .../riak/newapi/cap/MutationProducer.java | 24 + .../cap/UnresolvedConflictException.java | 8 +- .../com/basho/riak/newapi/cap/VClock.java | 5 + .../newapi/convert/ConversionException.java | 50 ++ .../riak/newapi/convert/ConversionUtil.java | 56 ++ .../basho/riak/newapi/convert/Converter.java | 4 +- .../riak/newapi/convert/JSONConverter.java | 106 ++++ .../convert/NoKeySpecifedException.java | 38 ++ .../basho/riak/newapi/convert/RiakKey.java | 31 ++ .../riak/newapi/operations/DeleteObject.java | 37 +- .../riak/newapi/operations/FetchObject.java | 62 ++- .../riak/newapi/operations/StoreObject.java | 46 +- .../newapi/query/NamedErlangFunction.java | 49 ++ .../basho/riak/client/itest/ITestBucket.java | 229 ++++++-- ...ITestClient.java => ITestClientBasic.java} | 44 +- .../riak/client/itest/ITestDomainBucket.java | 102 ++++ .../riak/client/itest/ITestHTTPBucket.java | 34 ++ .../riak/client/itest/ITestHTTPClient.java | 87 +++ .../riak/client/itest/ITestPBBucket.java | 35 ++ .../riak/client/itest/ITestPBClient.java | 33 ++ .../riak/client/raw/http/TestKeySource.java | 61 ++ .../riak/newapi/cap/ClobberMutationTest.java | 46 ++ .../newapi/convert/ConversionUtilTest.java | 68 +++ .../com/megacorp/commerce/LegacyCart.java | 106 ++++ .../com/megacorp/commerce/MergeResolver.java | 33 ++ .../com/megacorp/commerce/ShoppingCart.java | 145 +++++ 48 files changed, 2919 insertions(+), 249 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java create mode 100644 src/main/java/com/basho/riak/client/raw/http/KeySource.java rename src/main/java/com/basho/riak/client/raw/pbc/{PBClient.java => PBClientAdapter.java} (78%) create mode 100644 src/main/java/com/basho/riak/newapi/DefaultClient.java create mode 100644 src/main/java/com/basho/riak/newapi/DefaultRiakLink.java create mode 100644 src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java create mode 100644 src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java create mode 100644 src/main/java/com/basho/riak/newapi/cap/ClientId.java create mode 100644 src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java create mode 100644 src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java create mode 100644 src/main/java/com/basho/riak/newapi/cap/MutationProducer.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/ConversionException.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/JSONConverter.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/RiakKey.java rename src/test/java/com/basho/riak/client/itest/{ITestClient.java => ITestClientBasic.java} (66%) create mode 100644 src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestPBBucket.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestPBClient.java create mode 100644 src/test/java/com/basho/riak/client/raw/http/TestKeySource.java create mode 100644 src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java create mode 100644 src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java create mode 100644 src/test/java/com/megacorp/commerce/LegacyCart.java create mode 100644 src/test/java/com/megacorp/commerce/MergeResolver.java create mode 100644 src/test/java/com/megacorp/commerce/ShoppingCart.java diff --git a/pom.xml b/pom.xml index dc968afcb..3c06d6192 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,23 @@ riak-client 0.14.2-SNAPSHOT + + org.codehaus.jackson + jackson-core-asl + 1.7.5 + + + org.codehaus.jackson + jackson-mapper-asl + 1.7.5 + + + + org.mockito + mockito-all + 1.8.0 + test + junit junit @@ -28,6 +45,30 @@ + + + itest + + + + + org.codehaus.mojo + failsafe-maven-plugin + 2.4.3-alpha-1 + + + + integration-test + verify + + + + + + + + + diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index 41f9b8ef9..a4016d834 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -34,12 +34,16 @@ public interface RawClient { // RiakObject RiakObject[] fetch(Bucket bucket, String key) throws IOException; + + RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException; RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOException; void store(RiakObject object) throws IOException; - void delete(RiakObject object) throws IOException; + void delete(Bucket bucket, String key) throws IOException; + + void delete(Bucket bucket, String key, int deleteQuorum) throws IOException; // Bucket Iterator listBuckets() throws IOException; @@ -48,7 +52,7 @@ public interface RawClient { void updateBucket(String name, BucketProperties bucketProperties) throws IOException; - Iterator fetchBucketKeys(String bucketName) throws IOException; + Iterable listKeys(String bucketName) throws IOException; // Query WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException; diff --git a/src/main/java/com/basho/riak/client/raw/Retrier.java b/src/main/java/com/basho/riak/client/raw/Retrier.java index 59a25a7d2..d2b9418ad 100644 --- a/src/main/java/com/basho/riak/client/raw/Retrier.java +++ b/src/main/java/com/basho/riak/client/raw/Retrier.java @@ -20,6 +20,5 @@ * */ public interface Retrier { - T attempt(Command command, int times) throws RiakRetryFailedException; } diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java new file mode 100644 index 000000000..b46f3c5d3 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -0,0 +1,525 @@ +/* + * This file is provided 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.basho.riak.client.raw.http; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.httpclient.util.DateUtil; + +import com.basho.riak.client.RiakBucketInfo; +import com.basho.riak.client.RiakClient; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.client.request.RequestMeta; +import com.basho.riak.client.response.BucketResponse; +import com.basho.riak.client.response.FetchResponse; +import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.response.StoreResponse; +import com.basho.riak.client.response.WithBodyResponse; +import com.basho.riak.client.util.Constants; +import com.basho.riak.newapi.DefaultRiakLink; +import com.basho.riak.newapi.RiakLink; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.bucket.DefaultBucketProperties; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.ClientId; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.MapReduceSpec; +import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.WalkResult; + +/** + * @author russell + * + */ +public class HTTPClientAdapter implements RawClient { + + private final RiakClient client; + + /** + * @param client + */ + public HTTPClientAdapter(RiakClient client) { + this.client = client; + } + + /** + * @param string + * @param i + */ + public HTTPClientAdapter(String url) { + this(new RiakClient(url)); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket + * .Bucket, java.lang.String) + */ + public RiakObject[] fetch(Bucket bucket, String key) throws IOException { + if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + throw new IllegalArgumentException( + "bucket must not be null and bucket.getName() must not be null or empty " + + "or just whitespace."); + } + + if (key == null || key.trim().equals("")) { + throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); + } + + FetchResponse resp = client.fetch(bucket.getName(), key); + + return handleBodyResponse(bucket, resp); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket + * .Bucket, java.lang.String, int) + */ + public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException { + if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + throw new IllegalArgumentException( + "bucket must not be null and bucket.getName() must not be null or empty " + + "or just whitespace."); + } + + if (key == null || key.trim().equals("")) { + throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); + } + + FetchResponse resp = client.fetch(bucket.getName(), key, RequestMeta.readParams(readQuorum)); + + return handleBodyResponse(bucket, resp); + } + + /** + * @param bucket + * @param resp + * @return + */ + private RiakObject[] handleBodyResponse(Bucket bucket, WithBodyResponse resp) { + if (resp.hasSiblings()) { + return convert(resp.getSiblings(), bucket); + } else if (resp.hasObject()) { + return new RiakObject[] { convert(resp.getObject(), bucket) }; + } else { + return new RiakObject[] {}; + } + } + + /** + * @param siblings + * @param bucket + * @return + */ + private RiakObject[] convert(Collection siblings, Bucket bucket) { + final Collection results = new ArrayList(); + + for (com.basho.riak.client.RiakObject object : siblings) { + results.add(convert(object, bucket)); + } + + return results.toArray(new RiakObject[results.size()]); + } + + /** + * @param object + * @return + */ + private RiakObject convert(final com.basho.riak.client.RiakObject o, final Bucket bucket) { + + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + + builder.withValue(o.getValue()); + builder.withVClock(nullSafeGetBytes(o.getVclock())); + builder.withVtag(o.getVtag()); + + String lastModified = o.getLastmod(); + + if (lastModified != null) { + Date lastModDate = o.getLastmodAsDate(); + builder.withLastModified(lastModDate.getTime()); + } + + final Collection links = new ArrayList(); + + for (com.basho.riak.client.RiakLink link : o.iterableLinks()) { + links.add(convert(link)); + } + + builder.withLinks(links); + builder.withContentType(o.getContentType()); + + final Map userMetaData = new HashMap(); + + for (String key : o.usermetaKeys()) { + userMetaData.put(key, o.getUsermetaItem(key)); + } + + builder.withUsermeta(userMetaData); + + return builder.build(); + } + + /** + * @param link + * @return + */ + private RiakLink convert(com.basho.riak.client.RiakLink link) { + return new DefaultRiakLink(link.getBucket(), link.getKey(), link.getTag()); + } + + /** + * @param vclock + * @return + */ + private byte[] nullSafeGetBytes(String vclock) { + return vclock == null ? null : vclock.getBytes(); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject + * , com.basho.riak.client.raw.StoreMeta) + */ + public RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOException { + if(object == null || object.getBucket() == null) { + throw new IllegalArgumentException("cannot store a null RiakObject, or a RiakObject without a bucket"); + } + final Bucket bucket = object.getBucket(); + + RiakObject[] result = new RiakObject[] {}; + + com.basho.riak.client.RiakObject riakObject = convert(object); + RequestMeta requestMeta = convert(storeMeta); + StoreResponse resp = client.store(riakObject, requestMeta); + + if(resp.isSuccess()) { + riakObject.updateMeta(resp); + } else { + throw new IOException(resp.getBodyAsString()); + } + + if(storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { + result = handleBodyResponse(bucket, resp); + } + + return result; + } + + /** + * @param storeMeta + * @return + */ + private RequestMeta convert(StoreMeta storeMeta) { + RequestMeta requestMeta = RequestMeta.writeParams(storeMeta.getW(), storeMeta.getDw()); + + if(storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { + requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(true)); + } else { + requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(false)); + } + + return requestMeta; + } + + /** + * @param object + * @return + */ + private com.basho.riak.client.RiakObject convert(RiakObject object) { + + com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( + client, + object.getBucketName(), + object.getKey(), + nullSafeGetBytes(object.getValue()), + object.getContentType(), + getLinks(object), + getUserMetaData(object), + object.getVClockAsString(), + formatDate(object.getLastModified()), + object.getVtag()); + return riakObject; + } + + /** + * @param lastModified + * @return + */ + private String formatDate(Date lastModified) { + if(lastModified == null) { + return null; + } + return DateUtil.formatDate(lastModified); + } + + /** + * @param object + * @return + */ + private Map getUserMetaData(RiakObject object) { + final Map userMetaData = new HashMap(); + + for (Entry entry : object.userMetaEntries()) { + userMetaData.put(entry.getKey(), entry.getValue()); + } + return userMetaData; + } + + /** + * @param object + * @return + */ + private List getLinks(RiakObject object) { + + final List links = new ArrayList(); + + for (RiakLink link : object) { + links.add(convert(link)); + } + + return links; + } + + /** + * @param link + * @return + */ + private com.basho.riak.client.RiakLink convert(RiakLink link) { + return new com.basho.riak.client.RiakLink(link.getBucket(), link.getKey(), link.getTag()); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject + * ) + */ + public void store(RiakObject object) throws IOException { + store(object, new StoreMeta(null, null, false)); + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket + * .Bucket, java.lang.String) + */ + public void delete(Bucket bucket, String key) throws IOException { + HttpResponse resp = client.delete(bucket.getName(), key); + if(!resp.isSuccess()) { + throw new IOException(resp.getBodyAsString()); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket + * .Bucket, java.lang.String, int) + */ + public void delete(Bucket bucket, String key, int deleteQuorum) throws IOException { + HttpResponse resp = client.delete(bucket.getName(), key, RequestMeta.deleteParams(deleteQuorum)); + if(!resp.isSuccess()) { + throw new IOException(resp.getBodyAsString()); + } + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#listBuckets() + */ + public Iterator listBuckets() throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#fetchBucket(java.lang.String) + */ + public BucketProperties fetchBucket(String bucketName) throws IOException { + if (bucketName == null || bucketName.trim().equals("")) { + throw new IllegalArgumentException("bucketName cannot be null, empty or all whitespace"); + } + + BucketResponse response = client.getBucketSchema(bucketName, null); + + return convert(response); + } + + /** + * @param response + * @return + */ + private BucketProperties convert(BucketResponse response) { + RiakBucketInfo bucketInfo = response.getBucketInfo(); + return new DefaultBucketProperties.Builder().allowSiblings(bucketInfo.getAllowMult()).nVal(bucketInfo.getNVal()).chashKeyFunction(convert(bucketInfo.getCHashFun())).linkWalkFunction(convert(bucketInfo.getLinkFun())).build(); + } + + /** + * @param cHashFun + * @return + */ + private NamedErlangFunction convert(String funString) { + if (funString == null) { + return null; + } + String[] fun = funString.split(":"); + + if (fun.length != 2) { + return null; + } + + return new NamedErlangFunction(fun[0], fun[1]); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#updateBucket(java.lang.String, + * com.basho.riak.newapi.bucket.BucketProperties) + */ + public void updateBucket(String name, BucketProperties bucketProperties) throws IOException { + HttpResponse response = client.setBucketSchema(name, convert(bucketProperties)); + if (!response.isSuccess()) { + throw new IOException(response.getBodyAsString()); + } + + } + + /** + * @param bucketProperties + * @return + */ + private RiakBucketInfo convert(BucketProperties bucketProperties) { + RiakBucketInfo rbi = new RiakBucketInfo(); + + if (bucketProperties.getAllowSiblings() != null) { + rbi.setAllowMult(bucketProperties.getAllowSiblings()); + } + + if (bucketProperties.getNVal() != null) { + rbi.setNVal(bucketProperties.getNVal()); + } + + final NamedErlangFunction chashKeyFun = bucketProperties.getChashKeyFunction(); + if (chashKeyFun != null) { + rbi.setCHashFun(chashKeyFun.getMod(), chashKeyFun.getFun()); + } + + final NamedErlangFunction linkwalkFun = bucketProperties.getLinkWalkFunction(); + if (linkwalkFun != null) { + rbi.setLinkFun(linkwalkFun.getMod(), linkwalkFun.getFun()); + } + + return rbi; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#fetchBucketKeys(java.lang.String) + */ + public Iterable listKeys(String bucketName) throws IOException { + final BucketResponse bucketResponse = client.streamBucket(bucketName); + final KeySource keyStream = new KeySource(bucketResponse); + return new Iterable() { + public Iterator iterator() { + return keyStream; + } + }; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.newapi.RiakObject + * , com.basho.riak.client.raw.query.LinkWalkSpec) + */ + public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#mapReduce(com.basho.riak.newapi.query + * .MapReduceSpec) + */ + public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException { + return null; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#generateAndSetClientId() + */ + public byte[] generateAndSetClientId() throws IOException { + byte[] clientId = ClientId.generate(); + + client.setClientId(new String(clientId)); + return client.getClientId(); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#setClientId(byte[]) + */ + public void setClientId(byte[] clientId) throws IOException { + if (clientId == null || clientId.length != 4) { + throw new IllegalArgumentException("clientId must be 4 bytes. generateAndSetClientId() can do this for you"); + } + client.setClientId(new String(clientId)); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#getClientId() + */ + public byte[] getClientId() throws IOException { + return client.getClientId(); + } + +} diff --git a/src/main/java/com/basho/riak/client/raw/http/KeySource.java b/src/main/java/com/basho/riak/client/raw/http/KeySource.java new file mode 100644 index 000000000..5ccecd98c --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/http/KeySource.java @@ -0,0 +1,117 @@ +/* + * This file is provided 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.basho.riak.client.raw.http; + +import java.lang.ref.WeakReference; +import java.util.Iterator; +import java.util.Timer; +import java.util.TimerTask; + +import com.basho.riak.client.response.BucketResponse; + +/** + * Wraps the stream of keys from BucketResponse.getBucketInfo.getKeys + * in an iterator that handles closing the underlying http stream + * when finished with. + * + * @author russell + * + */ +public class KeySource implements Iterator { + + private static final Timer timer = new Timer(); + private final BucketResponse bucketResponse; + private final Iterator keys; + private ReaperTask reaper; + + /** + * @param bucketResponse + */ + public KeySource(BucketResponse bucketResponse) { + this.bucketResponse = bucketResponse; + this.keys = bucketResponse.getBucketInfo().getKeys().iterator(); + this.reaper = new ReaperTask(this, bucketResponse); + } + + /* + * (non-Javadoc) + * + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + + boolean hasNext = keys.hasNext(); + // If there are no more keys, close the underlying HTTP resource + // and cancel the timer + if (!hasNext) { + reaper.cancel(); + bucketResponse.close(); + } + + return hasNext; + } + + /* + * (non-Javadoc) + * + * @see java.util.Iterator#next() + */ + public String next() { + return keys.next(); + } + + /** + * This is a read only stream of keys, calling this results in + * UnsupportedOperationException + * + * @see java.util.Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * The underlying stream is not exposed to the caller (it is an + * implementation detail) This time task ensures that the underlying HTTP + * resource is closed when the iterator is no longer reachable. + * + * @author russell + */ + static class ReaperTask extends TimerTask { + private final BucketResponse bucketResponse; + private WeakReference ref; + + ReaperTask(Object holder, BucketResponse conn) { + this.bucketResponse = conn; + this.ref = new WeakReference(holder); + KeySource.timer.scheduleAtFixedRate(this, 500, 500); + } + + @Override public synchronized void run() { + if (ref == null) { + // NO-OP + } else if (ref.get() == null) { + // the reference was lost; cancel this timer and + // close the connection + cancel(); + bucketResponse.close(); + } + } + + @Override public synchronized boolean cancel() { + ref = null; + return super.cancel(); + } + } +} diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java similarity index 78% rename from src/main/java/com/basho/riak/client/raw/pbc/PBClient.java rename to src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index 51b031a92..225b61e84 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClient.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -34,6 +34,7 @@ import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.MapReduceSpec; import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.pbc.KeySource; import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.RiakClient; import com.google.protobuf.ByteString; @@ -42,7 +43,7 @@ * @author russell * */ -public class PBClient implements RawClient { +public class PBClientAdapter implements RawClient { private final RiakClient client; @@ -50,7 +51,7 @@ public class PBClient implements RawClient { * @param client * @throws IOException */ - public PBClient(String host, int port) throws IOException { + public PBClientAdapter(String host, int port) throws IOException { this.client = new RiakClient(host, port); } @@ -63,7 +64,8 @@ public PBClient(String host, int port) throws IOException { public RiakObject[] fetch(Bucket bucket, String key) throws IOException { if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { throw new IllegalArgumentException( - "bucket must not be null and bucket.getName() must not be null or empty or just whitespace."); + "bucket must not be null and bucket.getName() must not be null or empty " + + "or just whitespace."); } if (key == null || key.trim().equals("")) { @@ -72,6 +74,26 @@ public RiakObject[] fetch(Bucket bucket, String key) throws IOException { return convert(client.fetch(bucket.getName(), key), bucket); } + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket + * .Bucket, java.lang.String, int) + */ + public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException { + if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + throw new IllegalArgumentException( + "bucket must not be null and bucket.getName() must not be null or empty " + + "or just whitespace."); + } + + if (key == null || key.trim().equals("")) { + throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); + } + return convert(client.fetch(bucket.getName(), key, readQuorum), bucket); + } + /** * @param fetch * @return @@ -194,7 +216,7 @@ private com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { result.addLink(link.getTag(), link.getBucket(), link.getKey()); } - for (Entry metaDataItem : riakObject.usermetaKeys()) { + for (Entry metaDataItem : riakObject.userMetaEntries()) { result.addUsermetaItem(metaDataItem.getKey(), metaDataItem.getValue()); } @@ -217,16 +239,27 @@ private ByteString nullSafeFromBytes(byte[] bytes) { * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject * ) */ - public void store(RiakObject object) throws IOException {} + public void store(RiakObject object) throws IOException { + store(object, new StoreMeta(null, null, false)); + } /* * (non-Javadoc) * - * @see - * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.client.RiakObject - * ) + * @see com.basho.riak.client.raw.RawClient#delete(java.lang.String) */ - public void delete(RiakObject object) throws IOException {} + public void delete(Bucket bucket, String key) throws IOException { + client.delete(bucket.getName(), key); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.raw.RawClient#delete(java.lang.String, int) + */ + public void delete(Bucket bucket, String key, int deleteQuorum) throws IOException { + client.delete(bucket.getName(), key, deleteQuorum); + } /* * (non-Javadoc) @@ -286,8 +319,34 @@ private com.basho.riak.pbc.BucketProperties convert(BucketProperties p) { * @see * com.basho.riak.client.raw.RawClient#fetchBucketKeys(java.lang.String) */ - public Iterator fetchBucketKeys(String bucketName) throws IOException { - return null; + public Iterable listKeys(String bucketName) throws IOException { + if (bucketName == null || bucketName.trim().equals("")) { + throw new IllegalArgumentException("bucketName cannot be null, empty or all whitespace"); + } + + final KeySource keySource = client.listKeys(ByteString.copyFromUtf8(bucketName)); + final Iterator i = new Iterator() { + + private final Iterator delegate = keySource.iterator(); + + public boolean hasNext() { + return delegate.hasNext(); + } + + public String next() { + return nullSafeToStringUtf8(delegate.next()); + } + + public void remove() { + delegate.remove(); + } + }; + + return new Iterable() { + public Iterator iterator() { + return i; + } + }; } /* @@ -329,18 +388,20 @@ public byte[] generateAndSetClientId() throws IOException { */ public void setClientId(byte[] clientId) throws IOException { if (clientId == null || clientId.length != 4) { - throw new IllegalArgumentException("clientId must be 4 bytes.generateClientId() can do this for you"); + throw new IllegalArgumentException("clientId must be 4 bytes. generateAndSetClientId() can do this for you"); } client.setClientID(ByteString.copyFrom(clientId)); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.basho.riak.client.raw.RawClient#getClientId() */ public byte[] getClientId() throws IOException { final String clientId = client.getClientID(); - - if(clientId != null) { + + if (clientId != null) { return clientId.getBytes(); } else { throw new IOException("null clientId returned by client"); diff --git a/src/main/java/com/basho/riak/newapi/DefaultClient.java b/src/main/java/com/basho/riak/newapi/DefaultClient.java new file mode 100644 index 000000000..bc2c4bb48 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/DefaultClient.java @@ -0,0 +1,88 @@ +package com.basho.riak.newapi; + +import java.io.IOException; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.FetchBucket; +import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.query.LinkWalk; +import com.basho.riak.newapi.query.MapReduce; + +/** + * @author russell + * + */ +public final class DefaultClient implements RiakClient { + /** + * + */ + private final RawClient client; + + /** + * @param client + */ + DefaultClient(RawClient client) { + this.client = client; + } + + public LinkWalk walk(RiakObject startObject) { + return null; + } + + public WriteBucket updateBucket(Bucket b) { + WriteBucket op = new WriteBucket(client, b); + return op; + } + + public MapReduce mapReduce() { + return null; + } + + public FetchBucket fetchBucket(String bucketName) { + FetchBucket op = new FetchBucket(client, bucketName); + return op; + } + + public WriteBucket createBucket(String bucketName) { + WriteBucket op = new WriteBucket(client, bucketName); + return op; + } + + public RiakClient setClientId(final byte[] clientId) throws RiakException { + if (clientId == null || clientId.length != 4) { + throw new IllegalArgumentException("Client Id must be 4 bytes long"); + } + final byte[] cloned = clientId.clone(); + new DefaultRetrier().attempt(new Command() { + public Void execute() throws IOException { + client.setClientId(cloned); + return null; + } + }, 3); + + return this; + } + + public byte[] generateAndSetClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.generateAndSetClientId(); + } + }, 3); + + return clientId; + } + + public byte[] getClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.getClientId(); + } + }, 3); + + return clientId; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java b/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java new file mode 100644 index 000000000..96989dfdd --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java @@ -0,0 +1,129 @@ +/* + * This file is provided 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.basho.riak.newapi; + +/** + * Immutable RiakLink impl. + * + * @author russell + * + */ +public class DefaultRiakLink implements RiakLink { + + private final String bucket; + private final String key; + private final String tag; + + /** + * @param tag + * @param bucket + * @param key + */ + public DefaultRiakLink(String bucket, String key, String tag) { + this.tag = tag; + this.bucket = bucket; + this.key = key; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakLink#getBucket() + */ + public String getBucket() { + return bucket; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakLink#getKey() + */ + public String getKey() { + return key; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakLink#getTag() + */ + public String getTag() { + return tag; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bucket == null) ? 0 : bucket.hashCode()); + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((tag == null) ? 0 : tag.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DefaultRiakLink)) { + return false; + } + DefaultRiakLink other = (DefaultRiakLink) obj; + if (bucket == null) { + if (other.bucket != null) { + return false; + } + } else if (!bucket.equals(other.bucket)) { + return false; + } + if (key == null) { + if (other.key != null) { + return false; + } + } else if (!key.equals(other.key)) { + return false; + } + if (tag == null) { + if (other.tag != null) { + return false; + } + } else if (!tag.equals(other.tag)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override public String toString() { + return String.format("DefaultRiakLink [tag=%s, bucket=%s, key=%s]", tag, bucket, key); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java index 568054eca..aaeab4bb7 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -24,14 +24,18 @@ import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.RiakKey; /** * @author russell * */ public class DefaultRiakObject implements RiakObject { + + public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + private final Bucket bucket; - private final String key; + @RiakKey private final String key; private final VClock vclock; private final String vtag; private final long lastModified; @@ -105,7 +109,7 @@ private Collection copy(Collection links) { private void safeSetContentType(String contentType) { if (contentType == null) { - this.contentType = ""; + this.contentType = DEFAULT_CONTENT_TYPE; } else { this.contentType = contentType; } @@ -314,8 +318,20 @@ public RiakObject removeUsermeta(String key) { * return an unmodifiable view of the user meta entries. Attempts to modify * will throw UnsupportedOperationException. */ - public Iterable> usermetaKeys() { + public Iterable> userMetaEntries() { return Collections.unmodifiableCollection(userMeta.entrySet()); } + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakObject#getVClockAsString() + */ + public String getVClockAsString() { + if (vclock != null) { + return vclock.asString(); + } + return null; + } + } diff --git a/src/main/java/com/basho/riak/newapi/RiakException.java b/src/main/java/com/basho/riak/newapi/RiakException.java index 6e8cf80e8..4755918b8 100644 --- a/src/main/java/com/basho/riak/newapi/RiakException.java +++ b/src/main/java/com/basho/riak/newapi/RiakException.java @@ -19,10 +19,15 @@ */ public class RiakException extends Exception { + /** + * + */ + private static final long serialVersionUID = 7644302774003494842L; + /** * @param e */ - public RiakException(Exception e) { + public RiakException(Throwable e) { super(e); } diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java index 9ba1a3914..ebb1c723e 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -15,15 +15,9 @@ import java.io.IOException; -import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.client.raw.pbc.PBClient; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.FetchBucket; -import com.basho.riak.newapi.bucket.WriteBucket; -import com.basho.riak.newapi.query.LinkWalk; -import com.basho.riak.newapi.query.MapReduce; +import com.basho.riak.client.raw.http.HTTPClientAdapter; +import com.basho.riak.client.raw.pbc.PBClientAdapter; /** * @author russell @@ -31,73 +25,30 @@ */ public class RiakFactory { + private static final String DEFAULT_RIAK_URL = "http://127.0.0.1:8098/riak"; + + /** + * + * @return a default configuration PBC client + * @throws RiakException + */ public static RiakClient pbcClient() throws RiakException { try { - final RawClient client = new PBClient("127.0.0.1", 8087); - - return new RiakClient() { - public LinkWalk walk(RiakObject startObject) { - return null; - } - - public WriteBucket updateBucket(Bucket b) { - WriteBucket op = new WriteBucket(client, b); - return op; - } - - public MapReduce mapReduce() { - return null; - } - - public FetchBucket fetchBucket(String bucketName) { - FetchBucket op = new FetchBucket(client, bucketName); - return op; - } - - public WriteBucket createBucket(String bucketName) { - WriteBucket op = new WriteBucket(client, bucketName); - return op; - } + final RawClient client = new PBClientAdapter("127.0.0.1", 8087); - public RiakClient setClientId(final byte[] clientId) throws RiakException { - if (clientId == null || clientId.length != 4) { - throw new IllegalArgumentException("Client Id must be 4 bytes long"); - } - final byte[] cloned = clientId.clone(); - new DefaultRetrier().attempt(new Command() { - public Boolean execute() throws IOException { - client.setClientId(cloned); - return true; - } - }, 3); - - return this; - } - - public byte[] generateAndSetClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { - return client.generateAndSetClientId(); - } - }, 3); - - return clientId; - } - - public byte[] getClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { - return client.getClientId(); - } - }, 3); - - return clientId; - } - }; + return new DefaultClient(client); } catch (IOException e) { throw new RiakException(e); } } + /** + * @return a default configuration HTTP client + */ + public static RiakClient httpClient() throws RiakException { + final RawClient client = new HTTPClientAdapter(DEFAULT_RIAK_URL); + return new DefaultClient(client); + } + } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java index 87ef032f6..ff0a8713f 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -13,7 +13,6 @@ */ package com.basho.riak.newapi; -import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.Map.Entry; @@ -59,7 +58,7 @@ public interface RiakObject extends Iterable { String getUsermeta(String key); - Iterable> usermetaKeys(); + Iterable> userMetaEntries(); // Mutate @@ -100,4 +99,9 @@ public interface RiakObject extends Iterable { */ RiakObject removeUsermeta(String key); + /** + * @return A String of the VClock + */ + String getVClockAsString(); + } diff --git a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java index f8df458df..be342d3bb 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java @@ -13,8 +13,6 @@ */ package com.basho.riak.newapi.bucket; -import java.util.Iterator; - import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.operations.DeleteObject; @@ -33,12 +31,18 @@ public interface Bucket extends BucketProperties { StoreObject store(String key, String value); StoreObject store(T o); + + StoreObject store(String key, T o); + FetchObject fetch(String key); + FetchObject fetch(String key, Class type); FetchObject fetch(T o); - DeleteObject delete(T o); + DeleteObject delete(T o); + + DeleteObject delete(String key); - Iterator keys() throws RiakException; + Iterable keys() throws RiakException; } diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 2efddf198..c772306b8 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -13,19 +13,21 @@ */ package com.basho.riak.newapi.bucket; +import static com.basho.riak.newapi.convert.ConversionUtil.getKey; + import java.io.IOException; import java.util.Collection; -import java.util.Iterator; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.DefaultResolver; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.cap.UnresolvedConflictException; import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.newapi.convert.JSONConverter; +import com.basho.riak.newapi.convert.NoKeySpecifedException; import com.basho.riak.newapi.operations.DeleteObject; import com.basho.riak.newapi.operations.FetchObject; import com.basho.riak.newapi.operations.StoreObject; @@ -52,6 +54,8 @@ protected DefaultBucket(String name, BucketProperties properties, RawClient clie this.client = client; } + // / BUCKET PROPS + /* * (non-Javadoc) * @@ -205,12 +209,14 @@ public NamedErlangFunction getLinkWalkFunction() { return properties.getLinkWalkFunction(); } + // / BUCKET + /** * Iterate over the keys for this bucket (Expensive, are you sure?) */ - public Iterator keys() throws RiakException { + public Iterable keys() throws RiakException { try { - return client.fetchBucketKeys(name); + return client.listKeys(name); } catch (IOException e) { throw new RiakException(e); } @@ -227,25 +233,13 @@ public StoreObject store(final String key, final String value) { return new StoreObject(client, b, key).withMutator(new Mutation() { public RiakObject apply(RiakObject original) { - if(original == null) { + if (original == null) { return RiakObjectBuilder.newBuilder(b, key).withValue(value).build(); } else { - System.out.println(Thread.currentThread().getName() + " mutating existing value " + original.getValue() + " to " + value); return original.setValue(value); } } - }).withResolver(new ConflictResolver() { - - public RiakObject resolve(Collection siblings) throws UnresolvedConflictException { - if (siblings.size() > 1) { - throw new UnresolvedConflictException("Siblings found", siblings); - } else if (siblings.size() == 1) { - return siblings.iterator().next(); - } else { - return null; - } - } - }).withConverter(new Converter() { + }).withResolver(new DefaultResolver()).withConverter(new Converter() { public RiakObject toDomain(RiakObject riakObject) { return riakObject; @@ -262,18 +256,39 @@ public RiakObject fromDomain(RiakObject domainObject) { * * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.Object) */ - public StoreObject store(T o) { - return null; + public StoreObject store(final T o) { + final Bucket b = this; + @SuppressWarnings("unchecked") Class clazz = (Class) o.getClass(); + final String key = getKey(o); + if(key == null) { + throw new NoKeySpecifedException(o); + } + return new StoreObject(client, b, key) + .withConverter(new JSONConverter(clazz, b)) + .withMutator(new Mutation() { + public T apply(T original) { + return o; + }; + }).withResolver(new DefaultResolver()); } - + /* * (non-Javadoc) * - * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String, - * java.lang.Class) + * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.String, + * java.lang.Object) */ - public FetchObject fetch(String key, Class type) { - return null; + public StoreObject store(final String key, final T o) { + final Bucket b = this; + @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); + + return new StoreObject(client, b, key) + .withConverter(new JSONConverter(clazz, b, key)) + .withMutator(new Mutation() { + public T apply(T original) { + return o; + }; + }).withResolver(new DefaultResolver()); } /* @@ -282,7 +297,50 @@ public FetchObject fetch(String key, Class type) { * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.Object) */ public FetchObject fetch(T o) { - return null; + final Bucket b = this; + @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); + final String key = getKey(o); + if(key == null) { + throw new NoKeySpecifedException(o); + } + return new FetchObject(client, this, key) + .withConverter(new JSONConverter(clazz, b)) + .withResolver(new DefaultResolver()); + } + + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String, + * java.lang.Class) + */ + public FetchObject fetch(final String key, final Class type) { + final Bucket b = this; + return new FetchObject(client, this, key) + .withConverter(new JSONConverter(type, b)) + .withResolver(new DefaultResolver()); + } + + + /* (non-Javadoc) + * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) + */ + public FetchObject fetch(String key) { + final Bucket b = this; + + return new FetchObject(client, b, key) + .withResolver(new DefaultResolver()) + .withConverter(new Converter() { + + public RiakObject toDomain(RiakObject riakObject) { + return riakObject; + } + + public RiakObject fromDomain(RiakObject domainObject) { + return domainObject; + } + }); } /* @@ -290,7 +348,23 @@ public FetchObject fetch(T o) { * * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.Object) */ - public DeleteObject delete(T o) { - return null; + public DeleteObject delete(T o) { + final String key = getKey(o); + if(key == null) { + throw new NoKeySpecifedException(o); + } + return new DeleteObject(client, this, key); } + + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.String) + */ + public DeleteObject delete(String key) { + return new DeleteObject(client, this, key); + } + + } diff --git a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java new file mode 100644 index 000000000..cf2aa5c1e --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java @@ -0,0 +1,106 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.builders.DomainBucketBuilder; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.Mutation; +import com.basho.riak.newapi.cap.MutationProducer; +import com.basho.riak.newapi.convert.ConversionUtil; +import com.basho.riak.newapi.convert.Converter; + +/** + * A domain bucket is a wrapper around a bucket that is strongly typed uses a + * preset resolver, mutation producer, converter, r, w, dw, rw, retries, + * returnBody etc + * + * @author russell + * + */ +public class DomainBucket { + + private final Bucket bucket; + private final ConflictResolver resolver; + private final Converter converter; + private final MutationProducer mutationProducer; + private final Integer w; + private final Integer dw; + private final Integer r; + private final Integer rw; + private final boolean returnBody; + private final int retries; + private final Class clazz; + + /** + * @param bucket + * @param resolver + * @param converter + * @param mutation + * @param w + * @param dw + * @param r + * @param rw + * @param returnBody + * @param retries + * @param clazz + */ + public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter converter, + MutationProducer mutationProducer, Integer w, Integer dw, Integer r, Integer rw, boolean returnBody, + int retries, Class clazz) { + this.bucket = bucket; + this.resolver = resolver; + this.converter = converter; + this.mutationProducer = mutationProducer; + this.w = w; + this.dw = dw; + this.r = r; + this.rw = rw; + this.returnBody = returnBody; + this.retries = retries; + this.clazz = clazz; + } + + public T store(T o) throws RiakException { + final Mutation mutation = mutationProducer.produce(o); + return bucket.store(o).withConverter(converter).withMutator(mutation).withResolver(resolver).w(w).dw(dw).retry(retries).returnBody(returnBody).execute(); + } + + public T fetch(String key) throws RiakException { + return bucket.fetch(key, clazz).withConverter(converter).withResolver(resolver).r(r).retry(retries).execute(); + } + + public T fetch(T o) throws RiakException { + return bucket.fetch(o).withConverter(converter).withResolver(resolver).r(r).retry(retries).execute(); + } + + public void delete(T o) throws RiakException { + final String key = ConversionUtil.getKey(o); + delete(key); + } + + public void delete(String key) throws RiakException { + bucket.delete(key).rw(rw).execute(); + } + + /** + * @param b + * the Bucket to wrap + * @param clazz + * @return a DomainBucketBuilder for the wrapped bucket + */ + public static DomainBucketBuilder builder(Bucket b, Class clazz) { + return new DomainBucketBuilder(b, clazz); + } +} diff --git a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java index 055d63953..8945114e3 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java @@ -56,10 +56,10 @@ public WriteBucket(final RawClient client, String name) { public Bucket execute() throws RiakRetryFailedException { final BucketProperties propsToStore = builder.build(); - new DefaultRetrier().attempt(new Command() { - public Boolean execute() throws IOException { + new DefaultRetrier().attempt(new Command() { + public Void execute() throws IOException { client.updateBucket(name, propsToStore); - return true; + return null; } }, retries); diff --git a/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java b/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java new file mode 100644 index 000000000..584f2c30b --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java @@ -0,0 +1,135 @@ +/* + * This file is provided 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.basho.riak.newapi.builders; + +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.DomainBucket; +import com.basho.riak.newapi.cap.ClobberMutation; +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.DefaultResolver; +import com.basho.riak.newapi.cap.Mutation; +import com.basho.riak.newapi.cap.MutationProducer; +import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.newapi.convert.JSONConverter; + +/** + * @author russell + * @param + * the type of the DomainBucket to be built + */ +public class DomainBucketBuilder { + + private final Bucket bucket; + private final Class clazz; + + private ConflictResolver resolver = new DefaultResolver(); + private Converter converter; + private Mutation mutation; + private MutationProducer mutationProducer; + + private Integer w; + private Integer dw; + private Integer r; + private Integer rw; + private boolean returnBody = false; + private int retries = 0; + + /** + * @param bucket + * @param clazz + */ + public DomainBucketBuilder(Bucket bucket, Class clazz) { + this.bucket = bucket; + this.clazz = clazz; + // create a default converter + converter = new JSONConverter(clazz, bucket); + } + + public DomainBucket build() { + // if there is no Mutation or MutationProducer create a default one. + if (mutation != null && mutationProducer == null) { + mutationProducer = new MutationProducer() { + public Mutation produce(T o) { + return mutation; + } + }; + } else if (mutation == null && mutationProducer == null) { + mutationProducer = new MutationProducer() { + + public Mutation produce(T o) { + return new ClobberMutation(o); + } + }; + } + + return new DomainBucket(bucket, resolver, converter, mutationProducer, w, dw, r, rw, returnBody, retries, + clazz); + } + + /** + * @param mergeResolver + * @return + */ + public DomainBucketBuilder withResolver(ConflictResolver resolver) { + this.resolver = resolver; + return this; + } + + /** + * @param returnBody + * @return + */ + public DomainBucketBuilder returnBody(boolean returnBody) { + this.returnBody = returnBody; + return this; + } + + /** + * @param i + * @return + */ + public DomainBucketBuilder retry(int times) { + this.retries = times; + return this; + } + + /** + * @param i + * @return + */ + public DomainBucketBuilder w(int w) { + this.w = w; + return this; + } + + public DomainBucketBuilder r(int r) { + this.r = r; + return this; + } + + public DomainBucketBuilder rw(int rw) { + this.rw = rw; + return this; + } + + public DomainBucketBuilder dw(int dw) { + this.dw = dw; + return this; + } + + public DomainBucketBuilder mutationProducer(MutationProducer mutationProducer) { + this.mutationProducer = mutationProducer; + return this; + } +} diff --git a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java index 83ef57c52..784b1a49a 100644 --- a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java @@ -31,4 +31,8 @@ public BasicVClock(final byte[] value) { public byte[] getBytes() { return value.clone(); } + + public String asString() { + return new String(value); + } } diff --git a/src/main/java/com/basho/riak/newapi/cap/ClientId.java b/src/main/java/com/basho/riak/newapi/cap/ClientId.java new file mode 100644 index 000000000..3e103eb97 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/ClientId.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + +import java.security.SecureRandom; + +import org.apache.commons.codec.binary.Base64; + +/** + * @author russell + * + */ +public class ClientId { + + static SecureRandom rnd = new SecureRandom(); + + /** + * @return a generated client id + */ + public static byte[] generate() { + byte[] bytes = new byte[4]; + rnd.nextBytes(bytes); + return new Base64().encode(bytes); + } +} diff --git a/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java b/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java new file mode 100644 index 000000000..4a53946c4 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java @@ -0,0 +1,42 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + +/** + * A dumb mutation that overwrites the original value with a new one. + * + * @author russell + * @param + * + */ +public class ClobberMutation implements Mutation { + + final T newValue; + + /** + * @param newValue + */ + public ClobberMutation(T newValue) { + this.newValue = newValue; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.cap.Mutation#apply(java.lang.Object) + */ + public T apply(T original) { + return newValue; + } +} diff --git a/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java b/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java new file mode 100644 index 000000000..1325b9c6d --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java @@ -0,0 +1,23 @@ +package com.basho.riak.newapi.cap; + +import java.util.Collection; + + +/** + * A conflict resolver that doesn't resolve conflict. + * If it is presented with a collection of siblings it throws. + * + * @author russell + * + */ +public final class DefaultResolver implements ConflictResolver { + public T resolve(Collection siblings) throws UnresolvedConflictException { + if (siblings.size() > 1) { + throw new UnresolvedConflictException("Siblings found", siblings); + } else if (siblings.size() == 1) { + return siblings.iterator().next(); + } else { + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/cap/Mutation.java b/src/main/java/com/basho/riak/newapi/cap/Mutation.java index cfd7af060..505286dd6 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Mutation.java +++ b/src/main/java/com/basho/riak/newapi/cap/Mutation.java @@ -15,9 +15,16 @@ /** + * Interface for a mutation. + * * @author russell * */ public interface Mutation { - T apply(T value); + /** + * Applies a mutation to the "original" value passed in + * @param original the value to mutate. + * @return the mutated value. + */ + T apply(T original); } diff --git a/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java b/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java new file mode 100644 index 000000000..bb0bb561b --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + +/** + * Maybe you want to produce a mutation at will? Say if you are using a domain bucket? + * @author russell + * @param + * + */ +public interface MutationProducer { + Mutation produce(T o); +} diff --git a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java index 2e76280b8..9e387d750 100644 --- a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java +++ b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java @@ -16,11 +16,9 @@ import java.util.Collection; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; /** * @author russell - * @param * */ public class UnresolvedConflictException extends RiakException { @@ -31,9 +29,9 @@ public class UnresolvedConflictException extends RiakException { private static final long serialVersionUID = -219858468775752064L; private final String reason; - private final Collection siblings; + private final Collection siblings; - public UnresolvedConflictException(String reason, Collection siblings) { + public UnresolvedConflictException(String reason, Collection siblings) { this.reason = reason; this.siblings = siblings; } @@ -49,7 +47,7 @@ public String getReason() { * @param * @return the siblings */ - public Collection getSiblings() { + public Collection getSiblings() { return siblings; } diff --git a/src/main/java/com/basho/riak/newapi/cap/VClock.java b/src/main/java/com/basho/riak/newapi/cap/VClock.java index 6a2f0a684..0b1a79287 100644 --- a/src/main/java/com/basho/riak/newapi/cap/VClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/VClock.java @@ -24,4 +24,9 @@ public interface VClock { * @return */ byte[] getBytes(); + + /** + * @return + */ + String asString(); } diff --git a/src/main/java/com/basho/riak/newapi/convert/ConversionException.java b/src/main/java/com/basho/riak/newapi/convert/ConversionException.java new file mode 100644 index 000000000..7643333ae --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/ConversionException.java @@ -0,0 +1,50 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import com.basho.riak.newapi.RiakException; + +/** + * @author russell + * + */ +public class ConversionException extends RiakException { + + /** + * + */ + private static final long serialVersionUID = -2271716956697197374L; + + /** + * + */ + public ConversionException() { + super(); + } + + /** + * @param message + */ + public ConversionException(String message) { + super(message); + } + + /** + * @param cause + */ + public ConversionException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java b/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java new file mode 100644 index 000000000..007f33981 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java @@ -0,0 +1,56 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import java.lang.reflect.Field; + +/** + * @author russell + * + */ +public class ConversionUtil { + + public static String getKey(T domainObject, String defaultKey) { + String key = getKey(domainObject); + if (key == null) { + key = defaultKey; + } + return key; + } + + public static String getKey(T domainObject) { + final Field[] fields = domainObject.getClass().getDeclaredFields(); + + Object key = null; + + for (Field field : fields) { + + if (field.isAnnotationPresent(RiakKey.class)) { + boolean oldAccessible = field.isAccessible(); + field.setAccessible(true); + try { + key = field.get(domainObject); + } catch (IllegalAccessException e) { + // NO-OP since we can't get the key + } finally { + field.setAccessible(oldAccessible); + } + + } + } + + return key == null ? null : key.toString(); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/convert/Converter.java b/src/main/java/com/basho/riak/newapi/convert/Converter.java index 6f012ec53..612806c32 100644 --- a/src/main/java/com/basho/riak/newapi/convert/Converter.java +++ b/src/main/java/com/basho/riak/newapi/convert/Converter.java @@ -26,13 +26,13 @@ public interface Converter { * @param domainObject * @return a RiakObject populated from domainObject */ - RiakObject fromDomain(T domainObject); + RiakObject fromDomain(T domainObject) throws ConversionException; /** * Convert from a riakObject to a domain specific instance * @param riakObject the RiakObject to convert * @return an instance of type T */ - T toDomain(RiakObject riakObject); + T toDomain(RiakObject riakObject) throws ConversionException; } diff --git a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java new file mode 100644 index 000000000..8caed9101 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java @@ -0,0 +1,106 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import static com.basho.riak.newapi.convert.ConversionUtil.getKey; + +import java.io.IOException; +import java.io.StringWriter; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.ObjectMapper; + +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.builders.RiakObjectBuilder; + +/** + * Converts a RiakObject's value to an instance of T. T must have a field + * annotated with {@link RiakKey}. RiakObject's value *must* be a JSON string. + * + * @author russell + * + */ +public class JSONConverter implements Converter { + + private final ObjectMapper objectMapper = new ObjectMapper(); + private final Class clazz; + private final Bucket bucket; + private String defaultKey; + + public JSONConverter(Class clazz, final Bucket bucket) { + this.clazz = clazz; + this.bucket = bucket; + } + + /** + * @param clazz + * @param b + * @param defaultKey + */ + public JSONConverter(Class clazz, Bucket b, String defaultKey) { + this(clazz, b); + this.defaultKey = defaultKey; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.convert.Converter#fromDomain(java.lang.Object) + */ + public RiakObject fromDomain(T domainObject) throws ConversionException { + try { + String key = getKey(domainObject, this.defaultKey); + + if (key == null) { + throw new NoKeySpecifedException(domainObject); + } + + final StringWriter sw = new StringWriter(); + objectMapper.writeValue(sw, domainObject); + + return RiakObjectBuilder.newBuilder(bucket, key).withValue(sw.toString()).build(); + } catch (JsonProcessingException e) { + throw new ConversionException(e); + } catch (IOException e) { + throw new ConversionException(e); + } + + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.newapi.convert.Converter#toDomain(com.basho.riak.newapi + * .RiakObject) + */ + public T toDomain(RiakObject riakObject) throws ConversionException { + if (riakObject == null) { + return null; + } + + String json = riakObject.getValue(); + + try { + T domainObject = objectMapper.readValue(json, clazz); + return domainObject; + } catch (JsonProcessingException e) { + throw new ConversionException(e); + } catch (IOException e) { + throw new ConversionException(e); + } + } + +} diff --git a/src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java b/src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java new file mode 100644 index 000000000..51510e5c6 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java @@ -0,0 +1,38 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +/** + * @author russell + * + */ +public class NoKeySpecifedException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 8973356637885359438L; + private final Object domainObject; + + /** + * @param domainObject + */ + public NoKeySpecifedException(final Object domainObject) { + this.domainObject = domainObject; + } + + public Object getDomainObject() { + return domainObject; + } +} diff --git a/src/main/java/com/basho/riak/newapi/convert/RiakKey.java b/src/main/java/com/basho/riak/newapi/convert/RiakKey.java new file mode 100644 index 000000000..dc4d6faf7 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/RiakKey.java @@ -0,0 +1,31 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to declare a field as the key to a data item in Riak. + * + * @author russell + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface RiakKey { + +} diff --git a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java index 673ea5a63..e00e67ee5 100644 --- a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java @@ -13,23 +13,56 @@ */ package com.basho.riak.newapi.operations; +import java.io.IOException; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.Bucket; /** * @author russell * */ -public class DeleteObject implements RiakOperation { +public class DeleteObject implements RiakOperation { + + private final RawClient client; + private final Bucket bucket; + private final String key; private Integer rw; private int retries = 0; + /** + * @param client + * @param bucket + * @param key + */ + public DeleteObject(RawClient client, Bucket bucket, String key) { + this.client = client; + this.bucket = bucket; + this.key = key; + } + /* * (non-Javadoc) * * @see com.basho.riak.client.RiakOperation#execute() */ - public T execute() throws RiakRetryFailedException { + public Void execute() throws RiakRetryFailedException { + Command command = new Command() { + public Void execute() throws IOException { + if(rw == null) { + client.delete(bucket, key); + } else { + client.delete(bucket, key, rw); + } + return null; + } + }; + + new DefaultRetrier().attempt(command, retries); return null; } diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java index c001c075a..7405af77c 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -13,26 +13,72 @@ */ package com.basho.riak.newapi.operations; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.DefaultRetrier; +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.ConversionException; import com.basho.riak.newapi.convert.Converter; /** * @author russell - * + * */ public class FetchObject implements RiakOperation { - + + private final Bucket bucket; + private final RawClient client; + private final String key; + + private int retries = 0; + private Integer r; private ConflictResolver resolver; private Converter converter; - /* (non-Javadoc) + /** + * @param bucket + * @param client + */ + public FetchObject(final RawClient client, final Bucket bucket, final String key) { + this.bucket = bucket; + this.client = client; + this.key = key; + } + + /* + * (non-Javadoc) + * * @see com.basho.riak.client.RiakOperation#execute() */ - public T execute() throws UnresolvedConflictException, RiakRetryFailedException { - return null; + public T execute() throws UnresolvedConflictException, RiakRetryFailedException, ConversionException { + // fetch, resolve + Command command = new Command() { + public RiakObject[] execute() throws IOException { + if (r != null) { + return client.fetch(bucket, key, r); + } else { + return client.fetch(bucket, key); + } + } + }; + + final RiakObject[] ros = new DefaultRetrier().attempt(command, retries); + final Collection siblings = new ArrayList(ros.length); + + for (RiakObject o : ros) { + siblings.add(converter.toDomain(o)); + } + + return resolver.resolve(siblings); } public FetchObject withResolver(ConflictResolver resolver) { @@ -44,10 +90,14 @@ public FetchObject r(int r) { this.r = r; return this; } - + public FetchObject withConverter(Converter converter) { this.converter = converter; return this; } + public FetchObject retry(int times) { + this.retries = times; + return this; + } } diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index ab458d85d..c738d855c 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -28,9 +28,14 @@ import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.ConversionException; import com.basho.riak.newapi.convert.Converter; /** + * Stores a given object into riak. Fetches first. + * + * @TODO figure out if you *should* fetch first, and if you should, what about + * R? * @author russell * */ @@ -48,21 +53,11 @@ public class StoreObject implements RiakOperation { private ConflictResolver resolver; private Converter converter; - private String key; + private final String key; - /** - * Create a StoreObject to use the given RawClient to talk to riak. - * - * @param client - * The configured client to use. - */ - public StoreObject(final RawClient client, Bucket bucket) { + public StoreObject(final RawClient client, Bucket bucket, String key) { this.client = client; this.bucket = bucket; - } - - public StoreObject(final RawClient client, Bucket bucket, String key) { - this(client, bucket); this.key = key; } @@ -70,25 +65,16 @@ public StoreObject(final RawClient client, Bucket bucket, String key) { * @return null if returnBody is false * @throws RiakException */ - public T execute() throws RiakRetryFailedException, UnresolvedConflictException { - // fetch, resolve, mutate, put - final RiakObject[] ros = new DefaultRetrier().attempt(new Command() { - public RiakObject[] execute() throws IOException { - return client.fetch(bucket, key); - } - }, retries); - - final Collection siblings = new ArrayList(ros.length); - - for (RiakObject o : ros) { - siblings.add(converter.toDomain(o)); - } + public T execute() throws RiakRetryFailedException, UnresolvedConflictException, ConversionException { + // fetch, mutate, put - System.out.println("Siblings length is " + siblings.size()); + final T resolved = new FetchObject(client, bucket, key) + .retry(retries) + .withConverter(converter) + .withResolver(resolver) + .execute(); - final T resolved = resolver.resolve(siblings); final T mutated = mutation.apply(resolved); - final RiakObject o = converter.fromDomain(mutated); final RiakObject[] stored = new DefaultRetrier().attempt(new Command() { @@ -97,10 +83,10 @@ public RiakObject[] execute() throws IOException { } }, retries); - final Collection storedSiblings = new ArrayList(ros.length); + final Collection storedSiblings = new ArrayList(stored.length); for (RiakObject s : stored) { - siblings.add(converter.toDomain(s)); + storedSiblings.add(converter.toDomain(s)); } return resolver.resolve(storedSiblings); diff --git a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java index ce92e6db8..bdef33610 100644 --- a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java @@ -50,4 +50,53 @@ public String getFun() { return fun; } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((fun == null) ? 0 : fun.hashCode()); + result = prime * result + ((mod == null) ? 0 : mod.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof NamedErlangFunction)) { + return false; + } + NamedErlangFunction other = (NamedErlangFunction) obj; + if (fun == null) { + if (other.fun != null) { + return false; + } + } else if (!fun.equals(other.fun)) { + return false; + } + if (mod == null) { + if (other.mod != null) { + return false; + } + } else if (!mod.equals(other.mod)) { + return false; + } + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override public String toString() { + return String.format("NamedErlangFunction [mod=%s, fun=%s]", mod, fun); + } + } diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index 0ab1baf88..9db531371 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -13,104 +13,215 @@ */ package com.basho.riak.client.itest; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.UUID; -import java.util.concurrent.CountDownLatch; - -import static org.junit.Assert.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.junit.Before; import org.junit.Test; import com.basho.riak.newapi.RiakClient; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.newapi.convert.NoKeySpecifedException; +import com.megacorp.commerce.LegacyCart; +import com.megacorp.commerce.ShoppingCart; /** * @author russell * */ -public class ITestBucket { +public abstract class ITestBucket { + + protected RiakClient client; + + @Before public void setUp() throws RiakException { + client = getClient(); + } + + protected abstract RiakClient getClient() throws RiakException; @Test public void basicStore() throws Exception { final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.pbcClient(); - Bucket b = c.fetchBucket(bucketName).execute(); + Bucket b = client.fetchBucket(bucketName).execute(); RiakObject o = b.store("k", "v").execute(); assertNull(o); + + RiakObject fetched = b.fetch("k").execute(); + assertEquals("v", fetched.getValue()); + + // now update that riak object + b.store("k", "my new value").execute(); + fetched = b.fetch("k").execute(); + assertEquals("my new value", fetched.getValue()); + + b.delete("k").execute(); + + // give it time... + Thread.sleep(500); + + fetched = b.fetch("k").execute(); + assertNull(fetched); } - @Test public void siblings() throws Exception { - final CountDownLatch cdl = new CountDownLatch(1); + @Test public void byDefaultSiblingsThrowUnresolvedExceptionOnStore() throws Exception { final String bucketName = UUID.randomUUID().toString(); - RiakFactory.pbcClient().createBucket(bucketName).allowSiblings(true).execute(); + final Bucket b = client.createBucket(bucketName).allowSiblings(true).execute(); + b.store("k", "v").execute(); final int numThreads = 2; - final Thread[] threads = new Thread[numThreads]; + final Collection> storers = new ArrayList>(numThreads); - CountDownLatch el = new CountDownLatch(numThreads); + final ExecutorService es = Executors.newFixedThreadPool(numThreads); for (int i = 0; i < numThreads; i++) { - RiakClient c = RiakFactory.pbcClient(); + final RiakClient c = getClient(); c.generateAndSetClientId(); - threads[i] = new Thread(new Storer(cdl, el, c.fetchBucket(bucketName).execute(), "k", "v")); - threads[i].start(); + final Bucket bucket = c.fetchBucket(bucketName).execute(); + + storers.add(new Callable() { + public Boolean call() throws RiakException { + try { + for (int i = 0; i < 5; i++) { + bucket.store("k", Thread.currentThread().getName() + "v" + i).execute(); + Thread.sleep(50); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + return true; + } + }); } - cdl.countDown(); + Collection> results = es.invokeAll(storers); - el.await(); - System.out.println(bucketName); + for (Future f : results) { + try { + f.get(); + fail("Expected siblings"); + } catch (ExecutionException e) { + assertEquals(UnresolvedConflictException.class, e.getCause().getClass()); + } + } + + // TODO clean up your mess (teardown) } - private static final class Storer implements Runnable { - private final CountDownLatch startLatch; - private final CountDownLatch endLatch; - private final Bucket bucket; - private final String key; - private final String value; - - /** - * @param startLatch - * @param bucket - * @param key - * @param value - */ - private Storer(CountDownLatch startLatch, CountDownLatch endLatch, Bucket bucket, String key, String value) { - this.startLatch = startLatch; - this.endLatch = endLatch; - this.bucket = bucket; - this.key = key; - this.value = value; + /** + * @see ITestDomainBucket + * @throws Exception + */ + @Test public void storeDomainObjectWithKeyAnnotation() throws Exception { + final String bucketName = UUID.randomUUID().toString() + "_carts"; + final String userId = UUID.randomUUID().toString(); + + final Bucket carts = client.createBucket(bucketName).allowSiblings(true).execute(); + + final ShoppingCart cart = new ShoppingCart(userId); + + cart.addItem("coffee"); + cart.addItem("fixie"); + cart.addItem("moleskine"); + + carts.store(cart).returnBody(false).retry(3).execute(); + + final ShoppingCart fetchedCart = carts.fetch(cart).execute(); + + assertNotNull(fetchedCart); + assertEquals(cart.getUserId(), fetchedCart.getUserId()); + assertEquals(cart, fetchedCart); + + carts.delete(fetchedCart).rw(3).execute(); + + Thread.sleep(500); + + assertNull(carts.fetch(userId).execute()); + } + + @Test public void storeDomainObjectWithoutKeyAnnotation() throws Exception { + final String bucketName = UUID.randomUUID().toString() + "_carts"; + final String userId = UUID.randomUUID().toString(); + + final Bucket carts = client.createBucket(bucketName).allowSiblings(true).execute(); + + final LegacyCart cart = new LegacyCart(); + cart.setUserId(userId); + + cart.addItem("coffee"); + cart.addItem("fixie"); + cart.addItem("moleskine"); + + try { + carts.store(cart).returnBody(false).retry(3).execute(); + fail("Expected NoKeySpecifiedException"); + } catch (NoKeySpecifedException e) { + // NO-OP } - /* - * (non-Javadoc) - * - * @see java.lang.Runnable#run() - */ - public void run() { - try { - startLatch.await(); - for (int i = 0; i < 5; i++) { - System.out.println(Thread.currentThread().getName() + " doing run " + i); - bucket.store(key, Thread.currentThread().getName() + value + i).execute(); - Thread.sleep(10); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (RiakException e) { - System.out.println(Thread.currentThread().getName() + " just barfed"); - throw new RuntimeException(e); - } finally { - endLatch.countDown(); - } + carts.store(userId, cart).returnBody(false).retry(3).execute(); + + try { + carts.fetch(cart).retry(3).execute(); + fail("Expected NoKeySpecifiedException"); + } catch (NoKeySpecifedException e) { + // NO-OP + } + + final LegacyCart fetchedCart = carts.fetch(userId, LegacyCart.class).execute(); + + assertNotNull(fetchedCart); + assertEquals(cart.getUserId(), fetchedCart.getUserId()); + assertEquals(cart, fetchedCart); + + try { + carts.delete(cart).retry(3).execute(); + fail("Expected NoKeySpecifiedException"); + } catch (NoKeySpecifedException e) { + // NO-OP } + carts.delete(userId).rw(3).execute(); + + Thread.sleep(500); + + assertNull(carts.fetch(userId).execute()); } + @Test public void listKeys() throws Exception { + final Set keys = new LinkedHashSet(); + + final String bucketName = UUID.randomUUID().toString(); + + Bucket b = client.fetchBucket(bucketName).execute(); + + for (int i = 65; i <= 90; i++) { + String key = Character.toString((char) i); + b.store(key, i).execute(); + keys.add(key); + } + + for (String key : b.keys()) { + assertTrue(keys.remove(key)); + } + + assertTrue(keys.isEmpty()); + } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestClient.java b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java similarity index 66% rename from src/test/java/com/basho/riak/client/itest/ITestClient.java rename to src/test/java/com/basho/riak/client/itest/ITestClientBasic.java index 33f2f25ed..91fe2db91 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java @@ -13,28 +13,43 @@ */ package com.basho.riak.client.itest; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.util.UUID; +import org.junit.Before; import org.junit.Test; import com.basho.riak.newapi.RiakClient; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.bucket.Bucket; /** * @author russell * */ -public class ITestClient { +public abstract class ITestClientBasic { + + protected RiakClient client; + + @Before + public void setUp() throws RiakException { + this.client = getClient(); + } + + /** + * @return + */ + protected abstract RiakClient getClient() throws RiakException; @Test public void fetchBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.pbcClient(); - Bucket b = c.fetchBucket(bucketName).execute(); + Bucket b = client.fetchBucket(bucketName).execute(); assertNotNull(b); assertEquals(bucketName, b.getName()); @@ -44,16 +59,15 @@ public class ITestClient { @Test public void updateBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.pbcClient(); - Bucket b = c.fetchBucket(bucketName).execute(); + Bucket b = client.fetchBucket(bucketName).execute(); assertNotNull(b); assertEquals(bucketName, b.getName()); assertEquals(new Integer(3), b.getNVal()); assertFalse(b.getAllowSiblings()); - b = c.updateBucket(b).nVal(4).allowSiblings(true).execute(); + b = client.updateBucket(b).nVal(4).allowSiblings(true).execute(); assertNotNull(b); assertEquals(bucketName, b.getName()); @@ -61,12 +75,10 @@ public class ITestClient { assertTrue(b.getAllowSiblings()); } - @Test public void createBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); - RiakClient c = RiakFactory.pbcClient(); - Bucket b = c.createBucket(bucketName).nVal(1).allowSiblings(true).execute(); + Bucket b = client.createBucket(bucketName).nVal(1).allowSiblings(true).execute(); assertNotNull(b); assertEquals(bucketName, b.getName()); @@ -76,12 +88,12 @@ public class ITestClient { @Test public void clientIds() throws Exception { final byte[] clientId = "abcd".getBytes("UTF-8"); - RiakClient c = RiakFactory.pbcClient(); - c.setClientId(clientId.clone()); - assertArrayEquals(clientId, c.getClientId()); - byte[] newId = c.generateAndSetClientId(); + client.setClientId(clientId.clone()); + assertArrayEquals(clientId, client.getClientId()); + + byte[] newId = client.generateAndSetClientId(); - assertArrayEquals(newId, c.getClientId()); + assertArrayEquals(newId, client.getClientId()); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java new file mode 100644 index 000000000..e7bc73618 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java @@ -0,0 +1,102 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.DomainBucket; +import com.megacorp.commerce.MergeResolver; +import com.megacorp.commerce.ShoppingCart; + +/** + * A DomainBucket is a wrapper around a bucket that uses a preset conflict + * resolver, [ mutator, converter, r, rw, dw, w, retries etc] + * + * @author russell + * + */ +public class ITestDomainBucket { + + @Test public void useDomainBucket() throws Exception { + final String bucketName = UUID.randomUUID().toString() + "_carts"; + final String userId = UUID.randomUUID().toString(); + + final Bucket b = RiakFactory.pbcClient().createBucket(bucketName).allowSiblings(true).nVal(3).execute(); + + final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class) + .withResolver(new MergeResolver()) + .returnBody(true) + .retry(3) + .w(1) + .dw(1) + .r(1) + .rw(1) + .build(); + + final ShoppingCart cart = new ShoppingCart(userId); + + cart.addItem("coffee"); + cart.addItem("fixie"); + cart.addItem("moleskine"); + + final ShoppingCart storedCart = carts.store(cart); + + assertNotNull(storedCart); + assertEquals(cart.getUserId(), storedCart.getUserId()); + assertEquals(cart, storedCart); + + final ExecutorService es = Executors.newFixedThreadPool(2); + final Collection> tasks = new ArrayList>(); + + tasks.add(new Callable() { + public ShoppingCart call() throws Exception { + final ShoppingCart cart = carts.fetch(userId); + cart.addItem("bowtie"); + cart.addItem("nail gun"); + return carts.store(cart); + } + }); + + tasks.add(new Callable() { + public ShoppingCart call() throws Exception { + final ShoppingCart cart = carts.fetch(userId); + cart.addItem("hippo"); + cart.addItem("jasmin tea"); + return carts.store(cart); + } + }); + + es.invokeAll(tasks); + + final String[] expectedMergesCart = { "coffee", "fixie", "moleskine", "hippo", "jasmin tea", "nail gun", + "bowtie" }; + + final ShoppingCart finalCart = carts.fetch(userId); + assertTrue(finalCart.hasAll(Arrays.asList(expectedMergesCart))); + } +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java new file mode 100644 index 000000000..aa0e5b95a --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestHTTPBucket extends ITestBucket { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestBucket#getClient() + */ + @Override protected RiakClient getClient() throws RiakException { + return RiakFactory.httpClient(); + } +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java new file mode 100644 index 000000000..17c7f1e93 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java @@ -0,0 +1,87 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.assertEquals; + +import java.util.UUID; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.query.NamedErlangFunction; + +/** + * @author russell + * + */ +public class ITestHTTPClient extends ITestClientBasic { + + /* (non-Javadoc) + * @see com.basho.riak.client.itest.ITestClient#getClient() + */ + @Override protected RiakClient getClient() throws RiakException { + return RiakFactory.httpClient(); + } + + @Test public void fetchBucket() throws RiakException { + super.fetchBucket(); + final String bucketName = UUID.randomUUID().toString(); + + Bucket b = client.fetchBucket(bucketName).execute(); + + assertEquals(new NamedErlangFunction("riak_core_util", "chash_std_keyfun"), b.getChashKeyFunction()); + assertEquals(new NamedErlangFunction("riak_kv_wm_link_walker", "mapreduce_linkfun"), b.getLinkWalkFunction()); + } + + @Test public void updateBucket() throws RiakException { + final NamedErlangFunction newChashkeyFun = new NamedErlangFunction("riak_core_util", "chash_bucketonly_keyfun"); + final NamedErlangFunction newLinkwalkFun = new NamedErlangFunction("riak_core_util", "chash_std_keyfun"); + + super.updateBucket(); + + final String bucketName = UUID.randomUUID().toString(); + + Bucket b = client.fetchBucket(bucketName).execute(); + + + b = client.updateBucket(b).chashKeyFunction(newChashkeyFun).linkWalkFunction(newLinkwalkFun).execute(); + + assertEquals(newChashkeyFun, b.getChashKeyFunction()); + assertEquals(newLinkwalkFun, b.getLinkWalkFunction()); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.itest.ITestClient#createBucket() + */ + @Override public void createBucket() throws RiakException { + super.createBucket(); + + final NamedErlangFunction newChashkeyFun = new NamedErlangFunction("riak_core_util", "chash_bucketonly_keyfun"); + final NamedErlangFunction newLinkwalkFun = new NamedErlangFunction("riak_core_util", "chash_std_keyfun"); + + final String bucketName = UUID.randomUUID().toString(); + + Bucket b = client.createBucket(bucketName).chashKeyFunction(newChashkeyFun).linkWalkFunction(newLinkwalkFun).execute(); + + assertEquals(newChashkeyFun, b.getChashKeyFunction()); + assertEquals(newLinkwalkFun, b.getLinkWalkFunction()); + } + + + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java new file mode 100644 index 000000000..bbbcdde11 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java @@ -0,0 +1,35 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestPBBucket extends ITestBucket { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestBucket#getClient() + */ + @Override protected RiakClient getClient() throws RiakException { + return RiakFactory.pbcClient(); + } + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java new file mode 100644 index 000000000..f4ea90d5a --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java @@ -0,0 +1,33 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestPBClient extends ITestClientBasic { + + /* (non-Javadoc) + * @see com.basho.riak.client.itest.ITestClient#getClient() + */ + @Override protected RiakClient getClient() throws RiakException { + return RiakFactory.pbcClient(); + } + +} diff --git a/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java new file mode 100644 index 000000000..b285644c6 --- /dev/null +++ b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java @@ -0,0 +1,61 @@ +/* + * This file is provided 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.basho.riak.client.raw.http; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collection; +import java.util.Iterator; + +import org.junit.Test; + +import com.basho.riak.client.RiakBucketInfo; +import com.basho.riak.client.response.BucketResponse; + +/** + * @author russell + * + */ +public class TestKeySource { + + /** + * This is a bit ropey (calling GC to cause ks to be unreachable) but it + * needs testing + * + * @throws Exception + */ + @SuppressWarnings({ "unchecked", "unused" }) @Test public void streamIsClosedWhenKeySourceIsWeaklyReachable() throws Exception { + final BucketResponse bucketResponse = mock(BucketResponse.class); + final RiakBucketInfo riakBucketInfo = mock(RiakBucketInfo.class); + final Collection keys = mock(Collection.class); + final Iterator iterator = mock(Iterator.class); + + when(bucketResponse.getBucketInfo()).thenReturn(riakBucketInfo); + when(riakBucketInfo.getKeys()).thenReturn(keys); + when(keys.iterator()).thenReturn(iterator); + + KeySource ks = new KeySource(bucketResponse); + + ks = null; + + System.gc(); + Thread.sleep(1000); + + verify(bucketResponse, times(1)).close(); + } + +} diff --git a/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java b/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java new file mode 100644 index 000000000..331c343e7 --- /dev/null +++ b/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java @@ -0,0 +1,46 @@ +/* + * This file is provided 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.basho.riak.newapi.cap; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import org.junit.Test; + +/** + * @author russell + * + */ +public class ClobberMutationTest { + + /** + * Test method for {@link com.basho.riak.newapi.cap.ClobberMutation#ClobberMutation(java.lang.Object)}. + */ + @Test public void apply() { + final Object oldValue = new Object(); + + ClobberMutation mutation = new ClobberMutation(null); + + assertNull(mutation.apply(oldValue)); + + Object newValue = new Object(); + + assertNotSame(oldValue, newValue); + mutation = new ClobberMutation(newValue); + + assertSame(newValue, mutation.apply(new Object())); + } + +} diff --git a/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java b/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java new file mode 100644 index 000000000..e5ed78f98 --- /dev/null +++ b/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java @@ -0,0 +1,68 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Calendar; +import java.util.Date; + +import org.junit.Test; + +/** + * @author russell + * + */ +public class ConversionUtilTest { + + @Test public void getKey() { + final String expected = "aKey"; + final Object o = new Object() { + @SuppressWarnings("unused") @RiakKey private final String domainProperty = expected; + + }; + + assertEquals(expected, ConversionUtil.getKey(o)); + } + + @Test public void getNonStringKey() { + final Date expected = Calendar.getInstance().getTime(); + final Object o = new Object() { + @SuppressWarnings("unused") @RiakKey private final Date domainProperty = expected; + + }; + + assertEquals(expected.toString(), ConversionUtil.getKey(o)); + } + + @Test public void noKeyField() { + final Object o = new Object() { + @SuppressWarnings("unused") private final String domainProperty = "tomatoes"; + + }; + + assertNull(ConversionUtil.getKey(o)); + } + + @Test public void nullKeyField() { + final Object o = new Object() { + @SuppressWarnings("unused") @RiakKey private final Date domainProperty = null; + + }; + + assertNull(ConversionUtil.getKey(o)); + } + +} diff --git a/src/test/java/com/megacorp/commerce/LegacyCart.java b/src/test/java/com/megacorp/commerce/LegacyCart.java new file mode 100644 index 000000000..1d307a208 --- /dev/null +++ b/src/test/java/com/megacorp/commerce/LegacyCart.java @@ -0,0 +1,106 @@ +/* + * This file is provided 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.megacorp.commerce; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * @author russell + * + */ +public class LegacyCart { + + private String userId; + private Set cartItems = new CopyOnWriteArraySet(); + + /** + * @return the userId + */ + public String getUserId() { + return userId; + } + + /** + * @param userId + * the userId to set + */ + public void setUserId(String userId) { + this.userId = userId; + } + + /** + * @return the cartItems + */ + public Set getCartItems() { + return cartItems; + } + + /** + * @param cartItems + * the cartItems to set + */ + public void setCartItems(Set cartItems) { + this.cartItems = cartItems; + } + + /** + * @param string + */ + public void addItem(String item) { + cartItems.add(item); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((cartItems == null) ? 0 : cartItems.hashCode()); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof LegacyCart)) { + return false; + } + LegacyCart other = (LegacyCart) obj; + if (cartItems == null) { + if (other.cartItems != null) { + return false; + } + } else if (!cartItems.equals(other.cartItems)) { + return false; + } + if (userId == null) { + if (other.userId != null) { + return false; + } + } else if (!userId.equals(other.userId)) { + return false; + } + return true; + } +} diff --git a/src/test/java/com/megacorp/commerce/MergeResolver.java b/src/test/java/com/megacorp/commerce/MergeResolver.java new file mode 100644 index 000000000..5aaae8c69 --- /dev/null +++ b/src/test/java/com/megacorp/commerce/MergeResolver.java @@ -0,0 +1,33 @@ +package com.megacorp.commerce; + +import java.util.ArrayList; +import java.util.Collection; + +import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.UnresolvedConflictException; + +/** + * A simple example of a conflict resolver for the ShoppingCart domain type. + * + * Merge the contents of any siblings, worse case is deletes get undone. + * + * @author russell + * + */ +public final class MergeResolver implements ConflictResolver { + + public ShoppingCart resolve(Collection siblings) throws UnresolvedConflictException { + String userId = null; + final Collection items = new ArrayList(); + + for (ShoppingCart c : siblings) { + userId = c.getUserId(); + for (String item : c) { + items.add(item); + } + } + + final ShoppingCart resolved = new ShoppingCart(userId); + return resolved.addItems(items); + } +} \ No newline at end of file diff --git a/src/test/java/com/megacorp/commerce/ShoppingCart.java b/src/test/java/com/megacorp/commerce/ShoppingCart.java new file mode 100644 index 000000000..9ffad0bf9 --- /dev/null +++ b/src/test/java/com/megacorp/commerce/ShoppingCart.java @@ -0,0 +1,145 @@ +/* + * This file is provided 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.megacorp.commerce; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; + +import com.basho.riak.newapi.convert.RiakKey; + +/** + * A simple domain object for the sake of ITests. + * + * @author russell + * + */ +public class ShoppingCart implements Iterable { + + @RiakKey private final String userId; + @JsonProperty private final Set items; + + /** + * @param userId + */ + @JsonCreator public ShoppingCart(@JsonProperty("userId") String userId) { + this.userId = userId; + items = new CopyOnWriteArraySet(); + } + + public ShoppingCart addItem(String item) { + items.add(item); + return this; + } + + public ShoppingCart addItems(Collection all) { + items.addAll(all); + return this; + } + + public ShoppingCart removeItem(String item) { + items.remove(item); + return this; + } + + public ShoppingCart clear() { + items.clear(); + return this; + } + + public int size() { + return items.size(); + } + + public boolean hasItem(String item) { + return items.contains(item); + } + + public boolean hasAll(Collection all) { + return items.containsAll(all); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + return items.iterator(); + } + + public String getUserId() { + return userId; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((items == null) ? 0 : items.hashCode()); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ShoppingCart)) { + return false; + } + ShoppingCart other = (ShoppingCart) obj; + if (items == null) { + if (other.items != null) { + return false; + } + } else if (!items.equals(other.items)) { + return false; + } + if (userId == null) { + if (other.userId != null) { + return false; + } + } else if (!userId.equals(other.userId)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override public String toString() { + return String.format("ShoppingCart [userId=%s, items=%s]", userId, items); + } + +} From af42245d33fbf47ba147c2b33c5c0ef61233e91b Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 14 Apr 2011 17:35:31 +0100 Subject: [PATCH 006/764] README --- README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..e69de29bb From dc20920c139cf14aba5a6b31dd2c229e27ca7006 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 15 Apr 2011 18:59:42 +0100 Subject: [PATCH 007/764] Initial commit of a high level Java API for Riak See README.org --- README.md | 0 README.org | 191 ++++++++++++++++++ .../com/basho/riak/client/raw/Command.java | 4 +- .../com/basho/riak/client/raw/RawClient.java | 21 +- .../com/basho/riak/client/raw/Retrier.java | 2 +- .../basho/riak/client/raw/RiakResponse.java | 104 ++++++++++ .../client/raw/http/HTTPClientAdapter.java | 66 +++--- .../basho/riak/client/raw/http/KeySource.java | 5 +- .../riak/client/raw/pbc/PBClientAdapter.java | 25 +-- .../riak/client/raw/query/LinkWalkSpec.java | 2 +- .../com/basho/riak/newapi/DefaultClient.java | 6 +- .../basho/riak/newapi/DefaultRiakObject.java | 4 +- .../com/basho/riak/newapi/RiakClient.java | 6 +- .../com/basho/riak/newapi/RiakException.java | 2 +- .../com/basho/riak/newapi/RiakFactory.java | 8 + .../com/basho/riak/newapi/RiakObject.java | 5 +- .../riak/newapi/RiakRetryFailedException.java | 2 +- .../com/basho/riak/newapi/bucket/Bucket.java | 13 +- .../riak/newapi/bucket/BucketProperties.java | 3 +- .../riak/newapi/bucket/DefaultBucket.java | 76 ++++--- .../newapi/builders/RiakObjectBuilder.java | 18 +- .../basho/riak/newapi/cap/BasicVClock.java | 2 +- .../java/com/basho/riak/newapi/cap/CAP.java | 2 +- .../com/basho/riak/newapi/cap/ClientId.java | 6 +- .../riak/newapi/cap/ConflictResolver.java | 4 +- .../riak/newapi/cap/DefaultResolver.java | 5 +- .../com/basho/riak/newapi/cap/Mutation.java | 7 +- .../riak/newapi/cap/MutationProducer.java | 6 +- .../com/basho/riak/newapi/cap/Quorum.java | 1 - .../cap/UnresolvedConflictException.java | 2 +- .../com/basho/riak/newapi/cap/VClock.java | 1 - .../basho/riak/newapi/convert/Converter.java | 10 +- .../riak/newapi/convert/JSONConverter.java | 10 +- .../basho/riak/newapi/convert/RiakKey.java | 6 +- .../riak/newapi/operations/DeleteObject.java | 4 +- .../riak/newapi/operations/FetchObject.java | 9 +- .../riak/newapi/operations/RiakOperation.java | 4 +- .../riak/newapi/operations/StoreObject.java | 34 +++- .../basho/riak/newapi/query/MapReduce.java | 11 +- .../riak/newapi/query/MapReduceResult.java | 5 +- .../riak/newapi/query/MapReduceSpec.java | 3 +- .../newapi/query/NamedErlangFunction.java | 14 +- .../riak/newapi/query/NamedFunction.java | 2 +- .../basho/riak/newapi/query/WalkResult.java | 4 +- .../basho/riak/client/BasicOperations.java | 116 ----------- .../basho/riak/client/itest/ITestBucket.java | 40 ++++ .../riak/client/itest/ITestClientBasic.java | 23 +-- .../riak/client/itest/ITestDomainBucket.java | 31 +-- .../client/itest/ITestDomainBucketHTTP.java | 39 ++++ .../client/itest/ITestDomainBucketPB.java | 35 ++++ .../riak/client/itest/ITestHTTPClient.java | 31 +-- .../riak/client/itest/ITestPBClient.java | 6 +- .../riak/client/raw/http/TestKeySource.java | 3 +- .../riak/newapi/cap/ClobberMutationTest.java | 16 +- .../com/megacorp/commerce/LegacyCart.java | 8 +- ...geResolver.java => MergeCartResolver.java} | 10 +- 56 files changed, 719 insertions(+), 354 deletions(-) delete mode 100644 README.md create mode 100644 README.org create mode 100644 src/main/java/com/basho/riak/client/raw/RiakResponse.java delete mode 100644 src/test/java/com/basho/riak/client/BasicOperations.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java rename src/test/java/com/megacorp/commerce/{MergeResolver.java => MergeCartResolver.java} (74%) diff --git a/README.md b/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/README.org b/README.org new file mode 100644 index 000000000..d262121da --- /dev/null +++ b/README.org @@ -0,0 +1,191 @@ +* A New Riak Java Client API + +** What's wrong? + +Accusations have been made against the current riak-java-client. Certainly it +leaks implementation details (Apache HttpClient, JSONArray, JSONObject, +ByteString etc) into client code. And there are 3 different possible client +interfaces: + ++ An Http style client ++ A more OO client that uses the Http client ++ A protocol buffers client + +All of these leak their abstractions and force the user to make an upfront +choice about transport/features and then code to that decision. + +Some people don't like Apache HttpClient, and that is fair enough, so it would +be ideal if we didn't force it on those people. Better yet make it easy to +create new implementations for the transport (using Netty or RestTemplate or +what-have-you). + +More than that, though, it doesn't make it any easier to work with a fault +tolerant, distributed KV store (like Riak). + +** What's new? + +Well it *is* Java, so I added some more layers. + +*** New boss, same as the old boss + +Underneath is the same HTTP RiakClient and pbc.RiakClient that you know and +love. They have a couple more fixes and an accessor or two but fundamentally +uncchanged. + +*** Wrapper + +There's a new interface, that is currently called RawClient, and two adapters +that wrap the existing clients and adapt them to the new API. So if all you +want is to write code against a low level client then use the RawClient +interface and you don't have to chose upfront HTTP or PBC anymore. And if you +want to add your own Netty client, or Spring REST Template, then implement this +interface, please. + +*** Riak, Buckets, Objects + +On top of the RawClient there is a higher level API that attempts to make it +easier to deal with eventual consitency. All the ideas for this layer came from +the Coda Hale's talk [[http://blog.basho.com/2011/03/28/Riak-and-Scala-at-Yammer/][Riak and Scala at Yammer]] and a subsequent email +conversation he was kind enough to have with me. And also from [[http://lists.basho.com/pipermail/riak-users_lists.basho.com/2011-March/003662.html][this post]] to the +Riak mailing list from Kresten Krab Thorup. Not that they are in anyway to blame +for all this. + +**** Simpler client + +The high level Riak client lets you work with buckets and map reduce. The map +reduce/link walking stuff is incomplete so I'll skip that (for now). + +Have a look at +[[https://github.com/russelldb/riak-api/blob/master/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java][ITestClientBasic]] +and +[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/RiakClient.java][RiakClient]]. +All Riak access to a riak objects is done through the Bucket interface, the +client just creates/updates and fetches buckets. + +**** Buckets + +A test is worth a 100 words so have a look at +[[https://github.com/russelldb/riak-api/blob/master/src/test/java/com/basho/riak/client/itest/ITestBucket.java][ITestBucket]] +and the interface +[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/bucket/Bucket.java][Bucket]] + +Bucket methods return +[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java][RiakOperation's]], +which are implemented as fluent builders to save the proliferation of methods +that occur when you have a lot of optional arguments. + +**** Riak Opertaions + +A RiakOpertaion is configured and then it is executed. This is how to fetch, +store or delete data. It can be configured to be retried N times. By default +that N is 0 (IE try once and fail at once.) An operation accepts the parameters +it needs. So A Delete Operation accepts an optional RW param, for example. + +**** Conflict resolution, Mutation and Converstion + +***** Conflict + +Conflict happens in Dynamo style systems. It is best to have a strategy in mind +to deal with it. The strategy is highly dependant on your domain. A classic +example is the shopping cart [see_shopping_cart] , conflicting shopping carts +can be merged by a union of their contents, sure you might reinstate a deleted +toaster but that is better than losing money... See [cart_merger]. + +Both fetch and store make use of a ConflictResolver to handle siblings. The +default conflict resolver right now does not resolve conflicts, it blows up with +an UnresolvedConflictException (which gives you access to the siblings). + +Using the basic bucket interface you can provide an anonymous inner class as a +conflict resolver to either a fetch or a store operation. + +***** Conversion + +Since conflict resolution is a very domain specific thing it makes sense to +convert the Riak data into a domain specific object before conflict is +resolved. You provide an implementation of the [Converter] interface to any +fetch/store operation. By default, if you are working with a +operation the converter does nothing. If you are working with a generic +operation then there is a basic JSONConverter [link] that is the simplest +possible use of [[http://wiki.fasterxml.com/JacksonHome][Jackson JSON converter]]. It will attempt to coherce a +RiakObject's JSON payload into a domain class of your chosing. It can also +return Map, Collection etc if you are yet to decide on a domain. + +***** Mutation + +With conflict resolution comes Mutation. When you perform a store you may be + ++ Creating a new value with a new key ++ Updating an existing value + +And *you don't know in advance*. You may think you're creating a new value but +many people may have beaten you to it. Using the Shopping Cart as an example +again, you don't want to overwrite the existing value with your own new value, +so a Mutation that merges the current value with your new value makes sense +here. + +You provide an implementation of Mutation [link] that accepts the old value +and returns the new value. The default current mutation clobbers the old value, +that is it ignores the old value and returns your new value. + +***** Fetch then Store All together a Fetch operation now entails + +1. Fetch the object from Riak +2. Run the Converter +3. Run the ConflictResolver +4. Return the converted object + +a store + +1. Run a fetch +2. Run the mutation on the result +3. Store the new object +4. Optionally (if return body is true) run the Converter and ConflictResolver + and return the resolved value. + + +**** Domain Buckets + + If you are working with ShoppingCarts you're working with Shopping Carts. It is + a lot of faff providing the Converter, Mutation and ConflictResolver to the + Bucket operation over and over again (see [link to ItestBasicBucket]). So there + are [DomainBuckets]. A DomainBucket is a wrapper around a bucket (you see, + *another* layer) that is configured at creation time with a ConflictResolver, + MutationProvider and a Converter. Thereafter you can work with the DomainBucket + and deal solely with your ShoppingCart. Look at [link_to_itest_domain_bucket] + for an example. + +There well very soon be a default RiakObject DomainBucket preconfigured with a +ClobberMutation, no resolution ConflictResolver and do nothing converter in the +library for convenience. + +*** Workflow + +The API makes it easy to start experimenting with Riak and start to create +anonymous inner classes for ConflictResolution/Mutation/Conversion and then, as +your application firms up, you can codify the your strategies into solid, +testable, resusable classes and DomainBuckets. + +*** Flexible + + If you need raw speed pumping 1000s of objects in go right down to the lowest + level and use the pbc.RiakClient. If you want to start off with HTTP but later + implement your own transport use RawClient. If you want to work at a higher + level of abstraction use Bucket and DomainBucket. + +*** State of play + + This is very much an early release work in progress but it covers the KV store + and has integration test coverage of ~65%. Don't use it in production but + please play with it and feedback. + +*** TODO So much. A small snippet of which is: + +- Add tests to verify Links and UserMeta work +- MapReduce and LinkWalking for a start. +- Tidy the code and vet it for Thread Safety +- An simple method for registering and configuring RawClient implementations +- Many more unit tests +- Sort out the package names +- Stop leaking Jackson annotations +- A default RiakObject DomaonBucket (as described above) + diff --git a/src/main/java/com/basho/riak/client/raw/Command.java b/src/main/java/com/basho/riak/client/raw/Command.java index 9a884556b..9e6c877d5 100644 --- a/src/main/java/com/basho/riak/client/raw/Command.java +++ b/src/main/java/com/basho/riak/client/raw/Command.java @@ -17,10 +17,10 @@ /** * @author russell - * + * */ public interface Command { T execute() throws IOException; - + } diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index a4016d834..7d8a7d960 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -33,16 +33,16 @@ public interface RawClient { // RiakObject - RiakObject[] fetch(Bucket bucket, String key) throws IOException; - - RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException; + RiakResponse fetch(Bucket bucket, String key) throws IOException; - RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOException; + RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException; + + RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOException; void store(RiakObject object) throws IOException; void delete(Bucket bucket, String key) throws IOException; - + void delete(Bucket bucket, String key, int deleteQuorum) throws IOException; // Bucket @@ -56,16 +56,19 @@ public interface RawClient { // Query WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException; - + MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException; /** - * If you don't set a client id explicitly at least call this to set one. - * It generates the 4 byte ID and sets that Id on the client - * IE you *don't* need to call setClientId() with the result of generate. + * If you don't set a client id explicitly at least call this to set one. It + * generates the 4 byte ID and sets that Id on the client IE you *don't* + * need to call setClientId() with the result of generate. + * * @return the generated clientId for the client */ byte[] generateAndSetClientId() throws IOException; + void setClientId(byte[] clientId) throws IOException; + byte[] getClientId() throws IOException; } diff --git a/src/main/java/com/basho/riak/client/raw/Retrier.java b/src/main/java/com/basho/riak/client/raw/Retrier.java index d2b9418ad..8eef9d893 100644 --- a/src/main/java/com/basho/riak/client/raw/Retrier.java +++ b/src/main/java/com/basho/riak/client/raw/Retrier.java @@ -17,7 +17,7 @@ /** * @author russell - * + * */ public interface Retrier { T attempt(Command command, int times) throws RiakRetryFailedException; diff --git a/src/main/java/com/basho/riak/client/raw/RiakResponse.java b/src/main/java/com/basho/riak/client/raw/RiakResponse.java new file mode 100644 index 000000000..ae160158d --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/RiakResponse.java @@ -0,0 +1,104 @@ +/* + * This file is provided 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.basho.riak.client.raw; + +import java.util.Arrays; +import java.util.Iterator; + +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.cap.BasicVClock; +import com.basho.riak.newapi.cap.VClock; + +/** + * What riak returns: a VClock and bunch of siblings. + * + * @author russell + */ +public class RiakResponse implements Iterable { + + private static final RiakObject[] NO_OBJECTS = new RiakObject[] {}; + private final VClock vclock; + private final RiakObject[] riakObjects; + + /** + * @param vclock + * @param riakObjects + */ + public RiakResponse(byte[] vclock, RiakObject[] riakObjects) { + this.vclock = new BasicVClock(vclock); + if (riakObjects == null) { + this.riakObjects = NO_OBJECTS; + } else { + this.riakObjects = riakObjects; + } + } + + /** + * + */ + private RiakResponse() { + this.riakObjects = NO_OBJECTS; + this.vclock = null; + } + + /** + * @return the vclock + */ + public byte[] getVclockBytes() { + return vclock.getBytes(); + } + + /** + * @return the vclock + */ + public VClock getVclock() { + return vclock; + } + + /** + * @return the riakObjects + */ + public RiakObject[] getRiakObjects() { + return riakObjects; + } + + public boolean hasSiblings() { + return riakObjects.length > 1; + } + + public boolean hasValue() { + return riakObjects.length > 0; + } + + public int numberOfValues() { + return riakObjects.length; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + return Arrays.asList(riakObjects).iterator(); + } + + /** + * @return + */ + public static RiakResponse empty() { + return new RiakResponse(); + } + +} diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index b46f3c5d3..d16a08d4a 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -28,6 +28,7 @@ import com.basho.riak.client.RiakBucketInfo; import com.basho.riak.client.RiakClient; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; @@ -81,7 +82,7 @@ public HTTPClientAdapter(String url) { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String) */ - public RiakObject[] fetch(Bucket bucket, String key) throws IOException { + public RiakResponse fetch(Bucket bucket, String key) throws IOException { if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " @@ -104,7 +105,7 @@ public RiakObject[] fetch(Bucket bucket, String key) throws IOException { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ - public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException { + public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException { if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " @@ -125,14 +126,21 @@ public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOEx * @param resp * @return */ - private RiakObject[] handleBodyResponse(Bucket bucket, WithBodyResponse resp) { + private RiakResponse handleBodyResponse(Bucket bucket, WithBodyResponse resp) { + RiakResponse response = RiakResponse.empty(); + RiakObject[] values = new RiakObject[] {}; + if (resp.hasSiblings()) { - return convert(resp.getSiblings(), bucket); + values = convert(resp.getSiblings(), bucket); } else if (resp.hasObject()) { - return new RiakObject[] { convert(resp.getObject(), bucket) }; - } else { - return new RiakObject[] {}; + values = new RiakObject[] { convert(resp.getObject(), bucket) }; + } + + if (values.length > 0) { + response = new RiakResponse(resp.getObject().getVclock().getBytes(), values); } + + return response; } /** @@ -159,6 +167,7 @@ private RiakObject convert(final com.basho.riak.client.RiakObject o, final Bucke RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); builder.withValue(o.getValue()); + System.out.println("VClock into new riak object " + o.getVclock()); builder.withVClock(nullSafeGetBytes(o.getVclock())); builder.withVtag(o.getVtag()); @@ -212,29 +221,28 @@ private byte[] nullSafeGetBytes(String vclock) { * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ - public RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOException { - if(object == null || object.getBucket() == null) { + public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOException { + if (object == null || object.getBucket() == null) { throw new IllegalArgumentException("cannot store a null RiakObject, or a RiakObject without a bucket"); } final Bucket bucket = object.getBucket(); - - RiakObject[] result = new RiakObject[] {}; - + RiakResponse response = RiakResponse.empty(); + com.basho.riak.client.RiakObject riakObject = convert(object); RequestMeta requestMeta = convert(storeMeta); StoreResponse resp = client.store(riakObject, requestMeta); - - if(resp.isSuccess()) { + + if (resp.isSuccess()) { riakObject.updateMeta(resp); } else { throw new IOException(resp.getBodyAsString()); } - - if(storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { - result = handleBodyResponse(bucket, resp); - } - return result; + if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { + response = handleBodyResponse(bucket, resp); + } + + return response; } /** @@ -243,13 +251,13 @@ public RiakObject[] store(RiakObject object, StoreMeta storeMeta) throws IOExcep */ private RequestMeta convert(StoreMeta storeMeta) { RequestMeta requestMeta = RequestMeta.writeParams(storeMeta.getW(), storeMeta.getDw()); - - if(storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { + + if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(true)); } else { requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(false)); } - + return requestMeta; } @@ -259,6 +267,8 @@ private RequestMeta convert(StoreMeta storeMeta) { */ private com.basho.riak.client.RiakObject convert(RiakObject object) { + System.out.println("Vclock out of new object " + object.getVClockAsString()); + com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( client, object.getBucketName(), @@ -278,7 +288,7 @@ private com.basho.riak.client.RiakObject convert(RiakObject object) { * @return */ private String formatDate(Date lastModified) { - if(lastModified == null) { + if (lastModified == null) { return null; } return DateUtil.formatDate(lastModified); @@ -339,10 +349,10 @@ public void store(RiakObject object) throws IOException { * .Bucket, java.lang.String) */ public void delete(Bucket bucket, String key) throws IOException { - HttpResponse resp = client.delete(bucket.getName(), key); - if(!resp.isSuccess()) { - throw new IOException(resp.getBodyAsString()); - } + HttpResponse resp = client.delete(bucket.getName(), key); + if (!resp.isSuccess()) { + throw new IOException(resp.getBodyAsString()); + } } /* @@ -354,7 +364,7 @@ public void delete(Bucket bucket, String key) throws IOException { */ public void delete(Bucket bucket, String key, int deleteQuorum) throws IOException { HttpResponse resp = client.delete(bucket.getName(), key, RequestMeta.deleteParams(deleteQuorum)); - if(!resp.isSuccess()) { + if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } } diff --git a/src/main/java/com/basho/riak/client/raw/http/KeySource.java b/src/main/java/com/basho/riak/client/raw/http/KeySource.java index 5ccecd98c..42e7b107d 100644 --- a/src/main/java/com/basho/riak/client/raw/http/KeySource.java +++ b/src/main/java/com/basho/riak/client/raw/http/KeySource.java @@ -21,9 +21,8 @@ import com.basho.riak.client.response.BucketResponse; /** - * Wraps the stream of keys from BucketResponse.getBucketInfo.getKeys - * in an iterator that handles closing the underlying http stream - * when finished with. + * Wraps the stream of keys from BucketResponse.getBucketInfo.getKeys in an + * iterator that handles closing the underlying http stream when finished with. * * @author russell * diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index 225b61e84..fe357ef49 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -14,13 +14,12 @@ package com.basho.riak.client.raw.pbc; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.Map.Entry; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; @@ -61,7 +60,7 @@ public PBClientAdapter(String host, int port) throws IOException { * @see com.basho.riak.client.raw.RawClient#fetch(java.lang.String, * java.lang.String) */ - public RiakObject[] fetch(Bucket bucket, String key) throws IOException { + public RiakResponse fetch(Bucket bucket, String key) throws IOException { if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " @@ -81,7 +80,7 @@ public RiakObject[] fetch(Bucket bucket, String key) throws IOException { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ - public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOException { + public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException { if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " @@ -98,16 +97,18 @@ public RiakObject[] fetch(Bucket bucket, String key, int readQuorum) throws IOEx * @param fetch * @return */ - private RiakObject[] convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { - Collection converted = new ArrayList(); + private RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { + RiakResponse response = RiakResponse.empty(); - if (pbcObjects != null) { - for (com.basho.riak.pbc.RiakObject o : pbcObjects) { - converted.add(convert(o, bucket)); + if (pbcObjects != null && pbcObjects.length > 0) { + RiakObject[] converted = new RiakObject[pbcObjects.length]; + for (int i = 0; i < pbcObjects.length; i++) { + converted[i] = convert(pbcObjects[i], bucket); } + response = new RiakResponse(pbcObjects[0].getVclock().toByteArray(), converted); } - return converted.toArray(new RiakObject[converted.size()]); + return response; } /** @@ -157,7 +158,7 @@ private ByteString nullSafeToByteString(String value) { * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ - public RiakObject[] store(RiakObject riakObject, StoreMeta storeMeta) throws IOException { + public RiakResponse store(RiakObject riakObject, StoreMeta storeMeta) throws IOException { if (riakObject == null || riakObject.getKey() == null || riakObject.getBucket() == null) { throw new IllegalArgumentException( "object cannot be null, object's key cannot be null, object's bucket cannot be null"); @@ -323,7 +324,7 @@ public Iterable listKeys(String bucketName) throws IOException { if (bucketName == null || bucketName.trim().equals("")) { throw new IllegalArgumentException("bucketName cannot be null, empty or all whitespace"); } - + final KeySource keySource = client.listKeys(ByteString.copyFromUtf8(bucketName)); final Iterator i = new Iterator() { diff --git a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java index 15aaf745c..fb80ae81b 100644 --- a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java +++ b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java @@ -15,7 +15,7 @@ /** * @author russell - * + * */ public interface LinkWalkSpec { diff --git a/src/main/java/com/basho/riak/newapi/DefaultClient.java b/src/main/java/com/basho/riak/newapi/DefaultClient.java index bc2c4bb48..f570fe1ed 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultClient.java +++ b/src/main/java/com/basho/riak/newapi/DefaultClient.java @@ -13,7 +13,7 @@ /** * @author russell - * + * */ public final class DefaultClient implements RiakClient { /** @@ -72,7 +72,7 @@ public byte[] execute() throws IOException { return client.generateAndSetClientId(); } }, 3); - + return clientId; } @@ -82,7 +82,7 @@ public byte[] execute() throws IOException { return client.getClientId(); } }, 3); - + return clientId; } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java index aaeab4bb7..4107c29bc 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -31,9 +31,9 @@ * */ public class DefaultRiakObject implements RiakObject { - + public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; - + private final Bucket bucket; @RiakKey private final String key; private final VClock vclock; diff --git a/src/main/java/com/basho/riak/newapi/RiakClient.java b/src/main/java/com/basho/riak/newapi/RiakClient.java index 866d04d41..2b00e154f 100644 --- a/src/main/java/com/basho/riak/newapi/RiakClient.java +++ b/src/main/java/com/basho/riak/newapi/RiakClient.java @@ -24,11 +24,11 @@ * */ public interface RiakClient { - + RiakClient setClientId(byte[] clientId) throws RiakException; - + byte[] generateAndSetClientId() throws RiakException; - + byte[] getClientId() throws RiakException; FetchBucket fetchBucket(String bucketName); diff --git a/src/main/java/com/basho/riak/newapi/RiakException.java b/src/main/java/com/basho/riak/newapi/RiakException.java index 4755918b8..9784fc302 100644 --- a/src/main/java/com/basho/riak/newapi/RiakException.java +++ b/src/main/java/com/basho/riak/newapi/RiakException.java @@ -34,7 +34,7 @@ public RiakException(Throwable e) { public RiakException() { super(); } - + public RiakException(String message) { super(message); } diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java index ebb1c723e..681790702 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -51,4 +51,12 @@ public static RiakClient httpClient() throws RiakException { return new DefaultClient(client); } + /** + * @return a wrapped RiakClient + */ + public static RiakClient httpClient(com.basho.riak.client.RiakClient delegate) throws RiakException { + final RawClient client = new HTTPClientAdapter(delegate); + return new DefaultClient(client); + } + } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java index ff0a8713f..73089dd80 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -13,6 +13,7 @@ */ package com.basho.riak.newapi; +import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.Map.Entry; @@ -43,6 +44,8 @@ public interface RiakObject extends Iterable { String getContentType(); // links + Collection getLinks(); + boolean hasLinks(); int numLinks(); @@ -57,7 +60,7 @@ public interface RiakObject extends Iterable { boolean hasUsermeta(String key); String getUsermeta(String key); - + Iterable> userMetaEntries(); // Mutate diff --git a/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java b/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java index 4f586ca8b..7ae0770e9 100644 --- a/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java +++ b/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java @@ -15,7 +15,7 @@ /** * @author russell - * + * */ public class RiakRetryFailedException extends RiakException { diff --git a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java index be342d3bb..81d0a6f50 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java @@ -19,7 +19,6 @@ import com.basho.riak.newapi.operations.FetchObject; import com.basho.riak.newapi.operations.StoreObject; - /** * @author russell * @@ -27,22 +26,22 @@ public interface Bucket extends BucketProperties { String getName(); - + StoreObject store(String key, String value); StoreObject store(T o); - + StoreObject store(String key, T o); FetchObject fetch(String key); - + FetchObject fetch(String key, Class type); - + FetchObject fetch(T o); DeleteObject delete(T o); - + DeleteObject delete(String key); - + Iterable keys() throws RiakException; } diff --git a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java index 855b2bdfe..aeff029e3 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java +++ b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java @@ -21,11 +21,10 @@ /** * @author russell - * + * */ public interface BucketProperties { - /** * @return the allowSiblings if set, or null if not */ diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index c772306b8..6cf71927b 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -25,6 +25,8 @@ import com.basho.riak.newapi.cap.DefaultResolver; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.Quorum; +import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.ConversionException; import com.basho.riak.newapi.convert.Converter; import com.basho.riak.newapi.convert.JSONConverter; import com.basho.riak.newapi.convert.NoKeySpecifedException; @@ -245,7 +247,7 @@ public RiakObject toDomain(RiakObject riakObject) { return riakObject; } - public RiakObject fromDomain(RiakObject domainObject) { + public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { return domainObject; } }); @@ -260,18 +262,16 @@ public StoreObject store(final T o) { final Bucket b = this; @SuppressWarnings("unchecked") Class clazz = (Class) o.getClass(); final String key = getKey(o); - if(key == null) { + if (key == null) { throw new NoKeySpecifedException(o); } - return new StoreObject(client, b, key) - .withConverter(new JSONConverter(clazz, b)) - .withMutator(new Mutation() { - public T apply(T original) { - return o; - }; - }).withResolver(new DefaultResolver()); + return new StoreObject(client, b, key).withConverter(new JSONConverter(clazz, b)).withMutator(new Mutation() { + public T apply(T original) { + return o; + }; + }).withResolver(new DefaultResolver()); } - + /* * (non-Javadoc) * @@ -281,14 +281,12 @@ public T apply(T original) { public StoreObject store(final String key, final T o) { final Bucket b = this; @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); - - return new StoreObject(client, b, key) - .withConverter(new JSONConverter(clazz, b, key)) - .withMutator(new Mutation() { - public T apply(T original) { - return o; - }; - }).withResolver(new DefaultResolver()); + + return new StoreObject(client, b, key).withConverter(new JSONConverter(clazz, b, key)).withMutator(new Mutation() { + public T apply(T original) { + return o; + }; + }).withResolver(new DefaultResolver()); } /* @@ -300,15 +298,12 @@ public FetchObject fetch(T o) { final Bucket b = this; @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); final String key = getKey(o); - if(key == null) { + if (key == null) { throw new NoKeySpecifedException(o); } - return new FetchObject(client, this, key) - .withConverter(new JSONConverter(clazz, b)) - .withResolver(new DefaultResolver()); + return new FetchObject(client, this, key).withConverter(new JSONConverter(clazz, b)).withResolver(new DefaultResolver()); } - /* * (non-Javadoc) * @@ -317,30 +312,29 @@ public FetchObject fetch(T o) { */ public FetchObject fetch(final String key, final Class type) { final Bucket b = this; - return new FetchObject(client, this, key) - .withConverter(new JSONConverter(type, b)) - .withResolver(new DefaultResolver()); + return new FetchObject(client, this, key).withConverter(new JSONConverter(type, b)).withResolver(new DefaultResolver()); } - - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) */ public FetchObject fetch(String key) { final Bucket b = this; - - return new FetchObject(client, b, key) - .withResolver(new DefaultResolver()) - .withConverter(new Converter() { - public RiakObject toDomain(RiakObject riakObject) { - return riakObject; - } + return new FetchObject(client, b, key).withResolver(new DefaultResolver()).withConverter(new Converter() { - public RiakObject fromDomain(RiakObject domainObject) { - return domainObject; - } - }); + public RiakObject toDomain(RiakObject riakObject) { + return riakObject; + } + + public RiakObject fromDomain(RiakObject domainObject, + VClock vclock) + throws ConversionException { + return RiakObjectBuilder.from(domainObject).withVClock(vclock).build(); + } + }); } /* @@ -350,13 +344,12 @@ public RiakObject fromDomain(RiakObject domainObject) { */ public DeleteObject delete(T o) { final String key = getKey(o); - if(key == null) { + if (key == null) { throw new NoKeySpecifedException(o); } return new DeleteObject(client, this, key); } - /* * (non-Javadoc) * @@ -366,5 +359,4 @@ public DeleteObject delete(String key) { return new DeleteObject(client, this, key); } - } diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java index 94c76b785..ff10d6c95 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -51,7 +51,14 @@ public static RiakObjectBuilder newBuilder(Bucket bucket, String key) { } public static RiakObjectBuilder from(RiakObject o) { - return new RiakObjectBuilder(o.getBucket(), o.getKey()); + RiakObjectBuilder rob = new RiakObjectBuilder(o.getBucket(), o.getKey()); + rob.vclock = o.getVClock(); + rob.contentType = o.getContentType(); + rob.lastModified = o.getLastModified(); + rob.value = o.getValue(); + rob.links = o.getLinks(); + rob.userMeta = o.getMeta(); + return rob; } public RiakObject build() { @@ -92,4 +99,13 @@ public RiakObjectBuilder withContentType(String contentType) { this.contentType = contentType; return this; } + + /** + * @param vclock + * @return + */ + public RiakObjectBuilder withVClock(VClock vclock) { + this.vclock = vclock; + return this; + } } diff --git a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java index 784b1a49a..2f6e34b3e 100644 --- a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java @@ -31,7 +31,7 @@ public BasicVClock(final byte[] value) { public byte[] getBytes() { return value.clone(); } - + public String asString() { return new String(value); } diff --git a/src/main/java/com/basho/riak/newapi/cap/CAP.java b/src/main/java/com/basho/riak/newapi/cap/CAP.java index 6c79a4b91..16435573b 100644 --- a/src/main/java/com/basho/riak/newapi/cap/CAP.java +++ b/src/main/java/com/basho/riak/newapi/cap/CAP.java @@ -15,7 +15,7 @@ /** * @author russell - * + * */ public enum CAP { ALL, ONE, QUORUM; diff --git a/src/main/java/com/basho/riak/newapi/cap/ClientId.java b/src/main/java/com/basho/riak/newapi/cap/ClientId.java index 3e103eb97..ccdbe84eb 100644 --- a/src/main/java/com/basho/riak/newapi/cap/ClientId.java +++ b/src/main/java/com/basho/riak/newapi/cap/ClientId.java @@ -19,13 +19,13 @@ /** * @author russell - * + * */ public class ClientId { static SecureRandom rnd = new SecureRandom(); - - /** + + /** * @return a generated client id */ public static byte[] generate() { diff --git a/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java b/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java index 5f418c543..8e70235a3 100644 --- a/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java +++ b/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java @@ -17,10 +17,10 @@ /** * @author russell - * + * */ public interface ConflictResolver { T resolve(final Collection siblings) throws UnresolvedConflictException; - + } diff --git a/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java b/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java index 1325b9c6d..e18a682e2 100644 --- a/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java +++ b/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java @@ -2,10 +2,9 @@ import java.util.Collection; - /** - * A conflict resolver that doesn't resolve conflict. - * If it is presented with a collection of siblings it throws. + * A conflict resolver that doesn't resolve conflict. If it is presented with a + * collection of siblings it throws. * * @author russell * diff --git a/src/main/java/com/basho/riak/newapi/cap/Mutation.java b/src/main/java/com/basho/riak/newapi/cap/Mutation.java index 505286dd6..dc1d86396 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Mutation.java +++ b/src/main/java/com/basho/riak/newapi/cap/Mutation.java @@ -13,17 +13,18 @@ */ package com.basho.riak.newapi.cap; - /** * Interface for a mutation. * * @author russell - * + * */ public interface Mutation { /** * Applies a mutation to the "original" value passed in - * @param original the value to mutate. + * + * @param original + * the value to mutate. * @return the mutated value. */ T apply(T original); diff --git a/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java b/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java index bb0bb561b..6c1f10059 100644 --- a/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java +++ b/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java @@ -14,10 +14,12 @@ package com.basho.riak.newapi.cap; /** - * Maybe you want to produce a mutation at will? Say if you are using a domain bucket? + * Maybe you want to produce a mutation at will? Say if you are using a domain + * bucket? + * * @author russell * @param - * + * */ public interface MutationProducer { Mutation produce(T o); diff --git a/src/main/java/com/basho/riak/newapi/cap/Quorum.java b/src/main/java/com/basho/riak/newapi/cap/Quorum.java index ddcf34196..a8b913f86 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Quorum.java +++ b/src/main/java/com/basho/riak/newapi/cap/Quorum.java @@ -13,7 +13,6 @@ */ package com.basho.riak.newapi.cap; - public final class Quorum { private Integer i; private CAP cap; diff --git a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java index 9e387d750..b358f5436 100644 --- a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java +++ b/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java @@ -27,7 +27,7 @@ public class UnresolvedConflictException extends RiakException { * eclipse generated id */ private static final long serialVersionUID = -219858468775752064L; - + private final String reason; private final Collection siblings; diff --git a/src/main/java/com/basho/riak/newapi/cap/VClock.java b/src/main/java/com/basho/riak/newapi/cap/VClock.java index 0b1a79287..fcc7722b5 100644 --- a/src/main/java/com/basho/riak/newapi/cap/VClock.java +++ b/src/main/java/com/basho/riak/newapi/cap/VClock.java @@ -13,7 +13,6 @@ */ package com.basho.riak.newapi.cap; - /** * @author russell * diff --git a/src/main/java/com/basho/riak/newapi/convert/Converter.java b/src/main/java/com/basho/riak/newapi/convert/Converter.java index 612806c32..f5b7ba28d 100644 --- a/src/main/java/com/basho/riak/newapi/convert/Converter.java +++ b/src/main/java/com/basho/riak/newapi/convert/Converter.java @@ -14,6 +14,7 @@ package com.basho.riak.newapi.convert; import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.cap.VClock; /** * @author russell @@ -22,15 +23,18 @@ public interface Converter { /** - * Convert from domain specific type to RiakObject + * Convert from domain specific type to RiakObject + * * @param domainObject * @return a RiakObject populated from domainObject */ - RiakObject fromDomain(T domainObject) throws ConversionException; + RiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException; /** * Convert from a riakObject to a domain specific instance - * @param riakObject the RiakObject to convert + * + * @param riakObject + * the RiakObject to convert * @return an instance of type T */ T toDomain(RiakObject riakObject) throws ConversionException; diff --git a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java index 8caed9101..61f6c0c07 100644 --- a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java +++ b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java @@ -24,6 +24,7 @@ import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; /** * Converts a RiakObject's value to an instance of T. T must have a field @@ -57,12 +58,13 @@ public JSONConverter(Class clazz, Bucket b, String defaultKey) { /* * (non-Javadoc) * - * @see com.basho.riak.newapi.convert.Converter#fromDomain(java.lang.Object) + * @see com.basho.riak.newapi.convert.Converter#fromDomain(java.lang.Object, + * VClock) */ - public RiakObject fromDomain(T domainObject) throws ConversionException { + public RiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException { try { String key = getKey(domainObject, this.defaultKey); - + if (key == null) { throw new NoKeySpecifedException(domainObject); } @@ -70,7 +72,7 @@ public RiakObject fromDomain(T domainObject) throws ConversionException { final StringWriter sw = new StringWriter(); objectMapper.writeValue(sw, domainObject); - return RiakObjectBuilder.newBuilder(bucket, key).withValue(sw.toString()).build(); + return RiakObjectBuilder.newBuilder(bucket, key).withValue(sw.toString()).withVClock(vclock).build(); } catch (JsonProcessingException e) { throw new ConversionException(e); } catch (IOException e) { diff --git a/src/main/java/com/basho/riak/newapi/convert/RiakKey.java b/src/main/java/com/basho/riak/newapi/convert/RiakKey.java index dc4d6faf7..fbffeaea9 100644 --- a/src/main/java/com/basho/riak/newapi/convert/RiakKey.java +++ b/src/main/java/com/basho/riak/newapi/convert/RiakKey.java @@ -22,10 +22,8 @@ * Annotation to declare a field as the key to a data item in Riak. * * @author russell - * + * */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface RiakKey { +@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface RiakKey { } diff --git a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java index e00e67ee5..bb4f071ce 100644 --- a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java @@ -53,7 +53,7 @@ public DeleteObject(RawClient client, Bucket bucket, String key) { public Void execute() throws RiakRetryFailedException { Command command = new Command() { public Void execute() throws IOException { - if(rw == null) { + if (rw == null) { client.delete(bucket, key); } else { client.delete(bucket, key, rw); @@ -61,7 +61,7 @@ public Void execute() throws IOException { return null; } }; - + new DefaultRetrier().attempt(command, retries); return null; } diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java index 7405af77c..49ab31f0e 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -20,6 +20,7 @@ import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.Bucket; @@ -61,8 +62,8 @@ public FetchObject(final RawClient client, final Bucket bucket, final String key */ public T execute() throws UnresolvedConflictException, RiakRetryFailedException, ConversionException { // fetch, resolve - Command command = new Command() { - public RiakObject[] execute() throws IOException { + Command command = new Command() { + public RiakResponse execute() throws IOException { if (r != null) { return client.fetch(bucket, key, r); } else { @@ -71,8 +72,8 @@ public RiakObject[] execute() throws IOException { } }; - final RiakObject[] ros = new DefaultRetrier().attempt(command, retries); - final Collection siblings = new ArrayList(ros.length); + final RiakResponse ros = new DefaultRetrier().attempt(command, retries); + final Collection siblings = new ArrayList(ros.numberOfValues()); for (RiakObject o : ros) { siblings.add(converter.toDomain(o)); diff --git a/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java b/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java index 7aa3521b6..7cb1c36aa 100644 --- a/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java +++ b/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java @@ -17,10 +17,10 @@ /** * @author russell - * + * */ public interface RiakOperation { - + T execute() throws RiakException; } diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index c738d855c..cf6efa9a6 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -20,6 +20,7 @@ import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; @@ -44,6 +45,8 @@ public class StoreObject implements RiakOperation { private final RawClient client; private final Bucket bucket; + // TODO populate + private Integer r; private Integer w; private Integer dw; private boolean returnBody = false; @@ -67,23 +70,34 @@ public StoreObject(final RawClient client, Bucket bucket, String key) { */ public T execute() throws RiakRetryFailedException, UnresolvedConflictException, ConversionException { // fetch, mutate, put - - final T resolved = new FetchObject(client, bucket, key) - .retry(retries) - .withConverter(converter) - .withResolver(resolver) - .execute(); + Command command = new Command() { + public RiakResponse execute() throws IOException { + if (r != null) { + return client.fetch(bucket, key, r); + } else { + return client.fetch(bucket, key); + } + } + }; + + final RiakResponse ros = new DefaultRetrier().attempt(command, retries); + final Collection siblings = new ArrayList(ros.numberOfValues()); + + for (RiakObject o : ros) { + siblings.add(converter.toDomain(o)); + } + final T resolved = resolver.resolve(siblings); final T mutated = mutation.apply(resolved); - final RiakObject o = converter.fromDomain(mutated); + final RiakObject o = converter.fromDomain(mutated, ros.getVclock()); - final RiakObject[] stored = new DefaultRetrier().attempt(new Command() { - public RiakObject[] execute() throws IOException { + final RiakResponse stored = new DefaultRetrier().attempt(new Command() { + public RiakResponse execute() throws IOException { return client.store(o, generateStoreMeta()); } }, retries); - final Collection storedSiblings = new ArrayList(stored.length); + final Collection storedSiblings = new ArrayList(stored.numberOfValues()); for (RiakObject s : stored) { storedSiblings.add(converter.toDomain(s)); diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduce.java b/src/main/java/com/basho/riak/newapi/query/MapReduce.java index 0df9d279c..f1f4ac9a8 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduce.java +++ b/src/main/java/com/basho/riak/newapi/query/MapReduce.java @@ -16,18 +16,19 @@ import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.operations.RiakOperation; - /** * @author russell - * + * */ -public class MapReduce implements RiakOperation{ +public class MapReduce implements RiakOperation { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.basho.riak.client.RiakOperation#execute() */ public MapReduceResult execute() throws RiakException { return null; } - + } diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java index e388d5641..c7c101b6c 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java +++ b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java @@ -25,8 +25,9 @@ public interface MapReduceResult { /** * Mapped results to a simple java type * - * @param - * @param resultType A Java type to map the result too. + * @param + * @param resultType + * A Java type to map the result too. * @return a Collection of T. */ Collection getResult(T resultType); diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java b/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java index 071f20dd3..9fb0fd6da 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java +++ b/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java @@ -13,12 +13,11 @@ */ package com.basho.riak.newapi.query; - /** * A Map Reduce Query run it via {@link RiakClient#mapReduce(MapReduceSpec)} * * @author russell - * + * */ public class MapReduceSpec { diff --git a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java index bdef33610..a6f69f1cc 100644 --- a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java @@ -50,7 +50,9 @@ public String getFun() { return fun; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { @@ -61,7 +63,9 @@ public String getFun() { return result; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { @@ -92,11 +96,13 @@ public String getFun() { return true; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#toString() */ @Override public String toString() { return String.format("NamedErlangFunction [mod=%s, fun=%s]", mod, fun); } - + } diff --git a/src/main/java/com/basho/riak/newapi/query/NamedFunction.java b/src/main/java/com/basho/riak/newapi/query/NamedFunction.java index 6827726e7..a3cea6951 100644 --- a/src/main/java/com/basho/riak/newapi/query/NamedFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/NamedFunction.java @@ -17,7 +17,7 @@ * Tag interface. * * @author russell - * + * */ public interface NamedFunction { diff --git a/src/main/java/com/basho/riak/newapi/query/WalkResult.java b/src/main/java/com/basho/riak/newapi/query/WalkResult.java index b3b3256f4..d466841bc 100644 --- a/src/main/java/com/basho/riak/newapi/query/WalkResult.java +++ b/src/main/java/com/basho/riak/newapi/query/WalkResult.java @@ -20,7 +20,7 @@ /** * * @author russell - * + * */ -public interface WalkResult extends Iterable>{ +public interface WalkResult extends Iterable> { } diff --git a/src/test/java/com/basho/riak/client/BasicOperations.java b/src/test/java/com/basho/riak/client/BasicOperations.java deleted file mode 100644 index 9a8dcaea4..000000000 --- a/src/test/java/com/basho/riak/client/BasicOperations.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Collection; - -import org.junit.Test; - -import com.basho.riak.newapi.RiakClient; -import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.cap.CAP; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.Mutation; -import com.basho.riak.newapi.cap.UnresolvedConflictException; -import com.basho.riak.newapi.query.NamedErlangFunction; -import com.megacorp.kv.exceptions.BailException; -import com.megacorp.kv.exceptions.MyCheckedBusinessException; - -/** - * @author russell - * - */ -public class BasicOperations { - - @Test public void basicOpertaions() throws Exception { - final RiakClient c = RiakFactory.pbcClient(); - - c.createBucket("testBucket").retry(2).nVal(3).execute(); - - Bucket b = c.fetchBucket("bucket").retry(1).fetchKeys(false).fetchProperties(true).execute(); - - assertEquals(new Integer(3), b.getNVal()); - assertEquals("bucket", b.getName()); - - b = c.updateBucket(b).r(CAP.QUORUM).w(CAP.ALL).dw(CAP.ONE).rw(2) - .nVal(5) - .allowSiblings(true) - .chashKeyFunction(new NamedErlangFunction("keys", "hash")) - .execute(); - - assertEquals(new Integer(5), b.getNVal()); - assertTrue(b.getAllowSiblings()); - assertEquals(2, b.getRW()); - - // most simple store - b.store("k", "v").execute(); - - // most simple fetch - RiakObject o = b.fetch("k", RiakObject.class).execute(); - - assertEquals("v", o.getValue()); - - try { - b.fetch("k", RiakObject.class).r(1).withResolver(new ConflictResolver() { - public RiakObject resolve(Collection siblings) throws UnresolvedConflictException { - throw new UnresolvedConflictException("meh", siblings); - }}).execute(); - fail("Expected UnresolvedConflictException"); - } catch (UnresolvedConflictException e) { - assertEquals("meh", e.getReason()); - throw new MyCheckedBusinessException(e); - } catch(RiakRetryFailedException e) { - throw new BailException(e); - } - - // update value - o = b.store(o) - .w(3).dw(1) - .returnBody(true) - .retry(3) - .withMutator(new Mutation() { - public RiakObject apply(RiakObject value) { - return value.setValue("my new value"); - }}) - .withResolver(new ConflictResolver() { - - public RiakObject resolve(Collection siblings) - throws UnresolvedConflictException { - return siblings.iterator().next(); - }}) - .execute(); - - - assertEquals("new value", o.getValue()); - - o = b.fetch(o).execute(); - - //with default clobber mutator - b.store(o).withValue(o.setValue("new value")).execute(); - - b.delete(o).rw(3).retry(2).execute(); - - o = b.fetch(o).execute(); - - assertNull(o); - } -} diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index 9db531371..c02fa241b 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -21,7 +21,9 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; @@ -205,6 +207,44 @@ public Boolean call() throws RiakException { assertNull(carts.fetch(userId).execute()); } + @Test public void storeMap() throws Exception { + final String bucketName = UUID.randomUUID().toString() + "_maps"; + final String key = UUID.randomUUID().toString(); + + final Bucket maps = client.createBucket(bucketName).allowSiblings(true).execute(); + + final Map myMap = new HashMap(); + myMap.put("size", "s"); + myMap.put("colour", "red"); + myMap.put("style", "short-sleeve"); + + maps.store(key, myMap).returnBody(false).w(2).execute(); + + @SuppressWarnings("unchecked") final Map fetchedMap = maps.fetch(key, Map.class).execute(); + + assertEquals(myMap, fetchedMap); + } + + @Test public void storeList() throws Exception { + final String bucketName = UUID.randomUUID().toString() + "_lists"; + final String key = UUID.randomUUID().toString(); + + final Bucket lists = client.createBucket(bucketName).allowSiblings(true).execute(); + + final Collection myList = new ArrayList(); + myList.add("red"); + myList.add("yellow"); + myList.add("pink"); + myList.add("green"); + + lists.store(key, myList).returnBody(false).w(2).execute(); + + @SuppressWarnings("unchecked") final Collection fetchedList = lists.fetch(key, Collection.class).execute(); + + assertEquals(myList, fetchedList); + } + + // List Keys @Test public void listKeys() throws Exception { final Set keys = new LinkedHashSet(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java index 91fe2db91..c0183eea2 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java @@ -33,11 +33,10 @@ * */ public abstract class ITestClientBasic { - - protected RiakClient client; - - @Before - public void setUp() throws RiakException { + + protected RiakClient client; + + @Before public void setUp() throws RiakException { this.client = getClient(); } @@ -56,7 +55,7 @@ public void setUp() throws RiakException { assertEquals(new Integer(3), b.getNVal()); assertFalse(b.getAllowSiblings()); } - + @Test public void updateBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); @@ -66,15 +65,15 @@ public void setUp() throws RiakException { assertEquals(bucketName, b.getName()); assertEquals(new Integer(3), b.getNVal()); assertFalse(b.getAllowSiblings()); - + b = client.updateBucket(b).nVal(4).allowSiblings(true).execute(); - + assertNotNull(b); assertEquals(bucketName, b.getName()); assertEquals(new Integer(4), b.getNVal()); assertTrue(b.getAllowSiblings()); } - + @Test public void createBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); @@ -88,12 +87,12 @@ public void setUp() throws RiakException { @Test public void clientIds() throws Exception { final byte[] clientId = "abcd".getBytes("UTF-8"); - + client.setClientId(clientId.clone()); assertArrayEquals(clientId, client.getClientId()); - + byte[] newId = client.generateAndSetClientId(); - + assertArrayEquals(newId, client.getClientId()); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java index e7bc73618..04c56ec84 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java @@ -25,12 +25,14 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.DomainBucket; -import com.megacorp.commerce.MergeResolver; +import com.megacorp.commerce.MergeCartResolver; import com.megacorp.commerce.ShoppingCart; /** @@ -40,23 +42,25 @@ * @author russell * */ -public class ITestDomainBucket { +public abstract class ITestDomainBucket { + + protected RiakClient client; + + @Before public void setUp() throws RiakException { + this.client = getClient(); + } + + public abstract RiakClient getClient() throws RiakException; @Test public void useDomainBucket() throws Exception { final String bucketName = UUID.randomUUID().toString() + "_carts"; final String userId = UUID.randomUUID().toString(); - final Bucket b = RiakFactory.pbcClient().createBucket(bucketName).allowSiblings(true).nVal(3).execute(); + client.generateAndSetClientId(); + + final Bucket b = client.createBucket(bucketName).allowSiblings(true).nVal(3).execute(); - final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class) - .withResolver(new MergeResolver()) - .returnBody(true) - .retry(3) - .w(1) - .dw(1) - .r(1) - .rw(1) - .build(); + final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class).withResolver(new MergeCartResolver()).returnBody(true).retry(3).w(1).dw(1).r(1).rw(1).build(); final ShoppingCart cart = new ShoppingCart(userId); @@ -97,6 +101,7 @@ public ShoppingCart call() throws Exception { "bowtie" }; final ShoppingCart finalCart = carts.fetch(userId); + assertTrue(finalCart.hasAll(Arrays.asList(expectedMergesCart))); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java new file mode 100644 index 000000000..a41310a17 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java @@ -0,0 +1,39 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestDomainBucketHTTP extends ITestDomainBucket { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestDomainBucket#getClient() + */ + @Override public RiakClient getClient() throws RiakException { + // com.basho.riak.client.RiakClient riakClient = new + // com.basho.riak.client.RiakClient("http://127.0.0.1:8098/riak"); + // riakClient.getHttpClient().getHostConfiguration().setProxy("127.0.0.1", + // 8008); + return RiakFactory.httpClient(); + } + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java new file mode 100644 index 000000000..04bc3f589 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java @@ -0,0 +1,35 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestDomainBucketPB extends ITestDomainBucket { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestDomainBucket#getClient() + */ + @Override public RiakClient getClient() throws RiakException { + return RiakFactory.pbcClient(); + } + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java index 17c7f1e93..b9b27200c 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java @@ -30,15 +30,17 @@ * */ public class ITestHTTPClient extends ITestClientBasic { - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see com.basho.riak.client.itest.ITestClient#getClient() */ @Override protected RiakClient getClient() throws RiakException { return RiakFactory.httpClient(); } - - @Test public void fetchBucket() throws RiakException { + + @Test public void fetchBucket() throws RiakException { super.fetchBucket(); final String bucketName = UUID.randomUUID().toString(); @@ -47,41 +49,40 @@ public class ITestHTTPClient extends ITestClientBasic { assertEquals(new NamedErlangFunction("riak_core_util", "chash_std_keyfun"), b.getChashKeyFunction()); assertEquals(new NamedErlangFunction("riak_kv_wm_link_walker", "mapreduce_linkfun"), b.getLinkWalkFunction()); } - + @Test public void updateBucket() throws RiakException { final NamedErlangFunction newChashkeyFun = new NamedErlangFunction("riak_core_util", "chash_bucketonly_keyfun"); final NamedErlangFunction newLinkwalkFun = new NamedErlangFunction("riak_core_util", "chash_std_keyfun"); - + super.updateBucket(); - + final String bucketName = UUID.randomUUID().toString(); Bucket b = client.fetchBucket(bucketName).execute(); - b = client.updateBucket(b).chashKeyFunction(newChashkeyFun).linkWalkFunction(newLinkwalkFun).execute(); - + assertEquals(newChashkeyFun, b.getChashKeyFunction()); assertEquals(newLinkwalkFun, b.getLinkWalkFunction()); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.basho.riak.client.itest.ITestClient#createBucket() */ @Override public void createBucket() throws RiakException { super.createBucket(); - + final NamedErlangFunction newChashkeyFun = new NamedErlangFunction("riak_core_util", "chash_bucketonly_keyfun"); final NamedErlangFunction newLinkwalkFun = new NamedErlangFunction("riak_core_util", "chash_std_keyfun"); - + final String bucketName = UUID.randomUUID().toString(); Bucket b = client.createBucket(bucketName).chashKeyFunction(newChashkeyFun).linkWalkFunction(newLinkwalkFun).execute(); - + assertEquals(newChashkeyFun, b.getChashKeyFunction()); assertEquals(newLinkwalkFun, b.getLinkWalkFunction()); } - - } diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java index f4ea90d5a..ea7ec49a1 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java @@ -22,8 +22,10 @@ * */ public class ITestPBClient extends ITestClientBasic { - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see com.basho.riak.client.itest.ITestClient#getClient() */ @Override protected RiakClient getClient() throws RiakException { diff --git a/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java index b285644c6..dc49832b3 100644 --- a/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java +++ b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java @@ -38,7 +38,8 @@ public class TestKeySource { * * @throws Exception */ - @SuppressWarnings({ "unchecked", "unused" }) @Test public void streamIsClosedWhenKeySourceIsWeaklyReachable() throws Exception { + @SuppressWarnings({ "unchecked", "unused" }) @Test public void streamIsClosedWhenKeySourceIsWeaklyReachable() + throws Exception { final BucketResponse bucketResponse = mock(BucketResponse.class); final RiakBucketInfo riakBucketInfo = mock(RiakBucketInfo.class); final Collection keys = mock(Collection.class); diff --git a/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java b/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java index 331c343e7..02b99d21a 100644 --- a/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java +++ b/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java @@ -21,25 +21,27 @@ /** * @author russell - * + * */ public class ClobberMutationTest { /** - * Test method for {@link com.basho.riak.newapi.cap.ClobberMutation#ClobberMutation(java.lang.Object)}. + * Test method for + * {@link com.basho.riak.newapi.cap.ClobberMutation#ClobberMutation(java.lang.Object)} + * . */ @Test public void apply() { final Object oldValue = new Object(); - + ClobberMutation mutation = new ClobberMutation(null); - + assertNull(mutation.apply(oldValue)); - + Object newValue = new Object(); - + assertNotSame(oldValue, newValue); mutation = new ClobberMutation(newValue); - + assertSame(newValue, mutation.apply(new Object())); } diff --git a/src/test/java/com/megacorp/commerce/LegacyCart.java b/src/test/java/com/megacorp/commerce/LegacyCart.java index 1d307a208..5328adde1 100644 --- a/src/test/java/com/megacorp/commerce/LegacyCart.java +++ b/src/test/java/com/megacorp/commerce/LegacyCart.java @@ -62,7 +62,9 @@ public void addItem(String item) { cartItems.add(item); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { @@ -73,7 +75,9 @@ public void addItem(String item) { return result; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { diff --git a/src/test/java/com/megacorp/commerce/MergeResolver.java b/src/test/java/com/megacorp/commerce/MergeCartResolver.java similarity index 74% rename from src/test/java/com/megacorp/commerce/MergeResolver.java rename to src/test/java/com/megacorp/commerce/MergeCartResolver.java index 5aaae8c69..b386bb61c 100644 --- a/src/test/java/com/megacorp/commerce/MergeResolver.java +++ b/src/test/java/com/megacorp/commerce/MergeCartResolver.java @@ -1,7 +1,7 @@ package com.megacorp.commerce; -import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.UnresolvedConflictException; @@ -14,11 +14,11 @@ * @author russell * */ -public final class MergeResolver implements ConflictResolver { - +public final class MergeCartResolver implements ConflictResolver { + public ShoppingCart resolve(Collection siblings) throws UnresolvedConflictException { String userId = null; - final Collection items = new ArrayList(); + final Collection items = new HashSet(); for (ShoppingCart c : siblings) { userId = c.getUserId(); @@ -27,6 +27,8 @@ public ShoppingCart resolve(Collection siblings) throws Unresolved } } + System.out.println("Merged items for " + Thread.currentThread().getName() + " " + items); + final ShoppingCart resolved = new ShoppingCart(userId); return resolved.addItems(items); } From 4ac1fb1be65b5c0a9c4f036c9a36bd9053a77068 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 15 Apr 2011 19:21:33 +0100 Subject: [PATCH 008/764] Update links in README --- README.org | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/README.org b/README.org index d262121da..ff65bc780 100644 --- a/README.org +++ b/README.org @@ -56,21 +56,20 @@ The high level Riak client lets you work with buckets and map reduce. The map reduce/link walking stuff is incomplete so I'll skip that (for now). Have a look at -[[https://github.com/russelldb/riak-api/blob/master/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java][ITestClientBasic]] +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java][ITestClientBasic]] and -[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/RiakClient.java][RiakClient]]. +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/RiakClient.java][RiakClient]]. All Riak access to a riak objects is done through the Bucket interface, the client just creates/updates and fetches buckets. **** Buckets A test is worth a 100 words so have a look at -[[https://github.com/russelldb/riak-api/blob/master/src/test/java/com/basho/riak/client/itest/ITestBucket.java][ITestBucket]] +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestBucket.java][ITestBucket]] and the interface -[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/bucket/Bucket.java][Bucket]] - +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/bucket/Bucket.java][Bucket]] Bucket methods return -[[https://github.com/russelldb/riak-api/blob/master/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java][RiakOperation's]], +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java][RiakOperation's]] which are implemented as fluent builders to save the proliferation of methods that occur when you have a lot of optional arguments. @@ -79,7 +78,7 @@ that occur when you have a lot of optional arguments. A RiakOpertaion is configured and then it is executed. This is how to fetch, store or delete data. It can be configured to be retried N times. By default that N is 0 (IE try once and fail at once.) An operation accepts the parameters -it needs. So A Delete Operation accepts an optional RW param, for example. +it needs. So a [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java][Delete Operation]] accepts an optional RW param, for example. **** Conflict resolution, Mutation and Converstion @@ -87,9 +86,12 @@ it needs. So A Delete Operation accepts an optional RW param, for example. Conflict happens in Dynamo style systems. It is best to have a strategy in mind to deal with it. The strategy is highly dependant on your domain. A classic -example is the shopping cart [see_shopping_cart] , conflicting shopping carts +example is the +[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/megacorp/commerce/ShoppingCart.java][shopping cart]], conflicting shopping carts can be merged by a union of their contents, sure you might reinstate a deleted -toaster but that is better than losing money... See [cart_merger]. +toaster but that is better than losing money... + +See [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/megacorp/commerce/MergeCartResolver.java][MergeCartResolver]]. Both fetch and store make use of a ConflictResolver to handle siblings. The default conflict resolver right now does not resolve conflicts, it blows up with @@ -102,10 +104,10 @@ conflict resolver to either a fetch or a store operation. Since conflict resolution is a very domain specific thing it makes sense to convert the Riak data into a domain specific object before conflict is -resolved. You provide an implementation of the [Converter] interface to any +resolved. You provide an implementation of the [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/convert/Converter.java][Converter]] interface to any fetch/store operation. By default, if you are working with a operation the converter does nothing. If you are working with a generic -operation then there is a basic JSONConverter [link] that is the simplest +operation then there is a basic [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java][JSONConverter]] that is the simplest possible use of [[http://wiki.fasterxml.com/JacksonHome][Jackson JSON converter]]. It will attempt to coherce a RiakObject's JSON payload into a domain class of your chosing. It can also return Map, Collection etc if you are yet to decide on a domain. @@ -123,8 +125,8 @@ again, you don't want to overwrite the existing value with your own new value, so a Mutation that merges the current value with your new value makes sense here. -You provide an implementation of Mutation [link] that accepts the old value -and returns the new value. The default current mutation clobbers the old value, +You provide an implementation of [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/cap/Mutation.java][Mutation]] that accepts the old value +and returns the new value. The [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java][default]] current mutation clobbers the old value, that is it ignores the old value and returns your new value. ***** Fetch then Store All together a Fetch operation now entails @@ -147,11 +149,13 @@ a store If you are working with ShoppingCarts you're working with Shopping Carts. It is a lot of faff providing the Converter, Mutation and ConflictResolver to the - Bucket operation over and over again (see [link to ItestBasicBucket]). So there - are [DomainBuckets]. A DomainBucket is a wrapper around a bucket (you see, + Bucket operation over and over again. So there + are + [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java][Domain Buckets]]. A DomainBucket is a wrapper around a bucket (you see, *another* layer) that is configured at creation time with a ConflictResolver, MutationProvider and a Converter. Thereafter you can work with the DomainBucket - and deal solely with your ShoppingCart. Look at [link_to_itest_domain_bucket] + and deal solely with your ShoppingCart. Look at + [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java][this test]] for an example. There well very soon be a default RiakObject DomainBucket preconfigured with a @@ -188,4 +192,5 @@ testable, resusable classes and DomainBuckets. - Sort out the package names - Stop leaking Jackson annotations - A default RiakObject DomaonBucket (as described above) +- Lots more From d3df4ec30a0ee3b047daf745d17554bc2263377a Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 30 Mar 2011 07:56:25 +0100 Subject: [PATCH 009/764] Add getter for last modified date to pbc RiakObject Add test fetch non-existent key --- src/main/java/com/basho/riak/pbc/RiakObject.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/basho/riak/pbc/RiakObject.java b/src/main/java/com/basho/riak/pbc/RiakObject.java index 94e9237f6..3943e3b23 100644 --- a/src/main/java/com/basho/riak/pbc/RiakObject.java +++ b/src/main/java/com/basho/riak/pbc/RiakObject.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -197,4 +198,19 @@ public void addLink(ByteString tag, ByteString bucket, ByteString key) { links.add(new RiakLink(bucket, key, tag)); } + /** + * @return the lastModified + */ + public Date getLastModified() { + Date d = null; + + if (lastModified != null && lastModifiedUsec != null) { + long mega = lastModified / 1000000; + long milli = lastModified % 1000000; + int usec = lastModifiedUsec / 1000; + d = new Date(Long.valueOf((mega + "" + milli + "" + usec))); + } + return d; + } + } From 1f7abe8bcf3dd1746d046ab274440407af81dd5b Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 30 Mar 2011 22:43:55 +0100 Subject: [PATCH 010/764] Add getter for lastModified to pbc RiakObject add method to add user meta data to pbc RiakObject add tests for both --- .../java/com/basho/riak/pbc/RiakObject.java | 44 ++++++++---- .../com/basho/riak/pbc/TestRiakObject.java | 70 ++++++++++++++++++- .../basho/riak/test/util/ExpectedValues.java | 10 ++- 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/basho/riak/pbc/RiakObject.java b/src/main/java/com/basho/riak/pbc/RiakObject.java index 3943e3b23..41e627d36 100644 --- a/src/main/java/com/basho/riak/pbc/RiakObject.java +++ b/src/main/java/com/basho/riak/pbc/RiakObject.java @@ -43,7 +43,8 @@ public class RiakObject { private String vtag; private String contentEncoding; private String charset; - private Map userMeta; + private Object userMetaDataLock = new Object(); + private Map userMetaData = new LinkedHashMap(); private Integer lastModified; private Integer lastModifiedUsec; @@ -66,15 +67,17 @@ public class RiakObject { this.lastModifiedUsec = new Integer(content.getLastModUsecs()); } - if (content.getUsermetaCount() == 0) { - userMeta = Collections.emptyMap(); - } else { - userMeta = new LinkedHashMap(); + if (content.getUsermetaCount() > 0) { + Map tmpUserMetaData = new LinkedHashMap(); for (int i = 0; i < content.getUsermetaCount(); i++) { RpbPair um = content.getUsermeta(i); - userMeta.put(um.getKey().toStringUtf8(), + tmpUserMetaData.put(um.getKey().toStringUtf8(), str(um.getValue())); } + + synchronized (userMetaDataLock) { + userMetaData.putAll(tmpUserMetaData); + } } } @@ -172,8 +175,14 @@ RpbContent buildContent() { b.setLastModUsecs(lastModifiedUsec); } - if (userMeta != null && !userMeta.isEmpty()) { - for (Map.Entry ent : userMeta.entrySet()) { + final Map tmpUserMetaData = new LinkedHashMap(); + + synchronized (userMetaDataLock) { + tmpUserMetaData.putAll(userMetaData); + } + + if (tmpUserMetaData != null && !tmpUserMetaData.isEmpty()) { + for (Map.Entry ent : tmpUserMetaData.entrySet()) { ByteString key = ByteString.copyFromUtf8(ent.getKey()); com.basho.riak.pbc.RPB.RpbPair.Builder pb = RPB.RpbPair.newBuilder().setKey(key); if (ent.getValue() != null) { @@ -198,6 +207,19 @@ public void addLink(ByteString tag, ByteString bucket, ByteString key) { links.add(new RiakLink(bucket, key, tag)); } + /** + * Add an item to the user meta data for this RiakObject. + * @param key the key of the user meta data item + * @param value the user meta data item + * @return this RiakObject + */ + public RiakObject addUsermetaItem(String key, String value) { + synchronized (userMetaDataLock) { + userMetaData.put(key, value); + } + return this; + } + /** * @return the lastModified */ @@ -205,10 +227,8 @@ public Date getLastModified() { Date d = null; if (lastModified != null && lastModifiedUsec != null) { - long mega = lastModified / 1000000; - long milli = lastModified % 1000000; - int usec = lastModifiedUsec / 1000; - d = new Date(Long.valueOf((mega + "" + milli + "" + usec))); + long t = (lastModified * 1000L ) + (lastModifiedUsec / 100L); + d = new Date(t); } return d; } diff --git a/src/test/java/com/basho/riak/pbc/TestRiakObject.java b/src/test/java/com/basho/riak/pbc/TestRiakObject.java index c6cf4b26e..4a135a959 100644 --- a/src/test/java/com/basho/riak/pbc/TestRiakObject.java +++ b/src/test/java/com/basho/riak/pbc/TestRiakObject.java @@ -16,6 +16,7 @@ import static com.basho.riak.test.util.ExpectedValues.*; import static org.junit.Assert.*; +import java.util.Date; import java.util.UUID; import org.junit.Test; @@ -91,7 +92,24 @@ public class TestRiakObject { assertEquals(content, riakObject.buildContent()); } - @Test public void setContenType() { + @Test public void addUserMetaDataItem() { + final String[] userMetaKeys = { "MetaKey1", "MetaKey2" }; + final String[] userMetaValues = { "MetaValue1", "MetaValue2" }; + + final RiakObject riakObject = new RiakObject(BUCKET, KEY, CONTENT); + final RpbContent.Builder contentBuilder = RpbContent.newBuilder(); + + contentBuilder.addAllUsermeta(rpbPairs(userMetaKeys, userMetaValues)).setValue(BS_CONTENT); + + final RpbContent content = contentBuilder.build(); + + riakObject.addUsermetaItem(userMetaKeys[0], userMetaValues[0]); + riakObject.addUsermetaItem(userMetaKeys[1], userMetaValues[1]); + + assertEquals(content, riakObject.buildContent()); + } + + @Test public void setContentType() { final RiakObject riakObject = new RiakObject(BUCKET, KEY, CONTENT); final RpbContent.Builder contentBuilder = RpbContent.newBuilder(); @@ -101,11 +119,24 @@ public class TestRiakObject { assertEquals(contentBuilder.build(), riakObject.buildContent()); } - + + @Test public void getLastModifiedDate() { + final Date date = new Date(); + long time = date.getTime(); + long lastModified = time / 1000; + long lastModifiedUsec = (time % 1000) * 100; + + final RpbContent.Builder contentBuilder = RpbContent.newBuilder(); + contentBuilder.setValue(BS_CONTENT).setLastMod((int)lastModified).setLastModUsecs((int)lastModifiedUsec); + final RiakObject riakObject = new RiakObject(BS_VCLOCK, BS_BUCKET, BS_KEY, contentBuilder.build()); + + assertEquals(date, riakObject.getLastModified()); + } + private static void assertBasicValues(final RiakObject riakObject) { assertBasicValues(riakObject, false); } - + private static void assertBasicValues(final RiakObject riakObject, boolean hasVClock) { assertEquals(BUCKET, riakObject.getBucket()); assertEquals(BS_BUCKET, riakObject.getBucketBS()); @@ -155,4 +186,37 @@ public void run() { riakObject.buildContent(); } + @Test public void modifyUserMetaAndBuildContentConcurrently() throws InterruptedException { + final RiakObject riakObject = new RiakObject(BS_VCLOCK, BS_BUCKET, BS_KEY, BS_CONTENT); + final int cnt = 20; + + Thread[] threads = new Thread[cnt]; + + for (int i = 0; i < cnt; i++) { + threads[i] = new Thread(new Runnable() { + + public void run() { + String key = UUID.randomUUID().toString(); + String value = UUID.randomUUID().toString(); + int cnt = 0; + while (true) { + riakObject.addUsermetaItem(key + cnt, value + cnt); + cnt++; + try { + Thread.sleep(10); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + } + }); + threads[i].setDaemon(true); + threads[i].start(); + } + + Thread.sleep(500); + + riakObject.buildContent(); + } } diff --git a/src/test/java/com/basho/riak/test/util/ExpectedValues.java b/src/test/java/com/basho/riak/test/util/ExpectedValues.java index 8a7423025..ec155e98f 100644 --- a/src/test/java/com/basho/riak/test/util/ExpectedValues.java +++ b/src/test/java/com/basho/riak/test/util/ExpectedValues.java @@ -48,12 +48,11 @@ private ExpectedValues() {} /** * Generate a number of RpbLinks, each link has the values * {@link ExpectedValues#BUCKET} _ n, {@link ExpectedValues#KEY} _ n, {@link ExpectedValues#TAG} _ n - * @param num how many RpbLinks to generate + * @param numLinks how many RpbLinks to generate * @return List of RpbLinks */ - public static List rpbLinks(int num) { - final int numLinks = num; - final List rpbLinks = new ArrayList(); + public static List rpbLinks(int numLinks) { + final List rpbLinks = new ArrayList(numLinks); for(int i=0; i < numLinks; i++) { RpbLink.Builder builder = RpbLink.newBuilder() @@ -65,8 +64,7 @@ public static List rpbLinks(int num) { return rpbLinks; } - - + public static ByteString concatToByteString(String value, int counter) { return ByteString.copyFromUtf8(value + "_" + counter); } From 57fc57c11d454bacc572a12d32a1cf56382b6ab4 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 14 Apr 2011 09:12:02 +0100 Subject: [PATCH 011/764] Add getter for VTag to pbc.RiakObject --- src/main/java/com/basho/riak/pbc/RiakObject.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/basho/riak/pbc/RiakObject.java b/src/main/java/com/basho/riak/pbc/RiakObject.java index 41e627d36..e2f30c0a1 100644 --- a/src/main/java/com/basho/riak/pbc/RiakObject.java +++ b/src/main/java/com/basho/riak/pbc/RiakObject.java @@ -195,6 +195,10 @@ RpbContent buildContent() { return b.build(); } + public String getVtag() { + return this.vtag; + } + public void setContentType(String contentType) { this.contentType = contentType; } From 079954cdfc4e535846e56788a43ca679c2b80466 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 14 Apr 2011 14:55:06 +0100 Subject: [PATCH 012/764] Add RW param to delete operations for HTTP client --- .../basho/riak/client/itest/ITestBasic.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/java/com/basho/riak/client/itest/ITestBasic.java b/src/test/java/com/basho/riak/client/itest/ITestBasic.java index e6b53056c..b1153b89b 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBasic.java @@ -227,4 +227,28 @@ public class ITestBasic { assertTrue(storeresp.hasSiblings()); assertEquals(2, storeresp.getSiblings().size()); } + + @Test public void deleteQuorumIsApplied() { + final RiakClient c = new RiakClient(RIAK_URL); + + final String bucket = UUID.randomUUID().toString(); + final String key = UUID.randomUUID().toString(); + final byte[] value = "value".getBytes(); + + RiakBucketInfo bucketInfo = new RiakBucketInfo(); + bucketInfo.setNVal(3); + + c.setBucketSchema(bucket, bucketInfo); + RiakObject o = new RiakObject(bucket, key, value); + + final RequestMeta rm = WRITE_3_REPLICAS(); + + StoreResponse storeresp = c.store(o, rm); + assertSuccess(storeresp); + + HttpResponse deleteResponse = c.delete(bucket, key, RequestMeta.deleteParams(4)); + + assertEquals(500, deleteResponse.getStatusCode()); + assertTrue(deleteResponse.getBodyAsString().contains("n_val_violation")); + } } From 849c5ed57eb273169994c4abe956f8f4d38b6203 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 26 Apr 2011 09:08:33 +0100 Subject: [PATCH 013/764] Make filter name static final --- .../com/basho/riak/client/mapreduce/filter/SetMemberFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java index 376888736..fe6dcc19e 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java @@ -19,6 +19,7 @@ import org.json.JSONArray; public class SetMemberFilter implements MapReduceFilter { + private static final String NAME = "set_member"; private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); From 74f7fa7e3ca5c85322e48880fd6676045e64e35e Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 27 Apr 2011 13:00:34 +0100 Subject: [PATCH 014/764] Implement MapReduce for new API Add MapReduce opertaions, filters, phase functions etc. --- .../com/basho/riak/client/raw/RawClient.java | 2 +- .../riak/client/raw/http/ConversionUtil.java | 287 ++++++++++++++++++ .../client/raw/http/HTTPClientAdapter.java | 239 +-------------- .../riak/client/raw/pbc/ConversionUtil.java | 215 +++++++++++++ .../riak/client/raw/pbc/PBClientAdapter.java | 162 +--------- .../riak/client/raw/query/MapReduceSpec.java | 37 +++ .../raw/query/MapReduceTimeoutException.java | 4 +- .../com/basho/riak/newapi/DefaultClient.java | 38 ++- .../com/basho/riak/newapi/RiakClient.java | 16 +- .../riak/newapi/bucket/BucketProperties.java | 4 +- .../riak/newapi/bucket/DefaultBucket.java | 4 +- .../bucket/DefaultBucketProperties.java | 16 +- .../riak/newapi/bucket/DomainBucket.java | 10 +- .../basho/riak/newapi/bucket/FetchBucket.java | 15 +- .../basho/riak/newapi/bucket/WriteBucket.java | 16 +- .../raw => newapi/cap}/DefaultRetrier.java | 3 +- .../riak/newapi/cap/{CAP.java => Quora.java} | 2 +- .../com/basho/riak/newapi/cap/Quorum.java | 6 +- .../{client/raw => newapi/cap}/Retrier.java | 3 +- .../riak/newapi/operations/DeleteObject.java | 4 +- .../riak/newapi/operations/FetchObject.java | 2 +- .../riak/newapi/operations/StoreObject.java | 6 +- .../riak/newapi/query/BucketKeyMapReduce.java | 94 ++++++ .../riak/newapi/query/BucketMapReduce.java | 133 ++++++++ .../basho/riak/newapi/query/LinkPhase.java | 74 +++++ .../com/basho/riak/newapi/query/MapPhase.java | 102 +++++++ .../basho/riak/newapi/query/MapReduce.java | 199 +++++++++++- .../riak/newapi/query/MapReducePhase.java | 39 +++ .../riak/newapi/query/MapReduceResult.java | 13 +- .../basho/riak/newapi/query/ReducePhase.java | 66 ++++ .../query/filter/AbstractKeyFilter.java | 31 ++ .../query/filter/AbstractLogicalFilter.java | 62 ++++ .../newapi/query/filter/BetweenFilter.java | 41 +++ .../newapi/query/filter/EndsWithFilter.java | 29 ++ .../newapi/query/filter/EqualToFilter.java | 36 +++ .../query/filter/FloatToStringFilter.java | 28 ++ .../query/filter/GreaterThanFilter.java | 36 +++ .../filter/GreaterThanOrEqualFilter.java | 36 +++ .../query/filter/IntToStringFilter.java | 29 ++ .../KeyFilter.java} | 9 +- .../query/filter/KeyTransformFilter.java | 22 ++ .../newapi/query/filter/LessThanFilter.java | 38 +++ .../query/filter/LessThanOrEqualFilter.java | 36 +++ .../newapi/query/filter/LogicalAndFilter.java | 36 +++ .../newapi/query/filter/LogicalFilter.java | 22 ++ .../query/filter/LogicalFilterGroup.java | 43 +++ .../newapi/query/filter/LogicalNotFilter.java | 33 ++ .../newapi/query/filter/LogicalOrFilter.java | 35 +++ .../riak/newapi/query/filter/MatchFilter.java | 29 ++ .../newapi/query/filter/NotEqualToFilter.java | 36 +++ .../newapi/query/filter/SetMemberFilter.java | 69 +++++ .../newapi/query/filter/SimilarToFilter.java | 28 ++ .../newapi/query/filter/StartsWithFilter.java | 29 ++ .../query/filter/StringToFloatFilter.java | 26 ++ .../query/filter/StringToIntFilter.java | 27 ++ .../newapi/query/filter/ToLowerFilter.java | 27 ++ .../newapi/query/filter/ToUpperFilter.java | 28 ++ .../newapi/query/filter/TokenizeFilter.java | 29 ++ .../newapi/query/filter/UrlDecodeFilter.java | 26 ++ .../query/functions/AnonymousFunction.java | 24 ++ .../riak/newapi/query/functions/Function.java | 22 ++ .../query/functions/JSBucketKeyFunction.java | 47 +++ .../query/functions/JSSourceFunction.java | 42 +++ .../{ => functions}/NamedErlangFunction.java | 2 +- .../query/{ => functions}/NamedFunction.java | 4 +- .../query/functions/NamedJSFunction.java | 39 +++ .../query/serialize/FunctionToJson.java | 46 +++ .../query/serialize/FunctionWriter.java | 24 ++ .../serialize/JSBucketKeyFunctionWriter.java | 49 +++ .../serialize/JSSourceFunctionWriter.java | 47 +++ .../serialize/NamedErlangFunctionWriter.java | 51 ++++ .../serialize/NamedJSFunctionWriter.java | 49 +++ .../riak/client/itest/ITestHTTPClient.java | 2 +- .../riak/client/itest/ITestMapReduce.java | 208 +++++++++++++ .../riak/client/itest/ITestMapReduceHTTP.java | 34 +++ .../riak/client/itest/ITestMapReducePB.java | 34 +++ .../query/filter/LogicalAndFilterTest.java | 40 +++ .../query/serialize/FunctionToJsonTest.java | 74 +++++ .../commerce/GoogleStockDataItem.java | 117 +++++++ .../megacorp/commerce/MergeCartResolver.java | 2 - 80 files changed, 3258 insertions(+), 466 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java create mode 100644 src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java create mode 100644 src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java rename src/main/java/com/basho/riak/{client/raw => newapi/cap}/DefaultRetrier.java (94%) rename src/main/java/com/basho/riak/newapi/cap/{CAP.java => Quora.java} (97%) rename src/main/java/com/basho/riak/{client/raw => newapi/cap}/Retrier.java (91%) create mode 100644 src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java create mode 100644 src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java create mode 100644 src/main/java/com/basho/riak/newapi/query/LinkPhase.java create mode 100644 src/main/java/com/basho/riak/newapi/query/MapPhase.java create mode 100644 src/main/java/com/basho/riak/newapi/query/MapReducePhase.java create mode 100644 src/main/java/com/basho/riak/newapi/query/ReducePhase.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java rename src/main/java/com/basho/riak/newapi/query/{MapReduceSpec.java => filter/KeyFilter.java} (80%) create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java create mode 100644 src/main/java/com/basho/riak/newapi/query/functions/Function.java create mode 100644 src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java create mode 100644 src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java rename src/main/java/com/basho/riak/newapi/query/{ => functions}/NamedErlangFunction.java (98%) rename src/main/java/com/basho/riak/newapi/query/{ => functions}/NamedFunction.java (86%) create mode 100644 src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java create mode 100644 src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestMapReduce.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java create mode 100644 src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java create mode 100644 src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java create mode 100644 src/test/java/com/megacorp/commerce/GoogleStockDataItem.java diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index 7d8a7d960..5acfdc9dc 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -17,12 +17,12 @@ import java.util.Iterator; import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.MapReduceSpec; import com.basho.riak.newapi.query.WalkResult; /** diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java new file mode 100644 index 000000000..dbd8d23e3 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -0,0 +1,287 @@ +/* + * This file is provided 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.basho.riak.client.raw.http; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.httpclient.util.DateUtil; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.type.TypeFactory; + +import com.basho.riak.client.RiakBucketInfo; +import com.basho.riak.client.RiakClient; +import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.client.request.RequestMeta; +import com.basho.riak.client.response.BucketResponse; +import com.basho.riak.client.response.MapReduceResponse; +import com.basho.riak.client.util.Constants; +import com.basho.riak.newapi.DefaultRiakLink; +import com.basho.riak.newapi.RiakLink; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.bucket.DefaultBucketProperties; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; + +/** + * @author russell + * + */ +public class ConversionUtil { + /** + * @param siblings + * @param bucket + * @return + */ + static RiakObject[] convert(Collection siblings, Bucket bucket) { + final Collection results = new ArrayList(); + + for (com.basho.riak.client.RiakObject object : siblings) { + results.add(convert(object, bucket)); + } + + return results.toArray(new RiakObject[results.size()]); + } + + /** + * @param object + * @return + */ + static RiakObject convert(final com.basho.riak.client.RiakObject o, final Bucket bucket) { + + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + + builder.withValue(o.getValue()); + builder.withVClock(nullSafeGetBytes(o.getVclock())); + builder.withVtag(o.getVtag()); + + String lastModified = o.getLastmod(); + + if (lastModified != null) { + Date lastModDate = o.getLastmodAsDate(); + builder.withLastModified(lastModDate.getTime()); + } + + final Collection links = new ArrayList(); + + for (com.basho.riak.client.RiakLink link : o.iterableLinks()) { + links.add(convert(link)); + } + + builder.withLinks(links); + builder.withContentType(o.getContentType()); + + final Map userMetaData = new HashMap(); + + for (String key : o.usermetaKeys()) { + userMetaData.put(key, o.getUsermetaItem(key)); + } + + builder.withUsermeta(userMetaData); + + return builder.build(); + } + + /** + * @param link + * @return + */ + static RiakLink convert(com.basho.riak.client.RiakLink link) { + return new DefaultRiakLink(link.getBucket(), link.getKey(), link.getTag()); + } + + /** + * @param vclock + * @return + */ + static byte[] nullSafeGetBytes(String vclock) { + return vclock == null ? null : vclock.getBytes(); + } + + /** + * @param storeMeta + * @return + */ + static RequestMeta convert(StoreMeta storeMeta) { + RequestMeta requestMeta = RequestMeta.writeParams(storeMeta.getW(), storeMeta.getDw()); + + if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { + requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(true)); + } else { + requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(false)); + } + + return requestMeta; + } + + /** + * @param object + * @return + */ + static com.basho.riak.client.RiakObject convert(RiakObject object, final RiakClient client) { + com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( + client, + object.getBucketName(), + object.getKey(), + nullSafeGetBytes(object.getValue()), + object.getContentType(), + getLinks(object), + getUserMetaData(object), + object.getVClockAsString(), + formatDate(object.getLastModified()), + object.getVtag()); + return riakObject; + } + + /** + * @param lastModified + * @return + */ + static String formatDate(Date lastModified) { + if (lastModified == null) { + return null; + } + return DateUtil.formatDate(lastModified); + } + + /** + * @param object + * @return + */ + static Map getUserMetaData(RiakObject object) { + final Map userMetaData = new HashMap(); + + for (Entry entry : object.userMetaEntries()) { + userMetaData.put(entry.getKey(), entry.getValue()); + } + return userMetaData; + } + + /** + * @param object + * @return + */ + static List getLinks(RiakObject object) { + + final List links = new ArrayList(); + + for (RiakLink link : object) { + links.add(convert(link)); + } + + return links; + } + + /** + * @param link + * @return + */ + static com.basho.riak.client.RiakLink convert(RiakLink link) { + return new com.basho.riak.client.RiakLink(link.getBucket(), link.getKey(), link.getTag()); + } + + /** + * @param response + * @return + */ + static BucketProperties convert(BucketResponse response) { + RiakBucketInfo bucketInfo = response.getBucketInfo(); + return new DefaultBucketProperties.Builder() + .allowSiblings(bucketInfo.getAllowMult()) + .nVal(bucketInfo.getNVal()) + .chashKeyFunction(convert(bucketInfo.getCHashFun())) + .linkWalkFunction(convert(bucketInfo.getLinkFun())) + .build(); + } + + /** + * @param cHashFun + * @return + */ + static NamedErlangFunction convert(String funString) { + if (funString == null) { + return null; + } + String[] fun = funString.split(":"); + + if (fun.length != 2) { + return null; + } + + return new NamedErlangFunction(fun[0], fun[1]); + } + + /** + * @param bucketProperties + * @return + */ + static RiakBucketInfo convert(BucketProperties bucketProperties) { + RiakBucketInfo rbi = new RiakBucketInfo(); + + if (bucketProperties.getAllowSiblings() != null) { + rbi.setAllowMult(bucketProperties.getAllowSiblings()); + } + + if (bucketProperties.getNVal() != null) { + rbi.setNVal(bucketProperties.getNVal()); + } + + final NamedErlangFunction chashKeyFun = bucketProperties.getChashKeyFunction(); + if (chashKeyFun != null) { + rbi.setCHashFun(chashKeyFun.getMod(), chashKeyFun.getFun()); + } + + final NamedErlangFunction linkwalkFun = bucketProperties.getLinkWalkFunction(); + if (linkwalkFun != null) { + rbi.setLinkFun(linkwalkFun.getMod(), linkwalkFun.getFun()); + } + + return rbi; + } + + /** + * @param resp + * @return + */ + static MapReduceResult convert(final MapReduceResponse resp) throws IOException { + final ObjectMapper om = new ObjectMapper(); + + final MapReduceResult result = new MapReduceResult() { + + public String getResultRaw() { + return resp.getBodyAsString(); + } + + public Collection getResult(Class resultType) throws ConversionException { + try { + return om.readValue(getResultRaw(), TypeFactory.collectionType(Collection.class, resultType)); + } catch (IOException e) { + throw new ConversionException(e); + } + } + }; + return result; + } + +} diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index d16a08d4a..448242bbc 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -13,46 +13,35 @@ */ package com.basho.riak.client.raw.http; +import static com.basho.riak.client.raw.http.ConversionUtil.convert; + import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.httpclient.util.DateUtil; -import com.basho.riak.client.RiakBucketInfo; import com.basho.riak.client.RiakClient; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; import com.basho.riak.client.request.RequestMeta; import com.basho.riak.client.response.BucketResponse; import com.basho.riak.client.response.FetchResponse; import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.response.MapReduceResponse; import com.basho.riak.client.response.StoreResponse; import com.basho.riak.client.response.WithBodyResponse; -import com.basho.riak.client.util.Constants; -import com.basho.riak.newapi.DefaultRiakLink; -import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.bucket.DefaultBucketProperties; -import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.ClientId; import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.MapReduceSpec; -import com.basho.riak.newapi.query.NamedErlangFunction; import com.basho.riak.newapi.query.WalkResult; /** + * Adapts the old {@link RiakClient} to the new {@link RawClient} interface. + * * @author russell * */ @@ -143,77 +132,6 @@ private RiakResponse handleBodyResponse(Bucket bucket, WithBodyResponse resp) { return response; } - /** - * @param siblings - * @param bucket - * @return - */ - private RiakObject[] convert(Collection siblings, Bucket bucket) { - final Collection results = new ArrayList(); - - for (com.basho.riak.client.RiakObject object : siblings) { - results.add(convert(object, bucket)); - } - - return results.toArray(new RiakObject[results.size()]); - } - - /** - * @param object - * @return - */ - private RiakObject convert(final com.basho.riak.client.RiakObject o, final Bucket bucket) { - - RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); - - builder.withValue(o.getValue()); - System.out.println("VClock into new riak object " + o.getVclock()); - builder.withVClock(nullSafeGetBytes(o.getVclock())); - builder.withVtag(o.getVtag()); - - String lastModified = o.getLastmod(); - - if (lastModified != null) { - Date lastModDate = o.getLastmodAsDate(); - builder.withLastModified(lastModDate.getTime()); - } - - final Collection links = new ArrayList(); - - for (com.basho.riak.client.RiakLink link : o.iterableLinks()) { - links.add(convert(link)); - } - - builder.withLinks(links); - builder.withContentType(o.getContentType()); - - final Map userMetaData = new HashMap(); - - for (String key : o.usermetaKeys()) { - userMetaData.put(key, o.getUsermetaItem(key)); - } - - builder.withUsermeta(userMetaData); - - return builder.build(); - } - - /** - * @param link - * @return - */ - private RiakLink convert(com.basho.riak.client.RiakLink link) { - return new DefaultRiakLink(link.getBucket(), link.getKey(), link.getTag()); - } - - /** - * @param vclock - * @return - */ - private byte[] nullSafeGetBytes(String vclock) { - return vclock == null ? null : vclock.getBytes(); - } - /* * (non-Javadoc) * @@ -228,7 +146,7 @@ public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOExcep final Bucket bucket = object.getBucket(); RiakResponse response = RiakResponse.empty(); - com.basho.riak.client.RiakObject riakObject = convert(object); + com.basho.riak.client.RiakObject riakObject = convert(object, client); RequestMeta requestMeta = convert(storeMeta); StoreResponse resp = client.store(riakObject, requestMeta); @@ -245,91 +163,6 @@ public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOExcep return response; } - /** - * @param storeMeta - * @return - */ - private RequestMeta convert(StoreMeta storeMeta) { - RequestMeta requestMeta = RequestMeta.writeParams(storeMeta.getW(), storeMeta.getDw()); - - if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { - requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(true)); - } else { - requestMeta.setQueryParam(Constants.QP_RETURN_BODY, Boolean.toString(false)); - } - - return requestMeta; - } - - /** - * @param object - * @return - */ - private com.basho.riak.client.RiakObject convert(RiakObject object) { - - System.out.println("Vclock out of new object " + object.getVClockAsString()); - - com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( - client, - object.getBucketName(), - object.getKey(), - nullSafeGetBytes(object.getValue()), - object.getContentType(), - getLinks(object), - getUserMetaData(object), - object.getVClockAsString(), - formatDate(object.getLastModified()), - object.getVtag()); - return riakObject; - } - - /** - * @param lastModified - * @return - */ - private String formatDate(Date lastModified) { - if (lastModified == null) { - return null; - } - return DateUtil.formatDate(lastModified); - } - - /** - * @param object - * @return - */ - private Map getUserMetaData(RiakObject object) { - final Map userMetaData = new HashMap(); - - for (Entry entry : object.userMetaEntries()) { - userMetaData.put(entry.getKey(), entry.getValue()); - } - return userMetaData; - } - - /** - * @param object - * @return - */ - private List getLinks(RiakObject object) { - - final List links = new ArrayList(); - - for (RiakLink link : object) { - links.add(convert(link)); - } - - return links; - } - - /** - * @param link - * @return - */ - private com.basho.riak.client.RiakLink convert(RiakLink link) { - return new com.basho.riak.client.RiakLink(link.getBucket(), link.getKey(), link.getTag()); - } - /* * (non-Javadoc) * @@ -393,32 +226,6 @@ public BucketProperties fetchBucket(String bucketName) throws IOException { return convert(response); } - /** - * @param response - * @return - */ - private BucketProperties convert(BucketResponse response) { - RiakBucketInfo bucketInfo = response.getBucketInfo(); - return new DefaultBucketProperties.Builder().allowSiblings(bucketInfo.getAllowMult()).nVal(bucketInfo.getNVal()).chashKeyFunction(convert(bucketInfo.getCHashFun())).linkWalkFunction(convert(bucketInfo.getLinkFun())).build(); - } - - /** - * @param cHashFun - * @return - */ - private NamedErlangFunction convert(String funString) { - if (funString == null) { - return null; - } - String[] fun = funString.split(":"); - - if (fun.length != 2) { - return null; - } - - return new NamedErlangFunction(fun[0], fun[1]); - } - /* * (non-Javadoc) * @@ -433,34 +240,6 @@ public void updateBucket(String name, BucketProperties bucketProperties) throws } - /** - * @param bucketProperties - * @return - */ - private RiakBucketInfo convert(BucketProperties bucketProperties) { - RiakBucketInfo rbi = new RiakBucketInfo(); - - if (bucketProperties.getAllowSiblings() != null) { - rbi.setAllowMult(bucketProperties.getAllowSiblings()); - } - - if (bucketProperties.getNVal() != null) { - rbi.setNVal(bucketProperties.getNVal()); - } - - final NamedErlangFunction chashKeyFun = bucketProperties.getChashKeyFunction(); - if (chashKeyFun != null) { - rbi.setCHashFun(chashKeyFun.getMod(), chashKeyFun.getFun()); - } - - final NamedErlangFunction linkwalkFun = bucketProperties.getLinkWalkFunction(); - if (linkwalkFun != null) { - rbi.setLinkFun(linkwalkFun.getMod(), linkwalkFun.getFun()); - } - - return rbi; - } - /* * (non-Javadoc) * @@ -496,7 +275,8 @@ public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) th * .MapReduceSpec) */ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException { - return null; + MapReduceResponse resp = client.mapReduce(spec.getJSON()); + return convert(resp); } /* @@ -531,5 +311,4 @@ public void setClientId(byte[] clientId) throws IOException { public byte[] getClientId() throws IOException { return client.getClientId(); } - } diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java new file mode 100644 index 000000000..62fb69be8 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -0,0 +1,215 @@ +/* + * This file is provided 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.basho.riak.client.raw.pbc; + +import java.io.IOException; +import java.util.Collection; +import java.util.Date; +import java.util.Map.Entry; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.type.TypeFactory; + +import com.basho.riak.client.raw.RiakResponse; +import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.bucket.DefaultBucketProperties; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.pbc.MapReduceResponseSource; +import com.basho.riak.pbc.RequestMeta; +import com.basho.riak.pbc.mapreduce.MapReduceResponse; +import com.google.protobuf.ByteString; + +/** + * @author russell + * + */ +public class ConversionUtil { + /** + * @param fetch + * @return + */ + static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { + RiakResponse response = RiakResponse.empty(); + + if (pbcObjects != null && pbcObjects.length > 0) { + RiakObject[] converted = new RiakObject[pbcObjects.length]; + for (int i = 0; i < pbcObjects.length; i++) { + converted[i] = convert(pbcObjects[i], bucket); + } + response = new RiakResponse(pbcObjects[0].getVclock().toByteArray(), converted); + } + + return response; + } + + /** + * @param o + * @return + */ + static RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) { + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + + builder.withValue(nullSafeToStringUtf8(o.getValue())); + builder.withVClock(nullSafeToBytes(o.getVclock())); + builder.withVtag(o.getVtag()); + + Date lastModified = o.getLastModified(); + + if (lastModified != null) { + builder.withLastModified(lastModified.getTime()); + } + + return builder.build(); + } + + /** + * @param vclock + * @return + */ + static byte[] nullSafeToBytes(ByteString value) { + return value == null ? null : value.toByteArray(); + } + + /** + * @param value + * @return + */ + static String nullSafeToStringUtf8(ByteString value) { + return value == null ? null : value.toStringUtf8(); + } + + static ByteString nullSafeToByteString(String value) { + return value == null ? null : ByteString.copyFromUtf8(value); + } + + /** + * Convert a {@link StoreMeta} to a pbc {@link RequestMeta} + * + * @param storeMeta + * a {@link StoreMeta} for the store operation. + * @return a {@link RequestMeta} populated from the storeMeta's values. + */ + static RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { + RequestMeta requestMeta = new RequestMeta(); + if (storeMeta.hasW()) { + requestMeta.w(storeMeta.getW()); + } + if (storeMeta.hasDW()) { + requestMeta.dw(storeMeta.getDw()); + } + if (storeMeta.hasReturnBody()) { + requestMeta.returnBody(storeMeta.getReturnBody()); + } + String contentType = riakObject.getContentType(); + if (contentType != null) { + requestMeta.contentType(contentType); + } + return requestMeta; + } + + /** + * Convert a {@link RiakObject} to a pbc + * {@link com.basho.riak.pbc.RiakObject} + * + * @param riakObject + * the RiakObject to convert + * @return a {@link com.basho.riak.pbc.RiakObject} populated from riakObject + */ + static com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { + final VClock vc = riakObject.getVClock(); + ByteString bucketName = nullSafeToByteString(riakObject.getBucketName()); + ByteString key = nullSafeToByteString(riakObject.getKey()); + ByteString content = nullSafeToByteString(riakObject.getValue()); + + ByteString vclock = null; + if (vc != null) { + vclock = nullSafeFromBytes(vc.getBytes()); + } + + com.basho.riak.pbc.RiakObject result = new com.basho.riak.pbc.RiakObject(vclock, bucketName, key, content); + + for (com.basho.riak.newapi.RiakLink link : riakObject) { + result.addLink(link.getTag(), link.getBucket(), link.getKey()); + } + + for (Entry metaDataItem : riakObject.userMetaEntries()) { + result.addUsermetaItem(metaDataItem.getKey(), metaDataItem.getValue()); + } + + result.setContentType(riakObject.getContentType()); + return result; + } + + /** + * @param bytes + * @return + */ + static ByteString nullSafeFromBytes(byte[] bytes) { + return ByteString.copyFrom(bytes); + } + + /** + * @param bucketProperties + * @return + */ + static com.basho.riak.pbc.BucketProperties convert(BucketProperties p) { + return new com.basho.riak.pbc.BucketProperties().nValue(p.getNVal()).allowMult(p.getAllowSiblings()); + } + + /** + * @param properties + * @return + */ + static BucketProperties convert(com.basho.riak.pbc.BucketProperties properties) { + return new DefaultBucketProperties.Builder().allowSiblings(properties.getAllowMult()).nVal(properties.getNValue()).build(); + } + + /** + * @param resp + * @return + */ + static MapReduceResult convert(final MapReduceResponseSource resp) { + final ObjectMapper om = new ObjectMapper(); + final StringBuilder sb = new StringBuilder(); + + for (MapReduceResponse mrr : resp) { + // TODO investigate pb client null returns from MRRS + if (mrr != null && mrr.response != null) { + sb.append(mrr.response.toStringUtf8()); + } + } + + final MapReduceResult result = new MapReduceResult() { + + public String getResultRaw() { + return sb.toString(); + } + + public Collection getResult(Class resultType) throws ConversionException { + try { + return om.readValue(getResultRaw(), TypeFactory.collectionType(Collection.class, resultType)); + } catch (IOException e) { + throw new ConversionException(e); + } + } + }; + return result; + } +} diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index fe357ef49..cbbde94a2 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -13,32 +13,34 @@ */ package com.basho.riak.client.raw.pbc; +import static com.basho.riak.client.raw.pbc.ConversionUtil.convert; +import static com.basho.riak.client.raw.pbc.ConversionUtil.nullSafeToStringUtf8; + import java.io.IOException; -import java.util.Date; import java.util.Iterator; -import java.util.Map.Entry; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; -import com.basho.riak.newapi.RiakLink; +import com.basho.riak.client.util.Constants; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.bucket.DefaultBucketProperties; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.MapReduceSpec; import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.pbc.IRequestMeta; import com.basho.riak.pbc.KeySource; +import com.basho.riak.pbc.MapReduceResponseSource; import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.RiakClient; import com.google.protobuf.ByteString; /** + * Wraps the pb {@link RiakClient} and adapts it to the {@link RawClient} interface. + * * @author russell * */ @@ -93,64 +95,6 @@ public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOEx return convert(client.fetch(bucket.getName(), key, readQuorum), bucket); } - /** - * @param fetch - * @return - */ - private RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { - RiakResponse response = RiakResponse.empty(); - - if (pbcObjects != null && pbcObjects.length > 0) { - RiakObject[] converted = new RiakObject[pbcObjects.length]; - for (int i = 0; i < pbcObjects.length; i++) { - converted[i] = convert(pbcObjects[i], bucket); - } - response = new RiakResponse(pbcObjects[0].getVclock().toByteArray(), converted); - } - - return response; - } - - /** - * @param o - * @return - */ - private RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) { - RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); - - builder.withValue(nullSafeToStringUtf8(o.getValue())); - builder.withVClock(nullSafeToBytes(o.getVclock())); - builder.withVtag(o.getVtag()); - - Date lastModified = o.getLastModified(); - - if (lastModified != null) { - builder.withLastModified(lastModified.getTime()); - } - - return builder.build(); - } - - /** - * @param vclock - * @return - */ - private byte[] nullSafeToBytes(ByteString value) { - return value == null ? null : value.toByteArray(); - } - - /** - * @param value - * @return - */ - private String nullSafeToStringUtf8(ByteString value) { - return value == null ? null : value.toStringUtf8(); - } - - private ByteString nullSafeToByteString(String value) { - return value == null ? null : ByteString.copyFromUtf8(value); - } - /* * (non-Javadoc) * @@ -167,72 +111,6 @@ public RiakResponse store(RiakObject riakObject, StoreMeta storeMeta) throws IOE return convert(client.store(convert(riakObject), convert(storeMeta, riakObject)), riakObject.getBucket()); } - /** - * Convert a {@link StoreMeta} to a pbc {@link RequestMeta} - * - * @param storeMeta - * a {@link StoreMeta} for the store operation. - * @return a {@link RequestMeta} populated from the storeMeta's values. - */ - private RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { - RequestMeta requestMeta = new RequestMeta(); - if (storeMeta.hasW()) { - requestMeta.w(storeMeta.getW()); - } - if (storeMeta.hasDW()) { - requestMeta.dw(storeMeta.getDw()); - } - if (storeMeta.hasReturnBody()) { - requestMeta.returnBody(storeMeta.getReturnBody()); - } - String contentType = riakObject.getContentType(); - if (contentType != null) { - requestMeta.contentType(contentType); - } - return requestMeta; - } - - /** - * Convert a {@link RiakObject} to a pbc - * {@link com.basho.riak.pbc.RiakObject} - * - * @param riakObject - * the RiakObject to convert - * @return a {@link com.basho.riak.pbc.RiakObject} populated from riakObject - */ - private com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { - VClock vc = riakObject.getVClock(); - ByteString bucketName = nullSafeToByteString(riakObject.getBucketName()); - ByteString key = nullSafeToByteString(riakObject.getKey()); - ByteString content = nullSafeToByteString(riakObject.getValue()); - - ByteString vclock = null; - if (vc != null) { - vclock = nullSafeFromBytes(vc.getBytes()); - } - - com.basho.riak.pbc.RiakObject result = new com.basho.riak.pbc.RiakObject(vclock, bucketName, key, content); - - for (RiakLink link : riakObject) { - result.addLink(link.getTag(), link.getBucket(), link.getKey()); - } - - for (Entry metaDataItem : riakObject.userMetaEntries()) { - result.addUsermetaItem(metaDataItem.getKey(), metaDataItem.getValue()); - } - - result.setContentType(riakObject.getContentType()); - return result; - } - - /** - * @param bytes - * @return - */ - private ByteString nullSafeFromBytes(byte[] bytes) { - return ByteString.copyFrom(bytes); - } - /* * (non-Javadoc) * @@ -285,14 +163,6 @@ public BucketProperties fetchBucket(String bucketName) throws IOException { return convert(properties); } - /** - * @param properties - * @return - */ - private BucketProperties convert(com.basho.riak.pbc.BucketProperties properties) { - return new DefaultBucketProperties.Builder().allowSiblings(properties.getAllowMult()).nVal(properties.getNValue()).build(); - } - /* * (non-Javadoc) * @@ -306,14 +176,6 @@ public void updateBucket(final String name, final BucketProperties bucketPropert } - /** - * @param bucketProperties - * @return - */ - private com.basho.riak.pbc.BucketProperties convert(BucketProperties p) { - return new com.basho.riak.pbc.BucketProperties().nValue(p.getNVal()).allowMult(p.getAllowSiblings()); - } - /* * (non-Javadoc) * @@ -369,7 +231,10 @@ public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) th * .MapReduceSpec) */ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException { - return null; + IRequestMeta meta = new RequestMeta(); + meta.contentType(Constants.CTYPE_JSON); + MapReduceResponseSource resp = client.mapReduce(spec.getJSON(), meta); + return convert(resp); } /* @@ -408,5 +273,4 @@ public byte[] getClientId() throws IOException { throw new IOException("null clientId returned by client"); } } - } diff --git a/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java b/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java new file mode 100644 index 000000000..3e7bd1d62 --- /dev/null +++ b/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java @@ -0,0 +1,37 @@ +/* + * This file is provided 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.basho.riak.client.raw.query; + +/** + * A Map Reduce Query run it via {@link RiakClient#mapReduce(MapReduceSpec)} + * + * @author russell + * + */ +public class MapReduceSpec { + + private final String mapReduceSpecJSON; + + /** + * @param mapReduceSpecJSON + */ + public MapReduceSpec(String mapReduceSpecJSON) { + this.mapReduceSpecJSON = mapReduceSpecJSON; + } + + public String getJSON() { + return mapReduceSpecJSON; + } + +} diff --git a/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java index ed243a6a6..f6bd721b5 100644 --- a/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java +++ b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java @@ -13,11 +13,13 @@ */ package com.basho.riak.client.raw.query; +import com.basho.riak.newapi.RiakException; + /** * @author russell * */ -public class MapReduceTimeoutException extends Exception { +public class MapReduceTimeoutException extends RiakException { private static final long serialVersionUID = -1293682325413369755L; diff --git a/src/main/java/com/basho/riak/newapi/DefaultClient.java b/src/main/java/com/basho/riak/newapi/DefaultClient.java index f570fe1ed..5ba6afdd9 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultClient.java +++ b/src/main/java/com/basho/riak/newapi/DefaultClient.java @@ -3,22 +3,21 @@ import java.io.IOException; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.FetchBucket; import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.cap.DefaultRetrier; +import com.basho.riak.newapi.query.BucketKeyMapReduce; +import com.basho.riak.newapi.query.BucketMapReduce; import com.basho.riak.newapi.query.LinkWalk; -import com.basho.riak.newapi.query.MapReduce; /** * @author russell * */ public final class DefaultClient implements RiakClient { - /** - * - */ + private final RawClient client; /** @@ -28,19 +27,13 @@ public final class DefaultClient implements RiakClient { this.client = client; } - public LinkWalk walk(RiakObject startObject) { - return null; - } + // BUCKET OPS public WriteBucket updateBucket(Bucket b) { WriteBucket op = new WriteBucket(client, b); return op; } - public MapReduce mapReduce() { - return null; - } - public FetchBucket fetchBucket(String bucketName) { FetchBucket op = new FetchBucket(client, bucketName); return op; @@ -51,6 +44,8 @@ public WriteBucket createBucket(String bucketName) { return op; } + // CLIENT ID + public RiakClient setClientId(final byte[] clientId) throws RiakException { if (clientId == null || clientId.length != 4) { throw new IllegalArgumentException("Client Id must be 4 bytes long"); @@ -85,4 +80,23 @@ public byte[] execute() throws IOException { return clientId; } + + // QUERY + + public BucketKeyMapReduce mapReduce() { + return new BucketKeyMapReduce(client); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakClient#mapReduce(java.lang.String) + */ + public BucketMapReduce mapReduce(String bucket) { + return new BucketMapReduce(client, bucket); + } + + public LinkWalk walk(RiakObject startObject) { + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/RiakClient.java b/src/main/java/com/basho/riak/newapi/RiakClient.java index 2b00e154f..5e21ced0e 100644 --- a/src/main/java/com/basho/riak/newapi/RiakClient.java +++ b/src/main/java/com/basho/riak/newapi/RiakClient.java @@ -16,8 +16,9 @@ import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.FetchBucket; import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.query.BucketKeyMapReduce; +import com.basho.riak.newapi.query.BucketMapReduce; import com.basho.riak.newapi.query.LinkWalk; -import com.basho.riak.newapi.query.MapReduce; /** * @author russell @@ -41,5 +42,16 @@ public interface RiakClient { LinkWalk walk(final RiakObject startObject); // query - m/r - MapReduce mapReduce(); + + /** + * Map reduce over a set of bucket, key inputs + */ + BucketKeyMapReduce mapReduce(); + + /** + * Map reduce over a bucket + * @param bucket + * @return + */ + BucketMapReduce mapReduce(String bucket); } diff --git a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java index aeff029e3..29a1a1848 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java +++ b/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java @@ -16,8 +16,8 @@ import java.util.Collection; import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.query.NamedErlangFunction; -import com.basho.riak.newapi.query.NamedFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 6cf71927b..79c82e157 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -33,8 +33,8 @@ import com.basho.riak.newapi.operations.DeleteObject; import com.basho.riak.newapi.operations.FetchObject; import com.basho.riak.newapi.operations.StoreObject; -import com.basho.riak.newapi.query.NamedErlangFunction; -import com.basho.riak.newapi.query.NamedFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java index 73102c274..83cad6f60 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java @@ -16,10 +16,10 @@ import java.util.ArrayList; import java.util.Collection; -import com.basho.riak.newapi.cap.CAP; +import com.basho.riak.newapi.cap.Quora; import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.query.NamedErlangFunction; -import com.basho.riak.newapi.query.NamedFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedFunction; /** * Since not all interfaces to Riak are equal in terms of what they provide not @@ -244,7 +244,7 @@ public static final class Builder { public String backend; public int nVal = 3; public Boolean lastWriteWins; - public Boolean allowSiblings; + public boolean allowSiblings = false; public BucketProperties build() { return new DefaultBucketProperties(this); @@ -372,7 +372,7 @@ public Builder oldVClock(long oldVClock) { * @param r * @return */ - public Builder r(CAP r) { + public Builder r(Quora r) { this.r = new Quorum(r); return this; } @@ -386,7 +386,7 @@ public Builder r(int r) { * @param w * @return */ - public Builder w(CAP w) { + public Builder w(Quora w) { this.w = new Quorum(w); return this; } @@ -400,7 +400,7 @@ public Builder w(int w) { * @param rw * @return */ - public Builder rw(CAP rw) { + public Builder rw(Quora rw) { this.rw = new Quorum(rw); return this; } @@ -414,7 +414,7 @@ public Builder rw(int rw) { * @param dw * @return */ - public Builder dw(CAP dw) { + public Builder dw(Quora dw) { this.dw = new Quorum(dw); return this; } diff --git a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java index cf2aa5c1e..2d53008a0 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java @@ -74,7 +74,15 @@ public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter co public T store(T o) throws RiakException { final Mutation mutation = mutationProducer.produce(o); - return bucket.store(o).withConverter(converter).withMutator(mutation).withResolver(resolver).w(w).dw(dw).retry(retries).returnBody(returnBody).execute(); + return bucket.store(o) + .withConverter(converter) + .withMutator(mutation) + .withResolver(resolver) + .w(w) + .dw(dw) + .retry(retries) + .returnBody(returnBody) + .execute(); } public T fetch(String key) throws RiakException { diff --git a/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java b/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java index 577bf4c13..7aac5abbd 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java @@ -16,9 +16,9 @@ import java.io.IOException; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakRetryFailedException; +import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.operations.RiakOperation; /** @@ -31,8 +31,6 @@ public class FetchBucket implements RiakOperation { private final String bucket; private int retry = 0; - private boolean fetchKeys = false; - private boolean fetchProperties = true; /** * @param client @@ -57,15 +55,4 @@ public FetchBucket retry(int i) { this.retry = i; return this; } - - public FetchBucket fetchKeys(boolean fetchKeys) { - this.fetchKeys = fetchKeys; - return this; - } - - public FetchBucket fetchProperties(boolean fetchProperties) { - this.fetchProperties = fetchProperties; - return this; - } - } diff --git a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java index 8945114e3..49d0fc40a 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java @@ -17,14 +17,14 @@ import java.util.Collection; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.DefaultBucketProperties.Builder; -import com.basho.riak.newapi.cap.CAP; +import com.basho.riak.newapi.cap.DefaultRetrier; +import com.basho.riak.newapi.cap.Quora; import com.basho.riak.newapi.operations.RiakOperation; -import com.basho.riak.newapi.query.NamedErlangFunction; -import com.basho.riak.newapi.query.NamedFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedFunction; /** * @author russell @@ -142,7 +142,7 @@ public WriteBucket oldVClock(long oldVClock) { return this; } - public WriteBucket r(CAP r) { + public WriteBucket r(Quora r) { builder.r(r); return this; } @@ -152,7 +152,7 @@ public WriteBucket r(int r) { return this; } - public WriteBucket w(CAP w) { + public WriteBucket w(Quora w) { builder.w(w); return this; } @@ -162,7 +162,7 @@ public WriteBucket w(int w) { return this; } - public WriteBucket rw(CAP rw) { + public WriteBucket rw(Quora rw) { builder.rw(rw); return this; } @@ -172,7 +172,7 @@ public WriteBucket rw(int rw) { return this; } - public WriteBucket dw(CAP dw) { + public WriteBucket dw(Quora dw) { builder.dw(dw); return this; } diff --git a/src/main/java/com/basho/riak/client/raw/DefaultRetrier.java b/src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java similarity index 94% rename from src/main/java/com/basho/riak/client/raw/DefaultRetrier.java rename to src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java index 14790043d..9c2e9db03 100644 --- a/src/main/java/com/basho/riak/client/raw/DefaultRetrier.java +++ b/src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java @@ -11,10 +11,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.raw; +package com.basho.riak.newapi.cap; import java.io.IOException; +import com.basho.riak.client.raw.Command; import com.basho.riak.newapi.RiakRetryFailedException; /** diff --git a/src/main/java/com/basho/riak/newapi/cap/CAP.java b/src/main/java/com/basho/riak/newapi/cap/Quora.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/cap/CAP.java rename to src/main/java/com/basho/riak/newapi/cap/Quora.java index 16435573b..6560df8eb 100644 --- a/src/main/java/com/basho/riak/newapi/cap/CAP.java +++ b/src/main/java/com/basho/riak/newapi/cap/Quora.java @@ -17,6 +17,6 @@ * @author russell * */ -public enum CAP { +public enum Quora { ALL, ONE, QUORUM; } diff --git a/src/main/java/com/basho/riak/newapi/cap/Quorum.java b/src/main/java/com/basho/riak/newapi/cap/Quorum.java index a8b913f86..af7064ca4 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Quorum.java +++ b/src/main/java/com/basho/riak/newapi/cap/Quorum.java @@ -15,13 +15,13 @@ public final class Quorum { private Integer i; - private CAP cap; + private Quora quorum; public Quorum(int i) { this.i = i; } - public Quorum(CAP cap) { - this.cap = cap; + public Quorum(Quora quorum) { + this.quorum = quorum; } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/raw/Retrier.java b/src/main/java/com/basho/riak/newapi/cap/Retrier.java similarity index 91% rename from src/main/java/com/basho/riak/client/raw/Retrier.java rename to src/main/java/com/basho/riak/newapi/cap/Retrier.java index 8eef9d893..554b55189 100644 --- a/src/main/java/com/basho/riak/client/raw/Retrier.java +++ b/src/main/java/com/basho/riak/newapi/cap/Retrier.java @@ -11,8 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.raw; +package com.basho.riak.newapi.cap; +import com.basho.riak.client.raw.Command; import com.basho.riak.newapi.RiakRetryFailedException; /** diff --git a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java index bb4f071ce..ba55d5cf1 100644 --- a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java @@ -16,10 +16,10 @@ import java.io.IOException; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.DefaultRetrier; /** * @author russell @@ -66,7 +66,7 @@ public Void execute() throws IOException { return null; } - public DeleteObject rw(int rw) { + public DeleteObject rw(Integer rw) { this.rw = rw; return this; } diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java index 49ab31f0e..f7538563a 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -18,13 +18,13 @@ import java.util.Collection; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.cap.UnresolvedConflictException; import com.basho.riak.newapi.convert.ConversionException; import com.basho.riak.newapi.convert.Converter; diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index cf6efa9a6..531ec947c 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -18,7 +18,6 @@ import java.util.Collection; import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.DefaultRetrier; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; @@ -27,6 +26,7 @@ import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.ConflictResolver; +import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.UnresolvedConflictException; import com.basho.riak.newapi.convert.ConversionException; @@ -113,12 +113,12 @@ private StoreMeta generateStoreMeta() { return new StoreMeta(w, dw, returnBody); } - public StoreObject w(int w) { + public StoreObject w(Integer w) { this.w = w; return this; } - public StoreObject dw(int dw) { + public StoreObject dw(Integer dw) { this.dw = dw; return this; } diff --git a/src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java b/src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java new file mode 100644 index 000000000..e415e3735 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java @@ -0,0 +1,94 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.client.raw.RawClient; + +/** + * @author russell + * + */ + +public class BucketKeyMapReduce extends MapReduce implements Iterable { + + private final Object inputsLock = new Object(); + private final Collection inputs = new LinkedList(); + + /** + * @param client + */ + public BucketKeyMapReduce(RawClient client) { + super(client); + } + + /** + * Add a bucket, key, keydata to the list of inputs for the m/r query + * + * @param bucket + * @param key + * @param keyData + * @return this + */ + public BucketKeyMapReduce addInput(String bucket, String key, String keyData) { + synchronized (inputsLock) { + inputs.add(new String[] {bucket, key, keyData}); + } + + return this; + } + + /** + * Add a bucket, key input to the query + * + * @param bucket + * @param key + * @return + */ + public BucketKeyMapReduce addInput(String bucket, String key) { + synchronized (inputsLock) { + inputs.add(new String[] {bucket, key}); + } + + return this; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + final Collection inputsCopy = new LinkedList(); + + synchronized (inputsLock) { + inputsCopy.addAll(inputs); + } + + return inputsCopy.iterator(); + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.MapReduce#writeInput(org.codehaus.jackson.JsonGenerator) + */ + @Override protected void writeInput(JsonGenerator jsonGenerator) throws IOException { + jsonGenerator.writeObject(this); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java b/src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java new file mode 100644 index 000000000..2e8dadcfb --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java @@ -0,0 +1,133 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.annotate.JsonProperty; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.newapi.query.filter.KeyFilter; + +/** + * @author russell + * + */ +public class BucketMapReduce extends MapReduce implements Iterable { + + private final String bucket; + private final Object keyFiltersLock = new Object(); + private final Collection keyFilters; + + public BucketMapReduce(final RawClient client, String bucket) { + super(client); + this.bucket = bucket; + this.keyFilters = new LinkedList(); + } + + public BucketMapReduce(final RawClient client, String bucket, KeyFilter keyFilter) { + super(client); + this.bucket = bucket; + this.keyFilters = new LinkedList(); + this.keyFilters.add(keyFilter); + } + + public BucketMapReduce(final RawClient client, String bucket, Collection keyFilters) { + super(client); + this.bucket = bucket; + this.keyFilters = new LinkedList(keyFilters); + } + + /** + * @return the bucket + */ + public String getBucket() { + return bucket; + } + + /** + * Copy iterator. Does not read or write through to internal BucketInput + * state. + */ + public Iterator iterator() { + final Collection copyFilters = new LinkedList(); + + synchronized (keyFiltersLock) { + copyFilters.addAll(keyFilters); + } + + return copyFilters.iterator(); + } + + public BucketMapReduce addKeyFilters(KeyFilter... keyFilters) { + final Collection filters = Arrays.asList(keyFilters); + + synchronized (keyFiltersLock) { + this.keyFilters.addAll(filters); + } + + return this; + } + + public BucketMapReduce addKeyFilter(KeyFilter keyFilter) { + synchronized (keyFiltersLock) { + this.keyFilters.add(keyFilter); + } + + return this; + } + + /** + * @return + */ + private boolean hasFilters() { + synchronized (keyFiltersLock) { + return !keyFilters.isEmpty(); + } + } + + private Collection getKeyFilters() { + final Collection filters = new LinkedList(); + + for (KeyFilter filter : this) { + filters.add(filter.asArray()); + } + + return filters; + } + + /* + * (non-Javadoc) + * + * @see + * com.basho.riak.newapi.query.MapReduce#writeInput(org.codehaus.jackson + * .JsonGenerator) + */ + @Override protected void writeInput(JsonGenerator jsonGenerator) throws IOException { + if (hasFilters()) { + jsonGenerator.writeObject(new Object() { + @SuppressWarnings("unused") @JsonProperty String bucket = getBucket(); + @SuppressWarnings("unused") @JsonProperty Collection key_filters = getKeyFilters(); + }); + + } else { + jsonGenerator.writeString(bucket); + } + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/LinkPhase.java b/src/main/java/com/basho/riak/newapi/query/LinkPhase.java new file mode 100644 index 000000000..7ec40c6b3 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/LinkPhase.java @@ -0,0 +1,74 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +/** + * @author russell + * + */ +public class LinkPhase implements MapReducePhase { + + private final String bucket; + private final String tag; + private final boolean keep; + + /** + * @param bucket + * @param tag + * @param keep + */ + public LinkPhase(String bucket, String tag, boolean keep) { + this.bucket = bucket; + this.tag = tag; + this.keep = keep; + } + + /** + * @param bucket + * @param tag + */ + public LinkPhase(String bucket, String tag) { + this.bucket = bucket; + this.tag = tag; + this.keep = false; + } + + /** + * @return the bucket + */ + public String getBucket() { + return bucket; + } + + /** + * @return the tag + */ + public String getTag() { + return tag; + } + + /** + * @return whether the result is kept or just passed to the next phase. + */ + public boolean isKeep() { + return keep; + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.MapReducePhase#getType() + */ + public PhaseType getType() { + return PhaseType.LINK; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/MapPhase.java b/src/main/java/com/basho/riak/newapi/query/MapPhase.java new file mode 100644 index 000000000..7df5b5de5 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/MapPhase.java @@ -0,0 +1,102 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import com.basho.riak.newapi.query.functions.Function; + +/** + * A Map Phase of a Map/Reduce job spec. + * + * @author russell + * + */ +public class MapPhase implements MapReducePhase { + + private final Function phaseFunction; + private final boolean keep; + private final Object arg; // TODO object? you sure? + + /** + * @param phaseFunction + * @param arg + * @param keepResult + */ + public MapPhase(Function phaseFunction, Object arg, boolean keepResult) { + this.phaseFunction = phaseFunction; + this.arg = arg; + this.keep = keepResult; + } + + /** + * @param phaseFunction + * @param arg + */ + public MapPhase(Function phaseFunction, Object arg) { + this.phaseFunction = phaseFunction; + this.arg = arg; + this.keep = false; + } + + /** + * @param phaseFunction + * @param arg + */ + public MapPhase(Function phaseFunction) { + this.phaseFunction = phaseFunction; + this.arg = null; + this.keep = false; + } + + /** + * @param phaseFunction + * @param arg + */ + public MapPhase(Function phaseFunction, boolean keep) { + this.phaseFunction = phaseFunction; + this.arg = null; + this.keep = keep; + } + + /** + * @return the phaseFunction + */ + public Function getPhaseFunction() { + return phaseFunction; + } + + /** + * @return the keep + */ + public boolean isKeep() { + return keep; + } + + /** + * @return the arg + */ + public Object getArg() { + return arg; + } + + public static MapPhase map(Function function, Object arg, boolean keep) { + return new MapPhase(function, arg, keep); + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.MapReducePhase#getType() + */ + public PhaseType getType() { + return PhaseType.MAP; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduce.java b/src/main/java/com/basho/riak/newapi/query/MapReduce.java index f1f4ac9a8..9b3e05cce 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduce.java +++ b/src/main/java/com/basho/riak/newapi/query/MapReduce.java @@ -13,14 +13,40 @@ */ package com.basho.riak.newapi.query; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedList; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.ObjectMapper; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.operations.RiakOperation; +import com.basho.riak.newapi.query.functions.Function; +import com.basho.riak.newapi.query.serialize.FunctionToJson; /** * @author russell * */ -public class MapReduce implements RiakOperation { +public abstract class MapReduce implements RiakOperation { + + private final RawClient client; + + private Collection phases = new LinkedList(); + private Long timeout; + + /** + * @param client + */ + public MapReduce(RawClient client) { + this.client = client; + } /* * (non-Javadoc) @@ -28,7 +54,174 @@ public class MapReduce implements RiakOperation { * @see com.basho.riak.client.RiakOperation#execute() */ public MapReduceResult execute() throws RiakException { - return null; + final String strSpec = writeSpec(); + MapReduceSpec spec = new MapReduceSpec(strSpec); + try { + return client.mapReduce(spec); + } catch (IOException e) { + throw new RiakException(e); + } + } + + /** + * Creates the JSON string + * + * @return a String of JSON + * @throws RiakException + */ + private String writeSpec() throws RiakException { + + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + JsonGenerator jg = new JsonFactory().createJsonGenerator(out, JsonEncoding.UTF8); + jg.setCodec(new ObjectMapper()); + + jg.writeStartObject(); + + jg.writeFieldName("inputs"); + writeInput(jg); + + jg.writeFieldName("query"); + jg.writeStartArray(); + + writePhases(jg); + + jg.writeEndArray(); + if (timeout != null) { + jg.writeNumberField("timeout", timeout); + } + + jg.writeEndObject(); + jg.flush(); + + return out.toString("UTF8"); + } catch (IOException e) { + throw new RiakException(e); + } + + } + + /** + * @param jg + * a {@link JsonGenerator} + */ + private void writePhases(JsonGenerator jg) throws IOException { + writeMapReducePhases(jg); + } + + /** + * @param jg + */ + private void writeMapReducePhases(JsonGenerator jg) throws IOException { + synchronized (phases) { + for (MapReducePhase phase : phases) { + jg.writeStartObject(); + jg.writeFieldName(phase.getType().toString()); + jg.writeStartObject(); + + switch (phase.getType()) { + case MAP: + case REDUCE: + FunctionToJson.newWriter(((MapPhase) phase).getPhaseFunction(), jg).write(); + break; + case LINK: + jg.writeStringField("bucket", ((LinkPhase) phase).getBucket()); + jg.writeStringField("tag", ((LinkPhase) phase).getTag()); + break; + } + + jg.writeBooleanField("keep", phase.isKeep()); + jg.writeEndObject(); + jg.writeEndObject(); + } + } + } + + public MapReduce timeout(long timeout) { + this.timeout = timeout; + return this; + } + + public MapReduce addMapPhase(Function phaseFunction, boolean keep) { + synchronized (phases) { + phases.add(new MapPhase(phaseFunction, keep)); + } + + return this; + } + + public MapReduce addMapPhase(Function phaseFunction, Object arg, boolean keep) { + synchronized (phases) { + phases.add(new MapPhase(phaseFunction, arg, keep)); + } + + return this; + } + + public MapReduce addMapPhase(Function phaseFunction, Object arg) { + synchronized (phases) { + phases.add(new MapPhase(phaseFunction, arg)); + } + + return this; + } + + public MapReduce addMapPhase(Function phaseFunction) { + synchronized (phases) { + phases.add(new MapPhase(phaseFunction)); + } + + return this; + } + + public MapReduce addReducePhase(Function phaseFunction, boolean keep) { + synchronized (phases) { + phases.add(new ReducePhase(phaseFunction, keep)); + } + + return this; + } + + public MapReduce addReducePhase(Function phaseFunction, Object arg, boolean keep) { + synchronized (phases) { + phases.add(new ReducePhase(phaseFunction, arg, keep)); + } + + return this; + } + + public MapReduce addReducePhase(Function phaseFunction, Object arg) { + synchronized (phases) { + phases.add(new ReducePhase(phaseFunction, arg)); + } + + return this; + } + + public MapReduce addReducePhase(Function phaseFunction) { + synchronized (phases) { + phases.add(new ReducePhase(phaseFunction)); + } + + return this; + } + + public MapReduce addLinkPhase(String bucket, String tag, boolean keep) { + synchronized (phases) { + phases.add(new LinkPhase(bucket, tag, keep)); + } + + return this; + } + + public MapReduce addLinkPhase(String bucket, String tag) { + synchronized (phases) { + phases.add(new LinkPhase(bucket, tag)); + } + + return this; } -} + protected abstract void writeInput(JsonGenerator jsonGenerator) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/query/MapReducePhase.java b/src/main/java/com/basho/riak/newapi/query/MapReducePhase.java new file mode 100644 index 000000000..6dc460f21 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/MapReducePhase.java @@ -0,0 +1,39 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +/** + * @author russell + * + */ +public interface MapReducePhase { + + public enum PhaseType { + LINK("link"), MAP("map"), REDUCE("reduce"); + + private final String phaseName; + + private PhaseType(String phaseName) { + this.phaseName = phaseName; + } + + public String toString() { + return this.phaseName; + } + }; + + boolean isKeep(); + + PhaseType getType(); +} diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java index c7c101b6c..0b2778542 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java +++ b/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java @@ -14,7 +14,8 @@ package com.basho.riak.newapi.query; import java.util.Collection; -import java.util.Map; + +import com.basho.riak.newapi.convert.ConversionException; /** * @author russell @@ -30,15 +31,7 @@ public interface MapReduceResult { * A Java type to map the result too. * @return a Collection of T. */ - Collection getResult(T resultType); - - /** - * A Collection of results bound to Map where each result is - * like a C Struct. - * - * @return - */ - Collection> getResult(); + Collection getResult(Class resultType) throws ConversionException; /** * The raw JSON string of the result diff --git a/src/main/java/com/basho/riak/newapi/query/ReducePhase.java b/src/main/java/com/basho/riak/newapi/query/ReducePhase.java new file mode 100644 index 000000000..72cd95a1c --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/ReducePhase.java @@ -0,0 +1,66 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +import com.basho.riak.newapi.query.functions.Function; + +/** + * A reduce phase of a MapReduce job spec. Just a tag class. + * + * @author russell + * + */ +public class ReducePhase extends MapPhase { + + /** + * @param phaseFunction + * @param arg + * @param keepResult + */ + public ReducePhase(Function phaseFunction, Object arg, boolean keepResult) { + super(phaseFunction, arg, keepResult); + } + + /** + * @param phaseFunction + * @param arg + */ + public ReducePhase(Function phaseFunction, Object arg) { + super(phaseFunction, arg); + } + + /** + * @param phaseFunction + * @param keep + */ + public ReducePhase(Function phaseFunction, boolean keep) { + super(phaseFunction, keep); + } + + /** + * @param phaseFunction + */ + public ReducePhase(Function phaseFunction) { + super(phaseFunction); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.query.MapPhase#getType() + */ + @Override public PhaseType getType() { + return PhaseType.REDUCE; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java new file mode 100644 index 000000000..ef6ec7e1f --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java @@ -0,0 +1,31 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +/** + * @author russell + * + */ +public abstract class AbstractKeyFilter implements KeyFilter { + + + public abstract String getFilter(); + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.KeyFilter#asArray() + */ + public String[] asArray() { + return new String[] { getFilter() }; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java new file mode 100644 index 000000000..a439925d8 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java @@ -0,0 +1,62 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +import java.util.Collection; +import java.util.LinkedList; + +/** + * @author russell + * + */ +public abstract class AbstractLogicalFilter implements LogicalFilter { + + + private final Collection filters = new LinkedList(); + + public AbstractLogicalFilter(KeyFilter... filters) { + synchronized (this.filters) { + for (KeyFilter filter : filters) { + this.filters.add(filter.asArray()); + } + } + } + + public AbstractLogicalFilter add(KeyFilter filter) { + synchronized (filter) { + filters.add(filter.asArray()); + } + return this; + } + + public Object[] asArray() { + + int length = 0; + synchronized (filters) { + length = filters.size(); + } + + final Object[] merged = new Object[length + 1]; + merged[0] = getName(); + + synchronized (filters) { + System.arraycopy(filters.toArray(), 0, merged, 1, filters.size()); + } + + return merged; + } + + protected abstract String getName(); + +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java new file mode 100644 index 000000000..65d9b54be --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class BetweenFilter implements KeyFilter { + private static final String NAME = "between"; + + private final Object[] filter; + + public BetweenFilter(String from, String to) { + filter = new String[] { NAME, from, to }; + } + + public BetweenFilter(int from, int to) { + filter = new Object[] { NAME, from, to }; + } + + public BetweenFilter(long from, long to) { + filter = new Object[] { NAME, from, to }; + } + + public BetweenFilter(double from, double to) { + filter = new Object[] { NAME, from, to }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java new file mode 100644 index 000000000..e782cf438 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java @@ -0,0 +1,29 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class EndsWithFilter implements KeyFilter { + + private static final String NAME = "ends_with"; + private final String[] filter; + + public EndsWithFilter(String endsWith) { + filter = new String[] {NAME, endsWith}; + } + + public String[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java new file mode 100644 index 000000000..3185cdd4c --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class EqualToFilter implements KeyFilter { + private final static String NAME = "eq"; + private final Object[] filter; + + public EqualToFilter(String equalTo) { + filter = new String[] { NAME, equalTo }; + } + + public EqualToFilter(int equalTo) { + filter = new Object[] { NAME, equalTo }; + } + + public EqualToFilter(double equalTo) { + filter = new Object[] { NAME, equalTo }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java new file mode 100644 index 000000000..90d792091 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +public class FloatToStringFilter extends AbstractKeyFilter { + + private static final String NAME = "float_to_string"; + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java new file mode 100644 index 000000000..a49d8fdfd --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +public class GreaterThanFilter implements KeyFilter { + + private static final String NAME = "greater_than"; + private final Object[] filter; + + public GreaterThanFilter(String greaterThan) { + filter = new String[] { NAME, greaterThan }; + } + + public GreaterThanFilter(int greaterThan) { + filter = new Object[] { NAME, greaterThan }; + } + + public GreaterThanFilter(double greaterThan) { + filter = new Object[] { NAME, greaterThan }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java new file mode 100644 index 000000000..ad9b4408f --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class GreaterThanOrEqualFilter implements KeyFilter { + private static final String NAME = "greater_than_or_eq"; + private final Object[] filter; + + public GreaterThanOrEqualFilter(String greaterThanOrEq) { + filter = new String[] {NAME, greaterThanOrEq}; + } + + public GreaterThanOrEqualFilter(int greaterThanOrEq) { + filter = new Object[] {NAME, greaterThanOrEq}; + } + + public GreaterThanOrEqualFilter(double greaterThanOrEq) { + filter = new Object[] {NAME, greaterThanOrEq}; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java new file mode 100644 index 000000000..a030e955d --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java @@ -0,0 +1,29 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class IntToStringFilter extends AbstractKeyFilter { + + private static final String NAME = "int_to_string"; + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return NAME; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java b/src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java similarity index 80% rename from src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java rename to src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java index 9fb0fd6da..482ecf91d 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduceSpec.java +++ b/src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java @@ -11,14 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.newapi.query.filter; + /** - * A Map Reduce Query run it via {@link RiakClient#mapReduce(MapReduceSpec)} - * * @author russell * */ -public class MapReduceSpec { - +public interface KeyFilter { + Object[] asArray(); } diff --git a/src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java new file mode 100644 index 000000000..06a467ecc --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +/** + * @author russell + * + */ +public interface KeyTransformFilter extends KeyFilter { + +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java new file mode 100644 index 000000000..727ca1efb --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java @@ -0,0 +1,38 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class LessThanFilter implements KeyFilter { + + private static final String NAME = "less_than"; + + private final Object[] filter; + + public LessThanFilter(String lessThan) { + filter = new String[] {NAME, lessThan}; + } + + public LessThanFilter(int lessThan) { + filter = new Object[] {NAME, lessThan}; + } + + public LessThanFilter(double lessThan) { + filter = new Object[] {NAME, lessThan}; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java new file mode 100644 index 000000000..e29fd9e9c --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class LessThanOrEqualFilter implements KeyFilter { + private static final String NAME = "less_than_eq"; + private final Object[] filter; + + public LessThanOrEqualFilter(String lessThanOrEqualTo) { + filter = new String[] { NAME, lessThanOrEqualTo }; + } + + public LessThanOrEqualFilter(int lessThanOrEqualTo) { + filter = new Object[] { NAME, lessThanOrEqualTo }; + } + + public LessThanOrEqualFilter(double lessThanOrEqualTo) { + filter = new Object[] { NAME, lessThanOrEqualTo }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java new file mode 100644 index 000000000..8230d3277 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class LogicalAndFilter extends AbstractLogicalFilter { + + private static final String NAME = "and"; + + + /** + * @param filters + */ + public LogicalAndFilter(KeyFilter... filters) { + super(filters); + } + + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractLogicalFilter#getName() + */ + @Override protected String getName() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java new file mode 100644 index 000000000..b6573509f --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +/** + * @author russell + * + */ +public interface LogicalFilter extends KeyFilter { + +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java b/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java new file mode 100644 index 000000000..569b21701 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java @@ -0,0 +1,43 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +import java.util.Collection; +import java.util.LinkedList; + +public class LogicalFilterGroup implements LogicalFilter { + + private final Collection filters = new LinkedList(); + + public LogicalFilterGroup(KeyFilter... filters) { + synchronized (this.filters) { + for (KeyFilter filter : filters) { + this.filters.add(filter.asArray()); + } + } + } + + public LogicalFilterGroup add(KeyFilter filter) { + synchronized (filter) { + filters.add(filter.asArray()); + } + return this; + } + + public Object[] asArray() { + synchronized (filters) { + return filters.toArray(); + } + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java new file mode 100644 index 000000000..24db633bc --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java @@ -0,0 +1,33 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class LogicalNotFilter extends AbstractLogicalFilter { + private static final String NAME = "not"; + + /** + * @param filters + */ + public LogicalNotFilter(KeyFilter... filters) { + super(filters); + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractLogicalFilter#getName() + */ + @Override protected String getName() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java new file mode 100644 index 000000000..db74ec34b --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java @@ -0,0 +1,35 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +public class LogicalOrFilter extends AbstractLogicalFilter { + + private static final String NAME = "or"; + + /** + * @param filters + */ + public LogicalOrFilter(KeyFilter... filters) { + super(filters); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.query.filter.AbstractLogicalFilter#getName() + */ + @Override protected String getName() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java new file mode 100644 index 000000000..f8d0f8402 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java @@ -0,0 +1,29 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class MatchFilter implements KeyFilter { + + private static final String NAME = "matches"; + private final String[] filter; + + public MatchFilter(String matchFilter) { + filter = new String[] { NAME, matchFilter }; + } + + public String[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java new file mode 100644 index 000000000..da17e3e68 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class NotEqualToFilter implements KeyFilter { + private final static String NAME = "neq"; + private final Object[] filter; + + public NotEqualToFilter(String equalTo) { + filter = new String[] { NAME, equalTo }; + } + + public NotEqualToFilter(int equalTo) { + filter = new Object[] { NAME, equalTo }; + } + + public NotEqualToFilter(double equalTo) { + filter = new Object[] { NAME, equalTo }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java new file mode 100644 index 000000000..f4fb69db1 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java @@ -0,0 +1,69 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +import java.util.Set; + +import org.json.JSONException; + +public class SetMemberFilter implements KeyFilter { + + private static final String NAME = "set_member"; + private final Object[] filter; + + + public SetMemberFilter(String...setMembers) { + filter = new String[setMembers.length + 1]; + int cnt = 0; + filter[cnt] = NAME; + + for (String setMember : setMembers) { + filter[++cnt] = setMember; + } + } + + public SetMemberFilter(Set setMembers) { + filter = new String[setMembers.size() + 1]; + int cnt = 0; + filter[cnt] = NAME; + + for (String setMember : setMembers) { + filter[++cnt] = setMember; + } + } + + public SetMemberFilter(int[] setMembers) { + filter = new Object[setMembers.length + 1]; + int cnt = 0; + filter[cnt] = NAME; + + for (int setMember : setMembers) { + filter[++cnt] = setMember; + } + } + + public SetMemberFilter(double[] setMembers) throws JSONException { + filter = new Object[setMembers.length + 1]; + int cnt = 0; + filter[cnt] = NAME; + + for (double setMember : setMembers) { + filter[++cnt] = setMember; + } + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java new file mode 100644 index 000000000..5a55375dc --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class SimilarToFilter implements KeyFilter { + private static final String NAME = "similar_to"; + private final Object[] filter; + + public SimilarToFilter(String similarTo, int maxEditDistance) { + filter = new Object[] { NAME, similarTo, maxEditDistance }; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java new file mode 100644 index 000000000..ba7ebc233 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java @@ -0,0 +1,29 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class StartsWithFilter implements KeyFilter { + + private static final String NAME = "starts_with"; + private final String[] filter; + + public StartsWithFilter(String startsWithFilter) { + filter = new String[] { NAME, startsWithFilter }; + } + + public String[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java new file mode 100644 index 000000000..57d670df4 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java @@ -0,0 +1,26 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class StringToFloatFilter extends AbstractKeyFilter { + private static final String NAME = "string_to_float"; + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java new file mode 100644 index 000000000..db311cfbf --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java @@ -0,0 +1,27 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class StringToIntFilter extends AbstractKeyFilter { + + private static final String NAME = "string_to_int"; + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return NAME; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java new file mode 100644 index 000000000..dcd013a70 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java @@ -0,0 +1,27 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class ToLowerFilter extends AbstractKeyFilter { + + private static final String FILTER = "to_lower"; + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return FILTER; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java new file mode 100644 index 000000000..f9dbf3cd5 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java @@ -0,0 +1,28 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + + +public class ToUpperFilter extends AbstractKeyFilter { + + private static final String FILTER = "to_upper"; + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.AbstractKeyFilter#getFilter() + */ + @Override public String getFilter() { + return FILTER; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java new file mode 100644 index 000000000..08389b391 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java @@ -0,0 +1,29 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + + +public class TokenizeFilter implements KeyTransformFilter { + + private static final String NAME = "tokenize"; + private final Object[] filter; + + public TokenizeFilter(String separator, int tokenNum) { + filter = new Object[] {NAME, separator, tokenNum}; + } + + public Object[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java b/src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java new file mode 100644 index 000000000..15fabd951 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java @@ -0,0 +1,26 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +public class UrlDecodeFilter implements KeyTransformFilter { + + private static final String[] filter = new String[] { "urldecode" }; + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.filter.KeyFilter#asArray() + */ + public String[] asArray() { + return filter.clone(); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java new file mode 100644 index 000000000..c9009ddf5 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.newapi.query.functions; + +/** + * Tag interface for anonymous functions. + * + * @author russell + * + */ +public interface AnonymousFunction extends Function { + +} diff --git a/src/main/java/com/basho/riak/newapi/query/functions/Function.java b/src/main/java/com/basho/riak/newapi/query/functions/Function.java new file mode 100644 index 000000000..2a62d24bf --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/functions/Function.java @@ -0,0 +1,22 @@ +/* + * This file is provided 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.basho.riak.newapi.query.functions; + +/** + * @author russell + * + */ +public interface Function { + +} diff --git a/src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java new file mode 100644 index 000000000..c3b4b8ecc --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java @@ -0,0 +1,47 @@ +/* + * This file is provided 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.basho.riak.newapi.query.functions; + +/** + * A JS function that is stored in a Riak bucket/key location + * @author russell + * + */ +public class JSBucketKeyFunction implements AnonymousFunction { + + private final String bucket; + private final String key; + /** + * @param bucket + * @param key + */ + public JSBucketKeyFunction(String bucket, String key) { + this.bucket = bucket; + this.key = key; + } + /** + * @return the bucket + */ + public String getBucket() { + return bucket; + } + /** + * @return the key + */ + public String getKey() { + return key; + } + + +} diff --git a/src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java new file mode 100644 index 000000000..abc71a2c6 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java @@ -0,0 +1,42 @@ +/* + * This file is provided 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.basho.riak.newapi.query.functions; + +/** + * An anonymous JavaScript function. + * + * @author russell + * + */ +public class JSSourceFunction implements AnonymousFunction { + + private final String source; + + /** + * JavaScript code. + * + * @param source + */ + public JSSourceFunction(String source) { + this.source = source; + } + + /** + * @return the source + */ + public String getSource() { + return source; + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java similarity index 98% rename from src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java rename to src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java index a6f69f1cc..d2aafd899 100644 --- a/src/main/java/com/basho/riak/newapi/query/NamedErlangFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.newapi.query.functions; /** * Models a named erlang function. diff --git a/src/main/java/com/basho/riak/newapi/query/NamedFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java similarity index 86% rename from src/main/java/com/basho/riak/newapi/query/NamedFunction.java rename to src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java index a3cea6951..1df65f7b3 100644 --- a/src/main/java/com/basho/riak/newapi/query/NamedFunction.java +++ b/src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.newapi.query.functions; /** * Tag interface. @@ -19,6 +19,6 @@ * @author russell * */ -public interface NamedFunction { +public interface NamedFunction extends Function { } diff --git a/src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java b/src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java new file mode 100644 index 000000000..d5bc415bf --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java @@ -0,0 +1,39 @@ +/* + * This file is provided 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.basho.riak.newapi.query.functions; + +/** + * A named function that is a JS built in function. + * + * @author russell + * + */ +public class NamedJSFunction implements NamedFunction { + + private final String function; + + /** + * @param function + */ + public NamedJSFunction(String function) { + this.function = function; + } + + /** + * @return the function + */ + public String getFunction() { + return function; + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java b/src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java new file mode 100644 index 000000000..686000607 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java @@ -0,0 +1,46 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.newapi.query.functions.Function; +import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; +import com.basho.riak.newapi.query.functions.JSSourceFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedJSFunction; + +/** + * Helper to write a Function to a JsonGenerator + * + * @author russell + * + */ +public class FunctionToJson { + + public static FunctionWriter newWriter(Function function, JsonGenerator jsonGenerator) { + // eugh + if (function instanceof NamedErlangFunction) { + return new NamedErlangFunctionWriter((NamedErlangFunction) function, jsonGenerator); + } else if (function instanceof NamedJSFunction) { + return new NamedJSFunctionWriter((NamedJSFunction) function, jsonGenerator); + } else if (function instanceof JSSourceFunction) { + return new JSSourceFunctionWriter((JSSourceFunction) function, jsonGenerator); + } else if (function instanceof JSBucketKeyFunction) { + return new JSBucketKeyFunctionWriter((JSBucketKeyFunction) function, jsonGenerator); + } + + throw new IllegalArgumentException("No writer for function type " + function.getClass()); + } +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java b/src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java new file mode 100644 index 000000000..00fc056f1 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java @@ -0,0 +1,24 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import java.io.IOException; + +/** + * @author russell + * + */ +public interface FunctionWriter { + void write() throws IOException; +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java b/src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java new file mode 100644 index 000000000..816fac461 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java @@ -0,0 +1,49 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; + +/** + * @author russell + * + */ +public class JSBucketKeyFunctionWriter implements FunctionWriter { + + private final JSBucketKeyFunction function; + private final JsonGenerator jsonGenerator; + + /** + * @param function + * @param jsonGenerator + */ + public JSBucketKeyFunctionWriter(JSBucketKeyFunction function, JsonGenerator jsonGenerator) { + this.function = function; + this.jsonGenerator = jsonGenerator; + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.serialize.FunctionWriter#write() + */ + public void write() throws IOException { + jsonGenerator.writeStringField("language", "javascript"); + jsonGenerator.writeStringField("bucket", function.getBucket()); + jsonGenerator.writeStringField("key", function.getKey()); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java b/src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java new file mode 100644 index 000000000..097a247e9 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java @@ -0,0 +1,47 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.newapi.query.functions.JSSourceFunction; + +/** + * @author russell + * + */ +public class JSSourceFunctionWriter implements FunctionWriter { + + private final JSSourceFunction function; + private final JsonGenerator jsonGenerator; + /** + * @param function + * @param jsonGenerator + */ + public JSSourceFunctionWriter(JSSourceFunction function, JsonGenerator jsonGenerator) { + this.function = function; + this.jsonGenerator = jsonGenerator; + } + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.serialize.FunctionWriter#write() + */ + public void write() throws IOException { + jsonGenerator.writeStringField("language", "javascript"); + jsonGenerator.writeStringField("source", function.getSource()); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java b/src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java new file mode 100644 index 000000000..3c25c8ddf --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java @@ -0,0 +1,51 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.newapi.query.functions.NamedErlangFunction; + +/** + * @author russell + * + */ +public class NamedErlangFunctionWriter implements FunctionWriter { + + private final NamedErlangFunction function; + private final JsonGenerator jsonGenerator; + + /** + * @param function + * @param jsonGenerator + */ + public NamedErlangFunctionWriter(NamedErlangFunction function, JsonGenerator jsonGenerator) { + this.function = function; + this.jsonGenerator = jsonGenerator; + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.query.serialize.FunctionWriter#write() + */ + public void write() throws IOException { + jsonGenerator.writeStringField("language", "erlang"); + jsonGenerator.writeStringField("module", function.getMod()); + jsonGenerator.writeStringField("function", function.getFun()); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java b/src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java new file mode 100644 index 000000000..4a550bc40 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java @@ -0,0 +1,49 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; + +import com.basho.riak.newapi.query.functions.NamedJSFunction; + +/** + * @author russell + * + */ +public class NamedJSFunctionWriter implements FunctionWriter { + + private final NamedJSFunction function; + private final JsonGenerator jsonGenerator; + + /** + * @param function + * @param jsonGenerator + */ + public NamedJSFunctionWriter(NamedJSFunction function, JsonGenerator jsonGenerator) { + this.function = function; + this.jsonGenerator = jsonGenerator; + } + + + /* (non-Javadoc) + * @see com.basho.riak.newapi.query.serialize.FunctionWriter#write() + */ + public void write() throws IOException { + jsonGenerator.writeStringField("language", "javascript"); + jsonGenerator.writeStringField("name", function.getFunction()); + } + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java index b9b27200c..c2eb72c2a 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java @@ -23,7 +23,7 @@ import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.query.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java new file mode 100644 index 000000000..722e49e1d --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -0,0 +1,208 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.type.TypeFactory; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.basho.riak.newapi.DefaultRiakLink; +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.RiakLink; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.DomainBucket; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.filter.LessThanFilter; +import com.basho.riak.newapi.query.filter.StringToIntFilter; +import com.basho.riak.newapi.query.filter.TokenizeFilter; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedJSFunction; +import com.megacorp.commerce.GoogleStockDataItem; + +/** + * @author russell + * + */ +public abstract class ITestMapReduce { + protected RiakClient client; + + @Before public void setUp() throws RiakException { + client = getClient(); + } + + /** + * @return + * @throws RiakException + */ + protected abstract RiakClient getClient() throws RiakException; + + public static String BUCKET_NAME = "mr_test_java"; + public static int TEST_ITEMS = 200; + + @BeforeClass public static void setup() throws RiakException { + final RiakClient client = RiakFactory.pbcClient(); + final Bucket b = client.createBucket(BUCKET_NAME).execute(); + + for (int i = 0; i < TEST_ITEMS; i++) { + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(b, "java_" + Integer.toString(i)); + builder.withContentType("text/plain").withValue(Integer.toString(i)); + if (i < TEST_ITEMS - 1) { + RiakLink link = new DefaultRiakLink(BUCKET_NAME, "java_" + Integer.toString(i + 1), "test"); + List links = new ArrayList(1); + links.add(link); + builder.withLinks(links); + } + + b.store(builder.build()).withConverter(new Converter() { + + public RiakObject toDomain(RiakObject riakObject) throws ConversionException { + return riakObject; + } + + public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { + return domainObject; + } + }).execute(); + } + } + + @AfterClass public static void teardown() throws RiakException { + final RiakClient client = RiakFactory.pbcClient(); + final Bucket b = client.fetchBucket(BUCKET_NAME).execute(); + + for (int i = 0; i < TEST_ITEMS; i++) { + b.delete("java_" + Integer.toString(i)).execute(); + } + } + + @Test public void doLinkMapReduce() throws RiakException { + MapReduceResult result = client.mapReduce(BUCKET_NAME) + .addLinkPhase(BUCKET_NAME, "test", false) + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), false) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) + .execute(); + + assertNotNull(result); + Collection items = result.getResult(Integer.class); + assertEquals(TEST_ITEMS - 1, items.size()); + } + + @Test public void doErlangMapReduce() throws RiakException { + MapReduceResult result = client.mapReduce(BUCKET_NAME) + .addMapPhase(new NamedErlangFunction("riak_kv_mapreduce","map_object_value")) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce","reduce_string_to_integer")) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce","reduce_sort"),true) + .execute(); + + assertNotNull(result); + List items = new LinkedList(result.getResult(Integer.class)); + assertEquals(TEST_ITEMS, items.size()); + assertEquals(new Integer(0), items.get(0)); + assertEquals(new Integer(73), items.get(73)); + assertEquals(new Integer(197), items.get(197)); + } + + @Test public void doJavascriptMapReduce() throws RiakException { + MapReduceResult result = client.mapReduce(BUCKET_NAME) + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), false) + .addReducePhase(new NamedJSFunction("Riak.reduceNumericSort"), true) + .execute(); + + assertNotNull(result); + List items = new LinkedList(result.getResult(Integer.class)); + assertEquals(TEST_ITEMS, items.size()); + assertEquals(new Integer(0), items.get(0)); + assertEquals(new Integer(73), items.get(73)); + assertEquals(new Integer(197), items.get(197)); + } + + @Test public void doKeyFilterMapReduce() throws RiakException { + MapReduceResult result = client.mapReduce(BUCKET_NAME) + .addKeyFilter(new TokenizeFilter("_", 2)) + .addKeyFilter(new StringToIntFilter()) + .addKeyFilter(new LessThanFilter(50)) + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson")) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce","reduce_sort"), true) + .execute(); + + assertNotNull(result); + List items = new LinkedList(result.getResult(Integer.class)); + assertEquals(50, items.size()); + assertEquals(new Integer(0), items.get(0)); + assertEquals(new Integer(23), items.get(23)); + assertEquals(new Integer(49), items.get(49)); + } + + @Test public void mapResultToDomainObject() throws IOException, RiakException { + // set up data + final String json = "[{\"Date\":\"2010-01-04\",\"Open\":626.95,\"High\":629.51,\"Low\":624.24,\"Close\":626.75,\"Volume\":1956200,\"Adj. Close\":626.75}," + + "{\"Date\":\"2010-01-05\",\"Open\":627.18,\"High\":627.84,\"Low\":621.54,\"Close\":623.99,\"Volume\":3004700,\"Adj. Close\":623.99}," + + "{\"Date\":\"2010-01-06\",\"Open\":625.86,\"High\":625.86,\"Low\":606.36,\"Close\":608.26,\"Volume\":3978700,\"Adj. Close\":608.26}," + + "{\"Date\":\"2010-01-07\",\"Open\":609.4,\"High\":610,\"Low\":592.65,\"Close\":594.1,\"Volume\":6414300,\"Adj. Close\":594.1}," + + "{\"Date\":\"2010-01-08\",\"Open\":592,\"High\":603.25,\"Low\":589.11,\"Close\":602.02,\"Volume\":4724300,\"Adj. Close\":602.02}]"; + + final LinkedList expected = new ObjectMapper() + .readValue(json, + TypeFactory.collectionType(LinkedList.class, GoogleStockDataItem.class)); + + final Bucket b = client.createBucket("goog").execute(); + final DomainBucket bucket = DomainBucket.builder(b, GoogleStockDataItem.class).build(); + + for(GoogleStockDataItem i : expected) { + bucket.store(i); + } + + // perform test + + MapReduceResult result = client.mapReduce() + .addInput("goog","2010-01-04") + .addInput("goog","2010-01-05") + .addInput("goog","2010-01-06") + .addInput("goog","2010-01-07") + .addInput("goog","2010-01-08") + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true) + .execute(); + + LinkedList actual = new LinkedList( result.getResult(GoogleStockDataItem.class) ); + assertNotNull(actual); + assertEquals(expected.size(), actual.size()); + + assertTrue(expected.containsAll(actual)); + + //teardown + for(String k : b.keys()) { + bucket.delete(k); + } + } +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java new file mode 100644 index 000000000..7d95a7991 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestMapReduceHTTP extends ITestMapReduce { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestMapReduce#getClient() + */ + protected RiakClient getClient() throws RiakException { + return RiakFactory.httpClient(); + } +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java new file mode 100644 index 000000000..8edacb110 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; + +/** + * @author russell + * + */ +public class ITestMapReducePB extends ITestMapReduce { + + /* + * (non-Javadoc) + * + * @see com.basho.riak.client.itest.ITestMapReduce#getClient() + */ + protected RiakClient getClient() throws RiakException { + return RiakFactory.pbcClient(); + } +} diff --git a/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java b/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java new file mode 100644 index 000000000..6c79ce3e1 --- /dev/null +++ b/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java @@ -0,0 +1,40 @@ +/* + * This file is provided 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.basho.riak.newapi.query.filter; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * @author russell + * + */ +public class LogicalAndFilterTest { + + /** + * Test method for + * {@link com.basho.riak.newapi.query.filter.LogicalAndFilter#asArray()}. + */ + @Test public void testAsArray() { + final KeyFilter[] filters = new KeyFilter[] { new FloatToStringFilter(), new IntToStringFilter(), + new SetMemberFilter("rita", "sue", "bob") }; + LogicalAndFilter laf = new LogicalAndFilter(filters); + laf.add(new SimilarToFilter("hippo", 2)); + + assertArrayEquals(new Object[] { "and", new FloatToStringFilter().asArray(), new IntToStringFilter().asArray(), + new SetMemberFilter("rita", "sue", "bob").asArray(), new SimilarToFilter("hippo", 2).asArray() }, laf.asArray()); + } + +} diff --git a/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java b/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java new file mode 100644 index 000000000..f64ebe3aa --- /dev/null +++ b/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java @@ -0,0 +1,74 @@ +/* + * This file is provided 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.basho.riak.newapi.query.serialize; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import org.codehaus.jackson.JsonGenerator; +import org.junit.Test; + +import com.basho.riak.newapi.query.functions.Function; +import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; +import com.basho.riak.newapi.query.functions.JSSourceFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.query.functions.NamedJSFunction; + +/** + * @author russell + * + */ +public class FunctionToJsonTest { + + /** + * Tests that the static factory method returns a writer appropriate to the + * function type passed. + * + * @throws Exception + */ + @Test public void correctWriterForFunctionType() throws Exception { + final JsonGenerator jsonGenerator = mock(JsonGenerator.class); + + FunctionWriter fw = FunctionToJson.newWriter(new NamedErlangFunction("mod", "string"), jsonGenerator); + assertTrue(fw instanceof NamedErlangFunctionWriter); + fw.write(); + verify(jsonGenerator, atLeastOnce()).writeStringField(any(String.class), any(String.class)); + reset(jsonGenerator); + + fw = FunctionToJson.newWriter(new JSBucketKeyFunction("b", "k"), jsonGenerator); + assertTrue(fw instanceof JSBucketKeyFunctionWriter); + fw.write(); + verify(jsonGenerator, atLeastOnce()).writeStringField(any(String.class), any(String.class)); + reset(jsonGenerator); + + fw = FunctionToJson.newWriter(new JSSourceFunction("function(x) { alert(\"mooooo!\"); }"), jsonGenerator); + assertTrue(fw instanceof JSSourceFunctionWriter); + fw.write(); + verify(jsonGenerator, atLeastOnce()).writeStringField(any(String.class), any(String.class)); + reset(jsonGenerator); + + fw = FunctionToJson.newWriter(new NamedJSFunction("Riak.mapJson"), jsonGenerator); + assertTrue(fw instanceof NamedJSFunctionWriter); + fw.write(); + verify(jsonGenerator, atLeastOnce()).writeStringField(any(String.class), any(String.class)); + + try { + fw = FunctionToJson.newWriter(new Function() {}, jsonGenerator); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // NO-OP + } + } + +} diff --git a/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java b/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java new file mode 100644 index 000000000..ce535edbe --- /dev/null +++ b/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java @@ -0,0 +1,117 @@ +/* + * This file is provided 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.megacorp.commerce; + +import org.codehaus.jackson.annotate.JsonProperty; + +import com.basho.riak.newapi.convert.RiakKey; + +public class GoogleStockDataItem { + //{"Date":"2010-01-05","Open":627.18,"High":627.84,"Low":621.54,"Close":623.99,"Volume":3004700,"Adj. Close":623.99} + @JsonProperty("Date") + @RiakKey + private String date; + @JsonProperty("Open") + private Double open; + @JsonProperty("High") + private Double high; + @JsonProperty("Low") + private Double low; + @JsonProperty("Close") + private Double close; + @JsonProperty("Volume") + private Long volume; + @JsonProperty("Adj. Close") + private Double adjustedClose; + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((adjustedClose == null) ? 0 : adjustedClose.hashCode()); + result = prime * result + ((close == null) ? 0 : close.hashCode()); + result = prime * result + ((date == null) ? 0 : date.hashCode()); + result = prime * result + ((high == null) ? 0 : high.hashCode()); + result = prime * result + ((low == null) ? 0 : low.hashCode()); + result = prime * result + ((open == null) ? 0 : open.hashCode()); + result = prime * result + ((volume == null) ? 0 : volume.hashCode()); + return result; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof GoogleStockDataItem)) { + return false; + } + GoogleStockDataItem other = (GoogleStockDataItem) obj; + if (adjustedClose == null) { + if (other.adjustedClose != null) { + return false; + } + } else if (!adjustedClose.equals(other.adjustedClose)) { + return false; + } + if (close == null) { + if (other.close != null) { + return false; + } + } else if (!close.equals(other.close)) { + return false; + } + if (date == null) { + if (other.date != null) { + return false; + } + } else if (!date.equals(other.date)) { + return false; + } + if (high == null) { + if (other.high != null) { + return false; + } + } else if (!high.equals(other.high)) { + return false; + } + if (low == null) { + if (other.low != null) { + return false; + } + } else if (!low.equals(other.low)) { + return false; + } + if (open == null) { + if (other.open != null) { + return false; + } + } else if (!open.equals(other.open)) { + return false; + } + if (volume == null) { + if (other.volume != null) { + return false; + } + } else if (!volume.equals(other.volume)) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/src/test/java/com/megacorp/commerce/MergeCartResolver.java b/src/test/java/com/megacorp/commerce/MergeCartResolver.java index b386bb61c..6be455db3 100644 --- a/src/test/java/com/megacorp/commerce/MergeCartResolver.java +++ b/src/test/java/com/megacorp/commerce/MergeCartResolver.java @@ -27,8 +27,6 @@ public ShoppingCart resolve(Collection siblings) throws Unresolved } } - System.out.println("Merged items for " + Thread.currentThread().getName() + " " + items); - final ShoppingCart resolved = new ShoppingCart(userId); return resolved.addItems(items); } From 04c6755552408b346a0ffe9b5b3672cc142d4eab Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 28 Apr 2011 10:17:06 +0100 Subject: [PATCH 015/764] Add VClock to RiakObject's parsed from link walk multipart response The multipart parse code only attempts to pull a vclock header from the respnse header (IE siblings) but does not try and pull the vclock from a multipart link walk response. Attempt to pull the vclock header value from the part if no vclock header exists in the http response headers. --- .../com/basho/riak/client/util/ClientUtils.java | 17 +++++++++++++++++ .../com/basho/riak/client/TestRiakClient.java | 3 ++- .../riak/client/response/TestWalkResponse.java | 6 +++++- .../basho/riak/client/util/TestClientUtils.java | 2 ++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/basho/riak/client/util/ClientUtils.java b/src/main/java/com/basho/riak/client/util/ClientUtils.java index 40657f3d7..86da23a95 100644 --- a/src/main/java/com/basho/riak/client/util/ClientUtils.java +++ b/src/main/java/com/basho/riak/client/util/ClientUtils.java @@ -404,9 +404,13 @@ public static List parseMultipart(RiakClient riak, String bucket, St Map docHeaders, byte[] docBody) { String vclock = null; + boolean siblingVclock = false; if (docHeaders != null) { vclock = docHeaders.get(Constants.HDR_VCLOCK); + if( vclock != null) { + siblingVclock = true; + } } List parts = Multipart.parse(docHeaders, docBody); @@ -414,6 +418,19 @@ public static List parseMultipart(RiakClient riak, String bucket, St if (parts != null) { for (Multipart.Part part : parts) { Map headers = part.getHeaders(); + + // handles the case of link walk multi part responses where the vclock header is in the part not the top response + if (!siblingVclock) { + vclock = headers.get(Constants.HDR_VCLOCK); + } + + if(vclock == null) { + // this should never happen + // exception here to shorten path from bug occurrence + // to bug manifestation + throw new IllegalStateException("no vclock found"); + } + List links = parseLinkHeader(headers.get(Constants.HDR_LINK)); Map usermeta = parseUsermeta(headers); String location = headers.get(Constants.HDR_LOCATION); diff --git a/src/test/java/com/basho/riak/client/TestRiakClient.java b/src/test/java/com/basho/riak/client/TestRiakClient.java index 0a17b13cf..47e56a081 100644 --- a/src/test/java/com/basho/riak/client/TestRiakClient.java +++ b/src/test/java/com/basho/riak/client/TestRiakClient.java @@ -260,7 +260,8 @@ public HttpResponse answer(InvocationOnMock invocation) throws Throwable { final String BODY = "\r\n" + "--BCVLGEKnH0gY7KsH5nW3xnzhYbU\r\n" + "Content-Type: multipart/mixed; boundary=7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + "\r\n" - + "--7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + + "--7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + + "X-Riak-Vclock: vclock\r\n" + "Location: /riak/b/k1\r\n" + "\r\n" + "foo\r\n" diff --git a/src/test/java/com/basho/riak/client/response/TestWalkResponse.java b/src/test/java/com/basho/riak/client/response/TestWalkResponse.java index 627872d52..aeb4ee60b 100644 --- a/src/test/java/com/basho/riak/client/response/TestWalkResponse.java +++ b/src/test/java/com/basho/riak/client/response/TestWalkResponse.java @@ -66,11 +66,13 @@ public class TestWalkResponse { final String BODY = "\r\n" + "--BCVLGEKnH0gY7KsH5nW3xnzhYbU\r\n" + "Content-Type: multipart/mixed; boundary=7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + "\r\n" - + "--7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + + "--7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + + "X-Riak-Vclock: vclock1\r\n" + "Location: /riak/b/k1\r\n" + "\r\n" + "foo\r\n" + "--7Ymillu08Tqzwb9Cm6Bs8OewFd5\r\n" + + "X-Riak-Vclock: vclock2\r\n" + "Location: /riak/b/k2\r\n" + "\r\n" + "bar\r\n" @@ -90,11 +92,13 @@ public class TestWalkResponse { assertEquals("b", impl.getSteps().get(0).get(0).getBucket()); assertEquals("k1", impl.getSteps().get(0).get(0).getKey()); assertEquals("foo", impl.getSteps().get(0).get(0).getValue()); + assertEquals("vclock1", impl.getSteps().get(0).get(0).getVclock()); assertSame(mockRiakClient, impl.getSteps().get(0).get(1).getRiakClient()); assertEquals("b", impl.getSteps().get(0).get(1).getBucket()); assertEquals("k2", impl.getSteps().get(0).get(1).getKey()); assertEquals("bar", impl.getSteps().get(0).get(1).getValue()); + assertEquals("vclock2", impl.getSteps().get(0).get(1).getVclock()); } @Test(expected = RiakResponseRuntimeException.class) public void throws_on_invalid_subpart_content_type() { diff --git a/src/test/java/com/basho/riak/client/util/TestClientUtils.java b/src/test/java/com/basho/riak/client/util/TestClientUtils.java index 4f9f94e39..b84fd8405 100644 --- a/src/test/java/com/basho/riak/client/util/TestClientUtils.java +++ b/src/test/java/com/basho/riak/client/util/TestClientUtils.java @@ -274,6 +274,7 @@ public class TestClientUtils { @Test public void parse_multipart_returns_correct_riak_and_bucket_and_key() { Map headers = new HashMap(); headers.put("content-type", "multipart/mixed; boundary=boundary"); + headers.put("x-riak-vclock", "vclock"); String body = "\r\n--boundary\r\n" + "\r\n" + "--boundary--"; List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, body.getBytes()); @@ -308,6 +309,7 @@ public class TestClientUtils { @Test public void parse_multipart_returns_value() { Map headers = new HashMap(); headers.put("content-type", "multipart/mixed; boundary=boundary"); + headers.put("x-riak-vclock", "vclock"); String body = "\r\n--boundary\r\n" + "\r\n" + "foo\r\n" + "--boundary--"; List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, body.getBytes()); From b6be99ddc4aa44c8db259b83ce1c63125d089f4a Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 29 Apr 2011 14:01:51 +0100 Subject: [PATCH 016/764] Add link walking to both HTTP and PB client adapters Link walking for the PB adapter requires 2 m/r jobs 1. gathers the inputs by walking the links 2. uses the inputs to get the values --- .../com/basho/riak/client/raw/RawClient.java | 13 +- .../riak/client/raw/http/ConversionUtil.java | 53 ++++- .../client/raw/http/HTTPClientAdapter.java | 42 ++-- .../riak/client/raw/pbc/ConversionUtil.java | 181 ++++++++++++++++-- .../riak/client/raw/pbc/PBClientAdapter.java | 125 ++++++++++-- .../riak/client/raw/query/LinkWalkSpec.java | 55 +++++- .../com/basho/riak/newapi/DefaultClient.java | 2 +- .../basho/riak/newapi/DefaultRiakObject.java | 11 +- .../com/basho/riak/newapi/RiakObject.java | 5 +- .../riak/newapi/bucket/DefaultBucket.java | 64 +++---- .../riak/newapi/bucket/DomainBucket.java | 4 +- .../newapi/builders/DomainBucketBuilder.java | 10 +- .../newapi/builders/RiakObjectBuilder.java | 35 +++- .../riak/newapi/convert/ConversionUtil.java | 56 ------ .../riak/newapi/convert/JSONConverter.java | 9 +- .../riak/newapi/operations/DeleteObject.java | 5 +- .../riak/newapi/operations/FetchObject.java | 5 +- .../riak/newapi/operations/StoreObject.java | 5 +- .../com/basho/riak/newapi/query/LinkWalk.java | 78 +++++++- .../riak/client/itest/ITestMapReduce.java | 26 +-- .../newapi/convert/ConversionUtilTest.java | 8 +- .../query/filter/LogicalAndFilterTest.java | 2 +- .../query/serialize/FunctionToJsonTest.java | 9 +- 23 files changed, 575 insertions(+), 228 deletions(-) delete mode 100644 src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index 5acfdc9dc..747f2d849 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -20,7 +20,6 @@ import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.WalkResult; @@ -33,17 +32,17 @@ public interface RawClient { // RiakObject - RiakResponse fetch(Bucket bucket, String key) throws IOException; + RiakResponse fetch(String bucket, String key) throws IOException; - RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException; + RiakResponse fetch(String bucket, String key, int readQuorum) throws IOException; RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOException; void store(RiakObject object) throws IOException; - void delete(Bucket bucket, String key) throws IOException; + void delete(String bucket, String key) throws IOException; - void delete(Bucket bucket, String key, int deleteQuorum) throws IOException; + void delete(String bucket, String key, int deleteQuorum) throws IOException; // Bucket Iterator listBuckets() throws IOException; @@ -55,9 +54,9 @@ public interface RawClient { Iterable listKeys(String bucketName) throws IOException; // Query - WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException; + WalkResult linkWalk(final LinkWalkSpec linkWalkSpec) throws IOException; - MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapReduceTimeoutException; + MapReduceResult mapReduce(final MapReduceSpec spec) throws IOException, MapReduceTimeoutException; /** * If you don't set a client id explicitly at least call this to set one. It diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index dbd8d23e3..904023032 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -18,6 +18,8 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -29,20 +31,25 @@ import com.basho.riak.client.RiakBucketInfo; import com.basho.riak.client.RiakClient; import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.request.RequestMeta; +import com.basho.riak.client.request.RiakWalkSpec; import com.basho.riak.client.response.BucketResponse; import com.basho.riak.client.response.MapReduceResponse; +import com.basho.riak.client.response.WalkResponse; import com.basho.riak.client.util.Constants; import com.basho.riak.newapi.DefaultRiakLink; import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.query.LinkWalkStep; import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.WalkResult; import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.newapi.util.UnmodifiableIterator; /** * @author russell @@ -54,11 +61,11 @@ public class ConversionUtil { * @param bucket * @return */ - static RiakObject[] convert(Collection siblings, Bucket bucket) { + static RiakObject[] convert(Collection siblings) { final Collection results = new ArrayList(); for (com.basho.riak.client.RiakObject object : siblings) { - results.add(convert(object, bucket)); + results.add(convert(object)); } return results.toArray(new RiakObject[results.size()]); @@ -68,9 +75,9 @@ static RiakObject[] convert(Collection sibling * @param object * @return */ - static RiakObject convert(final com.basho.riak.client.RiakObject o, final Bucket bucket) { + static RiakObject convert(final com.basho.riak.client.RiakObject o) { - RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); builder.withValue(o.getValue()); builder.withVClock(nullSafeGetBytes(o.getVclock())); @@ -142,7 +149,7 @@ static RequestMeta convert(StoreMeta storeMeta) { static com.basho.riak.client.RiakObject convert(RiakObject object, final RiakClient client) { com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( client, - object.getBucketName(), + object.getBucket(), object.getKey(), nullSafeGetBytes(object.getValue()), object.getContentType(), @@ -284,4 +291,38 @@ public Collection getResult(Class resultType) throws ConversionExcepti return result; } + /** + * @param linkWalkSpec + * @return a String representation of this walk spec useful to the http.RiakClient + */ + static String convert(LinkWalkSpec linkWalkSpec) { + RiakWalkSpec riakWalkSpec = new RiakWalkSpec(); + for(LinkWalkStep step : linkWalkSpec) { + riakWalkSpec.addStep(step.getBucket(), step.getKey(), step.getKeep().toString()); + } + return riakWalkSpec.toString(); + } + + /** + * Converts a WalkResponse -> WalkResult + * @param walkResponse An http RiakClient WalkResponse + * @return a new api WalkResult + */ + static WalkResult convert(WalkResponse walkResponse) { + final Collection> convertedSteps = new LinkedList>(); + + for(List step : walkResponse.getSteps()) { + final LinkedList objects = new LinkedList(); + for(com.basho.riak.client.RiakObject o : step) { + objects.add(convert(o)); + } + convertedSteps.add(objects); + } + + return new WalkResult() { + public Iterator> iterator() { + return new UnmodifiableIterator>( convertedSteps.iterator() ); + } + }; + } } diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index 448242bbc..7ea68824c 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -33,7 +33,6 @@ import com.basho.riak.client.response.StoreResponse; import com.basho.riak.client.response.WithBodyResponse; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.cap.ClientId; import com.basho.riak.newapi.query.MapReduceResult; @@ -71,8 +70,8 @@ public HTTPClientAdapter(String url) { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String) */ - public RiakResponse fetch(Bucket bucket, String key) throws IOException { - if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + public RiakResponse fetch(String bucket, String key) throws IOException { + if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); @@ -82,9 +81,9 @@ public RiakResponse fetch(Bucket bucket, String key) throws IOException { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } - FetchResponse resp = client.fetch(bucket.getName(), key); + FetchResponse resp = client.fetch(bucket, key); - return handleBodyResponse(bucket, resp); + return handleBodyResponse(resp); } /* @@ -94,8 +93,8 @@ public RiakResponse fetch(Bucket bucket, String key) throws IOException { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ - public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException { - if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + public RiakResponse fetch(String bucket, String key, int readQuorum) throws IOException { + if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( "bucket must not be null and bucket.getName() must not be null or empty " + "or just whitespace."); @@ -105,9 +104,9 @@ public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOEx throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } - FetchResponse resp = client.fetch(bucket.getName(), key, RequestMeta.readParams(readQuorum)); + FetchResponse resp = client.fetch(bucket, key, RequestMeta.readParams(readQuorum)); - return handleBodyResponse(bucket, resp); + return handleBodyResponse(resp); } /** @@ -115,14 +114,14 @@ public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOEx * @param resp * @return */ - private RiakResponse handleBodyResponse(Bucket bucket, WithBodyResponse resp) { + private RiakResponse handleBodyResponse(WithBodyResponse resp) { RiakResponse response = RiakResponse.empty(); RiakObject[] values = new RiakObject[] {}; if (resp.hasSiblings()) { - values = convert(resp.getSiblings(), bucket); + values = convert(resp.getSiblings()); } else if (resp.hasObject()) { - values = new RiakObject[] { convert(resp.getObject(), bucket) }; + values = new RiakObject[] { convert(resp.getObject()) }; } if (values.length > 0) { @@ -143,7 +142,6 @@ public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOExcep if (object == null || object.getBucket() == null) { throw new IllegalArgumentException("cannot store a null RiakObject, or a RiakObject without a bucket"); } - final Bucket bucket = object.getBucket(); RiakResponse response = RiakResponse.empty(); com.basho.riak.client.RiakObject riakObject = convert(object, client); @@ -157,7 +155,7 @@ public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOExcep } if (storeMeta.hasReturnBody() && storeMeta.getReturnBody()) { - response = handleBodyResponse(bucket, resp); + response = handleBodyResponse(resp); } return response; @@ -181,8 +179,8 @@ public void store(RiakObject object) throws IOException { * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket * .Bucket, java.lang.String) */ - public void delete(Bucket bucket, String key) throws IOException { - HttpResponse resp = client.delete(bucket.getName(), key); + public void delete(String bucket, String key) throws IOException { + HttpResponse resp = client.delete(bucket, key); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } @@ -195,8 +193,8 @@ public void delete(Bucket bucket, String key) throws IOException { * com.basho.riak.client.raw.RawClient#delete(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ - public void delete(Bucket bucket, String key, int deleteQuorum) throws IOException { - HttpResponse resp = client.delete(bucket.getName(), key, RequestMeta.deleteParams(deleteQuorum)); + public void delete(String bucket, String key, int deleteQuorum) throws IOException { + HttpResponse resp = client.delete(bucket, key, RequestMeta.deleteParams(deleteQuorum)); if (!resp.isSuccess()) { throw new IOException(resp.getBodyAsString()); } @@ -260,11 +258,11 @@ public Iterator iterator() { * (non-Javadoc) * * @see - * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.newapi.RiakObject - * , com.basho.riak.client.raw.query.LinkWalkSpec) + * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.client.raw.query.LinkWalkSpec) */ - public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException { - return null; + public WalkResult linkWalk(final LinkWalkSpec linkWalkSpec) throws IOException { + final String walkSpecString = convert(linkWalkSpec); + return convert(client.walk(linkWalkSpec.getStartBucket(), linkWalkSpec.getStartKey(), walkSpecString)); } /* diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index 62fb69be8..783a9585e 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -14,23 +14,34 @@ package com.basho.riak.client.raw.pbc; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; +import org.apache.commons.httpclient.util.DateParseException; +import org.apache.commons.httpclient.util.DateUtil; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.query.LinkWalkStep.Accumulate; import com.basho.riak.newapi.query.MapReduceResult; +import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.newapi.util.UnmodifiableIterator; import com.basho.riak.pbc.MapReduceResponseSource; import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.mapreduce.MapReduceResponse; @@ -45,13 +56,13 @@ public class ConversionUtil { * @param fetch * @return */ - static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bucket bucket) { + static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects) { RiakResponse response = RiakResponse.empty(); if (pbcObjects != null && pbcObjects.length > 0) { RiakObject[] converted = new RiakObject[pbcObjects.length]; for (int i = 0; i < pbcObjects.length; i++) { - converted[i] = convert(pbcObjects[i], bucket); + converted[i] = convert(pbcObjects[i]); } response = new RiakResponse(pbcObjects[0].getVclock().toByteArray(), converted); } @@ -63,8 +74,8 @@ static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects, final Bu * @param o * @return */ - static RiakObject convert(com.basho.riak.pbc.RiakObject o, final Bucket bucket) { - RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(bucket, o.getKey()); + static RiakObject convert(com.basho.riak.pbc.RiakObject o) { + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); builder.withValue(nullSafeToStringUtf8(o.getValue())); builder.withVClock(nullSafeToBytes(o.getVclock())); @@ -134,7 +145,7 @@ static RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { */ static com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { final VClock vc = riakObject.getVClock(); - ByteString bucketName = nullSafeToByteString(riakObject.getBucketName()); + ByteString bucketName = nullSafeToByteString(riakObject.getBucket()); ByteString key = nullSafeToByteString(riakObject.getKey()); ByteString content = nullSafeToByteString(riakObject.getValue()); @@ -184,22 +195,23 @@ static BucketProperties convert(com.basho.riak.pbc.BucketProperties properties) /** * @param resp * @return + * @throws IOException */ - static MapReduceResult convert(final MapReduceResponseSource resp) { + static MapReduceResult convert(final MapReduceResponseSource resp) throws IOException { final ObjectMapper om = new ObjectMapper(); - final StringBuilder sb = new StringBuilder(); + final LinkedList results = new LinkedList(); for (MapReduceResponse mrr : resp) { // TODO investigate pb client null returns from MRRS if (mrr != null && mrr.response != null) { - sb.append(mrr.response.toStringUtf8()); + results.add(mrr.response.toStringUtf8()); } } final MapReduceResult result = new MapReduceResult() { public String getResultRaw() { - return sb.toString(); + return toJSONArray(results); } public Collection getResult(Class resultType) throws ConversionException { @@ -212,4 +224,151 @@ public Collection getResult(Class resultType) throws ConversionExcepti }; return result; } -} + + /** + * @param results + * @return + */ + static String toJSONArray(LinkedList results) { + if (results.size() > 1) { + final StringBuilder sb = new StringBuilder("["); + sb.append(join(results, ",")).append("]"); + return sb.toString(); + } else { + return results.get(0); + } + } + + /** + * Joins a collection of strings into a string, separated by delimiter. + * @param strings The collection of strings + * @param delimiter the separator to use + * @return the contents of Collection as a single string, each element separated by delimiter + */ + static String join(Collection strings, String delimiter) { + final StringBuilder sb = new StringBuilder(); + + final Iterator it = strings.iterator(); + + while (it.hasNext()) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append(delimiter); + } + } + + return sb.toString(); + } + + /** + * Converts an Http {@link Accumulate} value into a boolean + * + * @param accumulate + * the {@link Accumulate} value + * @param isFinalStep + * is the {@link Accumulate} value for the final step + * @return true if a m/r link phase should keep the result or false + * otherwise + */ + static boolean linkAccumulateToLinkPhaseKeep(Accumulate accumulate, boolean isFinalStep) { + // (in m/r terms we *always* want to keep the final step since its + // output + // is the input to the final map stage which we *do* keep) + boolean keep = true; + if (!isFinalStep) { + switch (accumulate) { + case YES: + keep = true; + break; + case NO: + case DEFAULT: + keep = false; + break; + default: + break; + } + } + return keep; + } + + /** + * Take a link walked m/r result and make it into a WalkResult. + * + * This is a little bit nasty since the JSON is parsed to a Map. + * + * @param secondPhaseResult + * the contents of which *must* be a json array of {step: int, v: + * riakObjectMap} + * @return a WalkResult of RiakObjects grouped by first-phase step + * @throws IOException + */ + @SuppressWarnings({ "rawtypes" }) static WalkResult convert(MapReduceResult secondPhaseResult) throws IOException { + final SortedMap> steps = new TreeMap>(); + + try { + Collection results = secondPhaseResult.getResult(Map.class); + for (Map o : results) { + final int step = Integer.parseInt((String) o.get("step")); + Collection stepAccumulator = steps.get(step); + + if (stepAccumulator == null) { + stepAccumulator = new ArrayList(); + steps.put(step, stepAccumulator); + } + + final Map data = (Map) o.get("v"); + + stepAccumulator.add(mapToRiakObject(data)); + } + } catch (ConversionException e) { + throw new IOException(e.getMessage()); + } + // create a result instance + return new WalkResult() { + public Iterator> iterator() { + return new UnmodifiableIterator>(steps.values().iterator()); + } + }; + } + + /** + * Copy the data from the map into a RiakObject. + * + * @param data + * a valid Map from JSON. + * @return A RiakObject populated from the map. + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) private static RiakObject mapToRiakObject(Map data) { + RiakObjectBuilder b = RiakObjectBuilder.newBuilder((String) data.get("bucket"), (String) data.get("key")); + b.withVClock(((String) data.get("vclock")).getBytes()); + + final List values = (List) data.get("values"); + // TODO figure out what to do about multiple values here, + // I say take the first for now (that is what the link walk interface + // does) + if (values.size() != 0) { + final Map value = (Map) values.get(0); + + b.withValue((String) value.get("data")); + final Map meta = (Map) value.get("metadata"); + b.withContentType((String) meta.get("content-type")); + b.withVtag((String) meta.get("X-Riak-VTag")); + + try { + Date lastModDate = DateUtil.parseDate((String) meta.get("X-Riak-Last-Modified")); + b.withLastModified(lastModDate.getTime()); + } catch (DateParseException e) { + // NO-OP + } + + List> links = (List>) meta.get("Links"); + for (List link : links) { + b.addLink(link.get(0), link.get(1), link.get(2)); + } + + Map userMetaData = (Map) meta.get("X-Riak-Meta"); + b.withUsermeta(userMetaData); + } + return b.build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index cbbde94a2..d7141d7e6 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -14,10 +14,14 @@ package com.basho.riak.client.raw.pbc; import static com.basho.riak.client.raw.pbc.ConversionUtil.convert; +import static com.basho.riak.client.raw.pbc.ConversionUtil.linkAccumulateToLinkPhaseKeep; import static com.basho.riak.client.raw.pbc.ConversionUtil.nullSafeToStringUtf8; import java.io.IOException; +import java.util.Collection; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; @@ -26,11 +30,16 @@ import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; import com.basho.riak.client.util.Constants; +import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.BucketProperties; +import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.query.BucketKeyMapReduce; +import com.basho.riak.newapi.query.LinkWalkStep; import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.newapi.query.functions.JSSourceFunction; +import com.basho.riak.newapi.query.functions.NamedErlangFunction; import com.basho.riak.pbc.IRequestMeta; import com.basho.riak.pbc.KeySource; import com.basho.riak.pbc.MapReduceResponseSource; @@ -62,17 +71,17 @@ public PBClientAdapter(String host, int port) throws IOException { * @see com.basho.riak.client.raw.RawClient#fetch(java.lang.String, * java.lang.String) */ - public RiakResponse fetch(Bucket bucket, String key) throws IOException { - if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + public RiakResponse fetch(String bucket, String key) throws IOException { + if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( - "bucket must not be null and bucket.getName() must not be null or empty " + "bucket must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } - return convert(client.fetch(bucket.getName(), key), bucket); + return convert(client.fetch(bucket, key)); } /* @@ -82,17 +91,17 @@ public RiakResponse fetch(Bucket bucket, String key) throws IOException { * com.basho.riak.client.raw.RawClient#fetch(com.basho.riak.newapi.bucket * .Bucket, java.lang.String, int) */ - public RiakResponse fetch(Bucket bucket, String key, int readQuorum) throws IOException { - if (bucket == null || bucket.getName() == null || bucket.getName().trim().equals("")) { + public RiakResponse fetch(String bucket, String key, int readQuorum) throws IOException { + if (bucket == null || bucket.trim().equals("")) { throw new IllegalArgumentException( - "bucket must not be null and bucket.getName() must not be null or empty " + "bucket must not be null or empty " + "or just whitespace."); } if (key == null || key.trim().equals("")) { throw new IllegalArgumentException("Key cannot be null or empty or just whitespace"); } - return convert(client.fetch(bucket.getName(), key, readQuorum), bucket); + return convert(client.fetch(bucket, key, readQuorum)); } /* @@ -108,7 +117,7 @@ public RiakResponse store(RiakObject riakObject, StoreMeta storeMeta) throws IOE "object cannot be null, object's key cannot be null, object's bucket cannot be null"); } - return convert(client.store(convert(riakObject), convert(storeMeta, riakObject)), riakObject.getBucket()); + return convert(client.store(convert(riakObject), convert(storeMeta, riakObject))); } /* @@ -127,8 +136,8 @@ public void store(RiakObject object) throws IOException { * * @see com.basho.riak.client.raw.RawClient#delete(java.lang.String) */ - public void delete(Bucket bucket, String key) throws IOException { - client.delete(bucket.getName(), key); + public void delete(String bucket, String key) throws IOException { + client.delete(bucket, key); } /* @@ -136,8 +145,8 @@ public void delete(Bucket bucket, String key) throws IOException { * * @see com.basho.riak.client.raw.RawClient#delete(java.lang.String, int) */ - public void delete(Bucket bucket, String key, int deleteQuorum) throws IOException { - client.delete(bucket.getName(), key, deleteQuorum); + public void delete(String bucket, String key, int deleteQuorum) throws IOException { + client.delete(bucket, key, deleteQuorum); } /* @@ -212,15 +221,89 @@ public Iterator iterator() { }; } - /* - * (non-Javadoc) + /** + * This is a bit of a hack. The pb interface doesn't really have a Link Walker + * like the REST interface does. This method runs (maximum) 2 map reduce + * requests to get the same results the link walk would for the given spec. * - * @see - * com.basho.riak.client.raw.RawClient#linkWalk(com.basho.riak.client.RiakObject - * , com.basho.riak.client.raw.query.LinkWalkSpec) + * The first m/r job gets the end of the link walk and the inputs for second m/r job. + * The second job gets all those inputs values. + * Then some client side massaging occurs to massage the result into the correct format. */ - public WalkResult linkWalk(RiakObject startObject, LinkWalkSpec linkWalkSpec) throws IOException { - return null; + public WalkResult linkWalk(final LinkWalkSpec linkWalkSpec) throws IOException { + MapReduceResult firstPhaseResult = linkWalkFirstPhase(linkWalkSpec); + MapReduceResult secondPhaseResult = linkWalkSecondPhase(firstPhaseResult); + WalkResult result = convert(secondPhaseResult); + return result; + } + + /** + * Creates an m/r job from the supplied link spec and executes it + * + * @param linkWalkSpec + * the Link Walk spec + * @return {@link MapReduceResult} containing the end of the link and any + * intermediate bkeys for a second pass + * @throws IOException + */ + private MapReduceResult linkWalkFirstPhase(final LinkWalkSpec linkWalkSpec) throws IOException { + BucketKeyMapReduce mr = new BucketKeyMapReduce(this); + mr.addInput(linkWalkSpec.getStartBucket(), linkWalkSpec.getStartKey()); + int size = linkWalkSpec.size(); + int cnt = 0; + + for (LinkWalkStep step : linkWalkSpec) { + cnt++; + boolean keep = linkAccumulateToLinkPhaseKeep(step.getKeep(), cnt == size); + mr.addLinkPhase(step.getBucket(), step.getKey(), keep); + } + + // this is a bit of a hack. The low level API is using the high level + // API so must strip out the exception. + try { + return mr.execute(); + } catch (RiakException e) { + throw (IOException) e.getCause(); + } + } + + /** + * Takes the results of running linkWalkFirstPhase and creates an m/r job + * from them + * + * @param firstPhaseResult + * the results of running linkWalkfirstPhase. + * @return the results from the intermediate bkeys of phase one. + * @throws IOException + */ + private MapReduceResult linkWalkSecondPhase(final MapReduceResult firstPhaseResult) throws IOException { + try { + @SuppressWarnings("rawtypes") Collection bkeys = firstPhaseResult.getResult(LinkedList.class); + + BucketKeyMapReduce mr = new BucketKeyMapReduce(this); + int stepCnt = 0; + + for (LinkedList> step : bkeys) { + // TODO find a way to *enforce* order here (custom + // deserializer?) + stepCnt++; + for (List input : step) { + // use the step count as key data so we can aggregate the + // results into the correct steps when they come back + mr.addInput(input.get(0), input.get(1), Integer.toString(stepCnt)); + } + } + + mr.addReducePhase(new NamedErlangFunction("riak_kv_mapreduce", "reduce_set_union"), false); + mr.addMapPhase(new JSSourceFunction("function(v, keyData) { return [{\"step\": keyData, \"v\": v}]; }"), + true); + + return mr.execute(); + } catch (ConversionException e) { + throw new IOException(e.getMessage()); + } catch (RiakException e) { + throw (IOException) e.getCause(); + } } /* diff --git a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java index fb80ae81b..100b80fc5 100644 --- a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java +++ b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java @@ -13,10 +13,63 @@ */ package com.basho.riak.client.raw.query; +import java.util.Iterator; +import java.util.LinkedList; + +import com.basho.riak.newapi.query.LinkWalkStep; +import com.basho.riak.newapi.util.UnmodifiableIterator; + /** + * An immutable class that represents a link walk specification + * * @author russell * */ -public interface LinkWalkSpec { +public class LinkWalkSpec implements Iterable { + + private final LinkedList steps; + private final String startBucket; + private final String startKey; + + /** + * @param steps + * @param startBucket + * @param startKey + */ + public LinkWalkSpec(final LinkedList steps, String startBucket, String startKey) { + this.steps = new LinkedList(steps); + this.startBucket = startBucket; + this.startKey = startKey; + } + + /** + * @return the startBucket + */ + public String getStartBucket() { + return startBucket; + } + + /** + * @return the startKey + */ + public String getStartKey() { + return startKey; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + final Iterator it = steps.iterator(); + return new UnmodifiableIterator(it); + } + /** + * @return how many steps in this link spec + */ + public int size() { + return steps.size(); + } } diff --git a/src/main/java/com/basho/riak/newapi/DefaultClient.java b/src/main/java/com/basho/riak/newapi/DefaultClient.java index 5ba6afdd9..6d3e6f299 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultClient.java +++ b/src/main/java/com/basho/riak/newapi/DefaultClient.java @@ -97,6 +97,6 @@ public BucketMapReduce mapReduce(String bucket) { } public LinkWalk walk(RiakObject startObject) { - return null; + return new LinkWalk(client, startObject); } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java index 4107c29bc..cfafd5df0 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -21,7 +21,6 @@ import java.util.Iterator; import java.util.Map; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; import com.basho.riak.newapi.convert.RiakKey; @@ -34,7 +33,7 @@ public class DefaultRiakObject implements RiakObject { public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; - private final Bucket bucket; + private final String bucket; @RiakKey private final String key; private final VClock vclock; private final String vtag; @@ -63,7 +62,7 @@ public class DefaultRiakObject implements RiakObject { * @param links * @param userMeta */ - public DefaultRiakObject(Bucket bucket, String key, VClock vclock, String vtag, final Date lastModified, + public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, String contentType, String value, final Collection links, final Map userMeta) { if (bucket == null) { @@ -131,7 +130,7 @@ public Iterator iterator() { return links.iterator(); } - public Bucket getBucket() { + public String getBucket() { return bucket; } @@ -165,10 +164,6 @@ public Map getMeta() { return new HashMap(userMeta); } - public String getBucketName() { - return bucket.getName(); - } - public String getValue() { return value; } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java index 73089dd80..82a2b389e 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -18,7 +18,6 @@ import java.util.Map; import java.util.Map.Entry; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.VClock; /** @@ -27,9 +26,7 @@ */ public interface RiakObject extends Iterable { - Bucket getBucket(); - - String getBucketName(); + String getBucket(); String getValue(); diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 79c82e157..7a377f478 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -13,7 +13,7 @@ */ package com.basho.riak.newapi.bucket; -import static com.basho.riak.newapi.convert.ConversionUtil.getKey; +import static com.basho.riak.newapi.convert.KeyUtil.getKey; import java.io.IOException; import java.util.Collection; @@ -22,6 +22,7 @@ import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.ClobberMutation; import com.basho.riak.newapi.cap.DefaultResolver; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.Quorum; @@ -233,10 +234,10 @@ public Iterable keys() throws RiakException { public StoreObject store(final String key, final String value) { final Bucket b = this; - return new StoreObject(client, b, key).withMutator(new Mutation() { + return new StoreObject(client, name, key).withMutator(new Mutation() { public RiakObject apply(RiakObject original) { if (original == null) { - return RiakObjectBuilder.newBuilder(b, key).withValue(value).build(); + return RiakObjectBuilder.newBuilder(b.getName(), key).withValue(value).build(); } else { return original.setValue(value); } @@ -259,17 +260,15 @@ public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws Conv * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.Object) */ public StoreObject store(final T o) { - final Bucket b = this; @SuppressWarnings("unchecked") Class clazz = (Class) o.getClass(); final String key = getKey(o); if (key == null) { throw new NoKeySpecifedException(o); } - return new StoreObject(client, b, key).withConverter(new JSONConverter(clazz, b)).withMutator(new Mutation() { - public T apply(T original) { - return o; - }; - }).withResolver(new DefaultResolver()); + return new StoreObject(client, name, key) + .withConverter(new JSONConverter(clazz, name)) + .withMutator(new ClobberMutation(o)) + .withResolver(new DefaultResolver()); } /* @@ -279,14 +278,11 @@ public T apply(T original) { * java.lang.Object) */ public StoreObject store(final String key, final T o) { - final Bucket b = this; @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); - return new StoreObject(client, b, key).withConverter(new JSONConverter(clazz, b, key)).withMutator(new Mutation() { - public T apply(T original) { - return o; - }; - }).withResolver(new DefaultResolver()); + return new StoreObject(client, name, key). + withConverter(new JSONConverter(clazz, name, key)) + .withMutator(new ClobberMutation(o)).withResolver(new DefaultResolver()); } /* @@ -295,13 +291,14 @@ public T apply(T original) { * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.Object) */ public FetchObject fetch(T o) { - final Bucket b = this; @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); final String key = getKey(o); if (key == null) { throw new NoKeySpecifedException(o); } - return new FetchObject(client, this, key).withConverter(new JSONConverter(clazz, b)).withResolver(new DefaultResolver()); + return new FetchObject(client, name, key) + .withConverter(new JSONConverter(clazz, name)) + .withResolver(new DefaultResolver()); } /* @@ -311,8 +308,9 @@ public FetchObject fetch(T o) { * java.lang.Class) */ public FetchObject fetch(final String key, final Class type) { - final Bucket b = this; - return new FetchObject(client, this, key).withConverter(new JSONConverter(type, b)).withResolver(new DefaultResolver()); + return new FetchObject(client, name, key) + .withConverter(new JSONConverter(type, name)) + .withResolver(new DefaultResolver()); } /* @@ -321,20 +319,20 @@ public FetchObject fetch(final String key, final Class type) { * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) */ public FetchObject fetch(String key) { - final Bucket b = this; - - return new FetchObject(client, b, key).withResolver(new DefaultResolver()).withConverter(new Converter() { + return new FetchObject(client, name, key) + .withResolver(new DefaultResolver()) + .withConverter(new Converter() { - public RiakObject toDomain(RiakObject riakObject) { - return riakObject; - } + public RiakObject toDomain(RiakObject riakObject) { + return riakObject; + } - public RiakObject fromDomain(RiakObject domainObject, - VClock vclock) - throws ConversionException { - return RiakObjectBuilder.from(domainObject).withVClock(vclock).build(); - } - }); + public RiakObject fromDomain(RiakObject domainObject, + VClock vclock) + throws ConversionException { + return RiakObjectBuilder.from(domainObject).withVClock(vclock).build(); + } + }); } /* @@ -347,7 +345,7 @@ public DeleteObject delete(T o) { if (key == null) { throw new NoKeySpecifedException(o); } - return new DeleteObject(client, this, key); + return new DeleteObject(client, name, key); } /* @@ -356,7 +354,7 @@ public DeleteObject delete(T o) { * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.String) */ public DeleteObject delete(String key) { - return new DeleteObject(client, this, key); + return new DeleteObject(client, name, key); } } diff --git a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java index 2d53008a0..b86ce5f61 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java @@ -18,8 +18,8 @@ import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.Mutation; import com.basho.riak.newapi.cap.MutationProducer; -import com.basho.riak.newapi.convert.ConversionUtil; import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.newapi.convert.KeyUtil; /** * A domain bucket is a wrapper around a bucket that is strongly typed uses a @@ -94,7 +94,7 @@ public T fetch(T o) throws RiakException { } public void delete(T o) throws RiakException { - final String key = ConversionUtil.getKey(o); + final String key = KeyUtil.getKey(o); delete(key); } diff --git a/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java b/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java index 584f2c30b..1bf78d3ee 100644 --- a/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java @@ -33,6 +33,7 @@ public class DomainBucketBuilder { private final Bucket bucket; private final Class clazz; + // The default resolver, it doesn't resolve private ConflictResolver resolver = new DefaultResolver(); private Converter converter; private Mutation mutation; @@ -52,8 +53,8 @@ public class DomainBucketBuilder { public DomainBucketBuilder(Bucket bucket, Class clazz) { this.bucket = bucket; this.clazz = clazz; - // create a default converter - converter = new JSONConverter(clazz, bucket); + // create a default converter (the JSONConverter) + converter = new JSONConverter(clazz, bucket.getName()); } public DomainBucket build() { @@ -132,4 +133,9 @@ public DomainBucketBuilder mutationProducer(MutationProducer mutationProdu this.mutationProducer = mutationProducer; return this; } + + public DomainBucketBuilder withConverter(final Converter converter) { + this.converter = converter; + return this; + } } diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java index ff10d6c95..6593d5b1f 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -19,10 +19,10 @@ import java.util.HashMap; import java.util.Map; +import com.basho.riak.newapi.DefaultRiakLink; import com.basho.riak.newapi.DefaultRiakObject; import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.BasicVClock; import com.basho.riak.newapi.cap.VClock; @@ -31,7 +31,7 @@ * */ public class RiakObjectBuilder { - private final Bucket bucket; + private final String bucket; private final String key; private String value; private VClock vclock; @@ -41,12 +41,12 @@ public class RiakObjectBuilder { private Map userMeta = new HashMap(); private String contentType; - private RiakObjectBuilder(Bucket bucket, String key) { + private RiakObjectBuilder(String bucket, String key) { this.bucket = bucket; this.key = key; } - public static RiakObjectBuilder newBuilder(Bucket bucket, String key) { + public static RiakObjectBuilder newBuilder(String bucket, String key) { return new RiakObjectBuilder(bucket, key); } @@ -86,12 +86,30 @@ public RiakObjectBuilder withLastModified(long lastModified) { } public RiakObjectBuilder withLinks(Collection links) { - this.links = new ArrayList(links); + if(links != null) { + this.links = new ArrayList(links); + } + return this; + } + + public RiakObjectBuilder addLink(String bucket, String key, String tag) { + synchronized (links) { + links.add(new DefaultRiakLink(bucket, key, tag)); + } return this; } public RiakObjectBuilder withUsermeta(Map usermeta) { - this.userMeta = new HashMap(usermeta); + if(usermeta != null) { + this.userMeta = new HashMap(usermeta); + } + return this; + } + + public RiakObjectBuilder addUsermeta(String key, String value) { + synchronized (userMeta) { + userMeta.put(key, value); + } return this; } @@ -100,12 +118,9 @@ public RiakObjectBuilder withContentType(String contentType) { return this; } - /** - * @param vclock - * @return - */ public RiakObjectBuilder withVClock(VClock vclock) { this.vclock = vclock; return this; } + } diff --git a/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java b/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java deleted file mode 100644 index 007f33981..000000000 --- a/src/main/java/com/basho/riak/newapi/convert/ConversionUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is provided 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.basho.riak.newapi.convert; - -import java.lang.reflect.Field; - -/** - * @author russell - * - */ -public class ConversionUtil { - - public static String getKey(T domainObject, String defaultKey) { - String key = getKey(domainObject); - if (key == null) { - key = defaultKey; - } - return key; - } - - public static String getKey(T domainObject) { - final Field[] fields = domainObject.getClass().getDeclaredFields(); - - Object key = null; - - for (Field field : fields) { - - if (field.isAnnotationPresent(RiakKey.class)) { - boolean oldAccessible = field.isAccessible(); - field.setAccessible(true); - try { - key = field.get(domainObject); - } catch (IllegalAccessException e) { - // NO-OP since we can't get the key - } finally { - field.setAccessible(oldAccessible); - } - - } - } - - return key == null ? null : key.toString(); - } - -} diff --git a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java index 61f6c0c07..ccbbd9f12 100644 --- a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java +++ b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java @@ -13,7 +13,7 @@ */ package com.basho.riak.newapi.convert; -import static com.basho.riak.newapi.convert.ConversionUtil.getKey; +import static com.basho.riak.newapi.convert.KeyUtil.getKey; import java.io.IOException; import java.io.StringWriter; @@ -22,7 +22,6 @@ import org.codehaus.jackson.map.ObjectMapper; import com.basho.riak.newapi.RiakObject; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; @@ -37,10 +36,10 @@ public class JSONConverter implements Converter { private final ObjectMapper objectMapper = new ObjectMapper(); private final Class clazz; - private final Bucket bucket; + private final String bucket; private String defaultKey; - public JSONConverter(Class clazz, final Bucket bucket) { + public JSONConverter(Class clazz, String bucket) { this.clazz = clazz; this.bucket = bucket; } @@ -50,7 +49,7 @@ public JSONConverter(Class clazz, final Bucket bucket) { * @param b * @param defaultKey */ - public JSONConverter(Class clazz, Bucket b, String defaultKey) { + public JSONConverter(Class clazz, String b, String defaultKey) { this(clazz, b); this.defaultKey = defaultKey; } diff --git a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java index ba55d5cf1..9970f4757 100644 --- a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java @@ -18,7 +18,6 @@ import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.DefaultRetrier; /** @@ -28,7 +27,7 @@ public class DeleteObject implements RiakOperation { private final RawClient client; - private final Bucket bucket; + private final String bucket; private final String key; private Integer rw; @@ -39,7 +38,7 @@ public class DeleteObject implements RiakOperation { * @param bucket * @param key */ - public DeleteObject(RawClient client, Bucket bucket, String key) { + public DeleteObject(RawClient client, String bucket, String key) { this.client = client; this.bucket = bucket; this.key = key; diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java index f7538563a..38905c784 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -22,7 +22,6 @@ import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.cap.UnresolvedConflictException; @@ -35,7 +34,7 @@ */ public class FetchObject implements RiakOperation { - private final Bucket bucket; + private final String bucket; private final RawClient client; private final String key; @@ -49,7 +48,7 @@ public class FetchObject implements RiakOperation { * @param bucket * @param client */ - public FetchObject(final RawClient client, final Bucket bucket, final String key) { + public FetchObject(final RawClient client, final String bucket, final String key) { this.bucket = bucket; this.client = client; this.key = key; diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index 531ec947c..3a4823cae 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -24,7 +24,6 @@ import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.cap.Mutation; @@ -43,7 +42,7 @@ public class StoreObject implements RiakOperation { private final RawClient client; - private final Bucket bucket; + private final String bucket; // TODO populate private Integer r; @@ -58,7 +57,7 @@ public class StoreObject implements RiakOperation { private final String key; - public StoreObject(final RawClient client, Bucket bucket, String key) { + public StoreObject(final RawClient client, String bucket, String key) { this.client = client; this.bucket = bucket; this.key = key; diff --git a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java index 2839269cd..b58b4f41f 100644 --- a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java +++ b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java @@ -13,9 +13,15 @@ */ package com.basho.riak.newapi.query; +import java.io.IOException; +import java.util.LinkedList; + +import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.operations.RiakOperation; +import com.basho.riak.newapi.query.LinkWalkStep.Accumulate; /** * @@ -24,13 +30,18 @@ */ public class LinkWalk implements RiakOperation { - private final RiakObject startObject; + private final RawClient client; + private final String startBucket; + private final String startKey; + private final LinkedList steps = new LinkedList(); /** * @param startObject */ - public LinkWalk(final RiakObject startObject) { - this.startObject = startObject; + public LinkWalk(final RawClient client, final RiakObject startObject) { + this.client = client; + this.startBucket = startObject.getBucket(); + this.startKey = startObject.getKey(); } /* @@ -39,7 +50,66 @@ public LinkWalk(final RiakObject startObject) { * @see com.basho.riak.client.RiakOperation#execute() */ public WalkResult execute() throws RiakException { - return null; + try { + return client.linkWalk(new LinkWalkSpec(steps, startBucket, startKey)); + } catch (IOException e) { + throw new RiakException(e); + } + } + + /** + * Add a link walking step to this link walk + * + * @param bucket + * the bucket, a null, or empty string is treated as the wildcard + * @param tag + * the tag of the link, a null or empty string is treated as the + * wildcard + * @param accumulate + * to keep the result of this step or not + * @return this + */ + public LinkWalk addStep(String bucket, String tag, Accumulate accumulate) { + synchronized (steps) { + steps.add(new LinkWalkStep(bucket, tag, accumulate)); + } + return this; + } + + /** + * Add a link walking step to this link walk + * + * @param bucket + * the bucket, a null, or empty string is treated as the wildcard _ + * @param tag + * the tag of the link, a null or empty string is treated as the + * wildcard + * @param accumulate + * to keep the result of this step or not + * @return this + */ + public LinkWalk addStep(String bucket, String tag, boolean keep) { + synchronized (steps) { + steps.add(new LinkWalkStep(bucket, tag, keep)); + } + return this; } + /** + * Add a link walking step to this link walk using the default accumulate + * value for the step (NO for all steps accept last step) + * + * @param bucket + * the bucket, a null, or empty string is treated as the wildcard _ + * @param tag + * the tag of the link, a null or empty string is treated as the + * wildcard + * @return this + */ + public LinkWalk addStep(String bucket, String tag) { + synchronized (steps) { + steps.add(new LinkWalkStep(bucket, tag)); + } + return this; + } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java index 722e49e1d..e38557a14 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -35,13 +35,10 @@ import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.RiakLink; -import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.DomainBucket; +import com.basho.riak.newapi.bucket.RiakBucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.convert.Converter; import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.filter.LessThanFilter; import com.basho.riak.newapi.query.filter.StringToIntFilter; @@ -67,15 +64,16 @@ public abstract class ITestMapReduce { */ protected abstract RiakClient getClient() throws RiakException; - public static String BUCKET_NAME = "mr_test_java"; - public static int TEST_ITEMS = 200; + public static final String BUCKET_NAME = "mr_test_java"; + public static final int TEST_ITEMS = 200; @BeforeClass public static void setup() throws RiakException { final RiakClient client = RiakFactory.pbcClient(); - final Bucket b = client.createBucket(BUCKET_NAME).execute(); + final Bucket bucket = client.createBucket(BUCKET_NAME).execute(); + final RiakBucket b = RiakBucket.newRiakBucket(bucket); for (int i = 0; i < TEST_ITEMS; i++) { - RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(b, "java_" + Integer.toString(i)); + RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(BUCKET_NAME, "java_" + Integer.toString(i)); builder.withContentType("text/plain").withValue(Integer.toString(i)); if (i < TEST_ITEMS - 1) { RiakLink link = new DefaultRiakLink(BUCKET_NAME, "java_" + Integer.toString(i + 1), "test"); @@ -84,16 +82,7 @@ public abstract class ITestMapReduce { builder.withLinks(links); } - b.store(builder.build()).withConverter(new Converter() { - - public RiakObject toDomain(RiakObject riakObject) throws ConversionException { - return riakObject; - } - - public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { - return domainObject; - } - }).execute(); + b.store(builder.build()); } } @@ -184,7 +173,6 @@ public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws Conv } // perform test - MapReduceResult result = client.mapReduce() .addInput("goog","2010-01-04") .addInput("goog","2010-01-05") diff --git a/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java b/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java index e5ed78f98..f10da96ba 100644 --- a/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java +++ b/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java @@ -34,7 +34,7 @@ public class ConversionUtilTest { }; - assertEquals(expected, ConversionUtil.getKey(o)); + assertEquals(expected, KeyUtil.getKey(o)); } @Test public void getNonStringKey() { @@ -44,7 +44,7 @@ public class ConversionUtilTest { }; - assertEquals(expected.toString(), ConversionUtil.getKey(o)); + assertEquals(expected.toString(), KeyUtil.getKey(o)); } @Test public void noKeyField() { @@ -53,7 +53,7 @@ public class ConversionUtilTest { }; - assertNull(ConversionUtil.getKey(o)); + assertNull(KeyUtil.getKey(o)); } @Test public void nullKeyField() { @@ -62,7 +62,7 @@ public class ConversionUtilTest { }; - assertNull(ConversionUtil.getKey(o)); + assertNull(KeyUtil.getKey(o)); } } diff --git a/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java b/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java index 6c79ce3e1..1abee3818 100644 --- a/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java +++ b/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java @@ -13,7 +13,7 @@ */ package com.basho.riak.newapi.query.filter; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; diff --git a/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java b/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java index f64ebe3aa..eee177289 100644 --- a/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java +++ b/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java @@ -13,8 +13,13 @@ */ package com.basho.riak.newapi.query.serialize; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; import org.codehaus.jackson.JsonGenerator; import org.junit.Test; From 3259637120eb1f089c0b4938f1a9da8ce88ceb35 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 29 Apr 2011 14:03:26 +0100 Subject: [PATCH 017/764] Add the Link walk test and code Add a domain bucket for RiakObject --- .../basho/riak/newapi/bucket/RiakBucket.java | 114 ++++++++++++++++++ .../basho/riak/newapi/convert/KeyUtil.java | 57 +++++++++ .../basho/riak/newapi/query/LinkWalkStep.java | 87 +++++++++++++ .../newapi/util/UnmodifiableIterator.java | 56 +++++++++ .../riak/client/itest/ITestLinkWalk.java | 110 +++++++++++++++++ 5 files changed, 424 insertions(+) create mode 100644 src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java create mode 100644 src/main/java/com/basho/riak/newapi/convert/KeyUtil.java create mode 100644 src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java create mode 100644 src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java diff --git a/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java b/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java new file mode 100644 index 000000000..fc1749b00 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java @@ -0,0 +1,114 @@ +/* + * This file is provided 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.basho.riak.newapi.bucket; + +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.builders.DomainBucketBuilder; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.newapi.convert.Converter; + +/** + * A DomainBucket for convenience. + * @author russell + * + */ +public class RiakBucket { + + private final DomainBucket delegate; + private final Bucket bucket; + + public static RiakBucket newRiakBucket(final Bucket b) { + // create a DomainBucket as a delegate + DomainBucketBuilder builder = DomainBucket.builder(b, RiakObject.class); + builder.withConverter(new Converter() { + // no conversion required + public RiakObject toDomain(RiakObject riakObject) throws ConversionException { + return riakObject; + } + + public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { + return domainObject; + } + }); + + return new RiakBucket(builder.build(), b); + } + + private RiakBucket(final DomainBucket delegate, final Bucket bucket) { + this.delegate = delegate; + this.bucket = bucket; + } + + /** + * @param o + * @return + * @throws RiakException + * @see com.basho.riak.newapi.bucket.DomainBucket#store(java.lang.Object) + */ + public RiakObject store(RiakObject o) throws RiakException { + return delegate.store(o); + } + + /** + * Convenience for storing a String in Riak. + * @param key + * @param value + * @return + * @throws RiakException + */ + public RiakObject store(String key, String value) throws RiakException { + return delegate.store(RiakObjectBuilder.newBuilder(bucket.getName(), key).withValue(value).build()); + } + /** + * @param key + * @return + * @throws RiakException + * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.String) + */ + public RiakObject fetch(String key) throws RiakException { + return delegate.fetch(key); + } + + /** + * @param o + * @return + * @throws RiakException + * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.Object) + */ + public RiakObject fetch(RiakObject o) throws RiakException { + return delegate.fetch(o); + } + + /** + * @param o + * @throws RiakException + * @see com.basho.riak.newapi.bucket.DomainBucket#delete(java.lang.Object) + */ + public void delete(RiakObject o) throws RiakException { + delegate.delete(o); + } + + /** + * @param key + * @throws RiakException + * @see com.basho.riak.newapi.bucket.DomainBucket#delete(java.lang.String) + */ + public void delete(String key) throws RiakException { + delegate.delete(key); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/convert/KeyUtil.java b/src/main/java/com/basho/riak/newapi/convert/KeyUtil.java new file mode 100644 index 000000000..c72aff9fa --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/convert/KeyUtil.java @@ -0,0 +1,57 @@ +/* + * This file is provided 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.basho.riak.newapi.convert; + +import java.lang.reflect.Field; + +/** + * Static method to get the annotated key from a domain object. + * @author russell + * + */ +public class KeyUtil { + + public static String getKey(T domainObject, String defaultKey) { + String key = getKey(domainObject); + if (key == null) { + key = defaultKey; + } + return key; + } + + public static String getKey(T domainObject) { + final Field[] fields = domainObject.getClass().getDeclaredFields(); + + Object key = null; + + for (Field field : fields) { + + if (field.isAnnotationPresent(RiakKey.class)) { + boolean oldAccessible = field.isAccessible(); + field.setAccessible(true); + try { + key = field.get(domainObject); + } catch (IllegalAccessException e) { + // NO-OP since we can't get the key + } finally { + field.setAccessible(oldAccessible); + } + + } + } + + return key == null ? null : key.toString(); + } + +} diff --git a/src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java b/src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java new file mode 100644 index 000000000..76f873d3d --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java @@ -0,0 +1,87 @@ +/* + * This file is provided 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.basho.riak.newapi.query; + +/** + * @author russell + * + */ +public class LinkWalkStep { + + public enum Accumulate { + YES("1"), NO("2"), DEFAULT("_"); + + private final String asString; + + private Accumulate(String asString) { + this.asString = asString; + } + + public String toString() { + return asString; + } + + public static Accumulate fromBoolean(boolean bool) { + if (bool) { + return Accumulate.YES; + } else { + return Accumulate.NO; + } + } + }; + + private final String bucket; + private final String tag; + private final Accumulate keep; + + public LinkWalkStep(String bucket, String key, Accumulate keep) { + this.bucket = bucket; + this.tag = key; + this.keep = keep; + } + + public LinkWalkStep(String bucket, String key, boolean keep) { + this.bucket = bucket; + this.tag = key; + this.keep = Accumulate.fromBoolean(keep); + } + + public LinkWalkStep(String bucket, String key) { + this.bucket = bucket; + this.tag = key; + this.keep = Accumulate.DEFAULT; + } + + /** + * @return the bucket + */ + public String getBucket() { + return bucket; + } + + /** + * @return the key + */ + public String getKey() { + return tag; + } + + /** + * @return the keep + */ + public Accumulate getKeep() { + return keep; + } + +} diff --git a/src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java b/src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java new file mode 100644 index 000000000..56bb516c9 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java @@ -0,0 +1,56 @@ +/* + * This file is provided 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.basho.riak.newapi.util; + +import java.util.Iterator; + +/** + * Decorates an iterator so that remove throws {@link UnsupportedOperationException} + * @author russell + * @param + * + */ +public class UnmodifiableIterator implements Iterator { + + private final Iterator delegate; + + + /** + * @param delegate the iterator to decorate + */ + public UnmodifiableIterator(Iterator delegate) { + this.delegate = delegate; + } + + /* (non-Javadoc) + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + return delegate.hasNext(); + } + + /* (non-Javadoc) + * @see java.util.Iterator#next() + */ + public E next() { + return delegate.next(); + } + + /* (non-Javadoc) + * @see java.util.Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java new file mode 100644 index 000000000..a540c57ee --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java @@ -0,0 +1,110 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.junit.Test; + +import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakException; +import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.RiakBucket; +import com.basho.riak.newapi.builders.RiakObjectBuilder; +import com.basho.riak.newapi.query.WalkResult; + +/** + * @author russell + * + */ +public class ITestLinkWalk { + + @Test public void test_walk() throws RiakException { + final RiakClient client = RiakFactory.pbcClient(); + + final String fooVal = "fooer"; + final String barVal = "barrer"; + + final String bucketName = "test_walk_" + UUID.randomUUID().toString(); + final String[] first = { "first", "the first" }; + final String[] second = { "second", fooVal }; + final String[] third = { "third", barVal }; + final String[] fourth = { "fourth", fooVal }; + final String[] fith = { "fith", barVal }; + + final String fooTag = "foo"; + final String barTag = "bar"; + + final Bucket b = client.createBucket(bucketName).execute(); + final RiakBucket bucket = RiakBucket.newRiakBucket(b); + + RiakObject o1 = RiakObjectBuilder.newBuilder(bucketName, first[0]).withValue(first[1]).addLink(bucketName, + second[0], + fooTag).addLink(bucketName, + third[0], + barTag).build(); + + RiakObject o2 = RiakObjectBuilder.newBuilder(bucketName, second[0]).withValue(second[1]).addLink(bucketName, + fourth[0], + fooTag).build(); + + RiakObject o3 = RiakObjectBuilder.newBuilder(bucketName, third[0]).withValue(third[1]).addLink(bucketName, + fourth[0], + fooTag).build(); + + RiakObject o4 = RiakObjectBuilder.newBuilder(bucketName, fourth[0]).withValue(fourth[1]).addLink(bucketName, + fith[0], + barTag). + addUsermeta("metaKey", "123").build(); + + RiakObject o5 = RiakObjectBuilder.newBuilder(bucketName, fith[0]).withValue(fith[1]).build(); + + bucket.store(o1); + bucket.store(o2); + bucket.store(o3); + bucket.store(o4); + bucket.store(o5); + + // Perform walk + WalkResult result = client.walk(o1).addStep(bucketName, fooTag, true).addStep(bucketName, fooTag).execute(); + assertNotNull(result); + + int stepsCnt = 0; + List keys = new ArrayList(); + for (Collection s : result) { + + for (RiakObject object : s) { + keys.add(object.getKey()); + assertEquals(fooVal, object.getValue()); + } + + assertEquals(1, s.size()); + stepsCnt++; + } + + assertEquals(2, stepsCnt); + + assertTrue(keys.contains("second")); + assertTrue(keys.contains("fourth")); + } +} From 0c31b83e0e7859283743ebf8356b13156ef216d2 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 29 Apr 2011 16:44:32 +0100 Subject: [PATCH 018/764] Add ITest for filters to existing m/r test --- .../basho/riak/client/itest/ITestBasic.java | 24 ------------------- .../riak/client/itest/ITestMapReduce.java | 22 +++++++++++++++++ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/basho/riak/client/itest/ITestBasic.java b/src/test/java/com/basho/riak/client/itest/ITestBasic.java index b1153b89b..e6b53056c 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBasic.java @@ -227,28 +227,4 @@ public class ITestBasic { assertTrue(storeresp.hasSiblings()); assertEquals(2, storeresp.getSiblings().size()); } - - @Test public void deleteQuorumIsApplied() { - final RiakClient c = new RiakClient(RIAK_URL); - - final String bucket = UUID.randomUUID().toString(); - final String key = UUID.randomUUID().toString(); - final byte[] value = "value".getBytes(); - - RiakBucketInfo bucketInfo = new RiakBucketInfo(); - bucketInfo.setNVal(3); - - c.setBucketSchema(bucket, bucketInfo); - RiakObject o = new RiakObject(bucket, key, value); - - final RequestMeta rm = WRITE_3_REPLICAS(); - - StoreResponse storeresp = c.store(o, rm); - assertSuccess(storeresp); - - HttpResponse deleteResponse = c.delete(bucket, key, RequestMeta.deleteParams(4)); - - assertEquals(500, deleteResponse.getStatusCode()); - assertTrue(deleteResponse.getBodyAsString().contains("n_val_violation")); - } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java index f5e10bdf7..e37273aa2 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -33,6 +33,9 @@ import com.basho.riak.client.RiakObject; import com.basho.riak.client.mapreduce.ErlangFunction; import com.basho.riak.client.mapreduce.JavascriptFunction; +import com.basho.riak.client.mapreduce.filter.LessThanFilter; +import com.basho.riak.client.mapreduce.filter.StringToIntFilter; +import com.basho.riak.client.mapreduce.filter.TokenizeFilter; import com.basho.riak.client.request.MapReduceBuilder; import com.basho.riak.client.response.MapReduceResponse; @@ -114,4 +117,23 @@ public static void teardown() { assertEquals(73, results.getInt(73)); assertEquals(197, results.getInt(197)); } + + @Test public void doKeyFilterMapReduce() throws HttpException, IOException, JSONException { + RiakClient c = new RiakClient(RIAK_URL); + MapReduceBuilder builder = new MapReduceBuilder(c); + builder.setBucket(BUCKET_NAME); + builder.map(JavascriptFunction.named("Riak.mapValuesJson"), false); + builder.reduce(JavascriptFunction.named("Riak.reduceNumericSort"), true); + builder.keyFilter(new TokenizeFilter("_", 2)); + builder.keyFilter(new StringToIntFilter()); + builder.keyFilter(new LessThanFilter(50)); + MapReduceResponse response = builder.submit(); + + assertTrue(response.isSuccess()); + JSONArray results = response.getResults(); + assertEquals(50, results.length()); + assertEquals(0, results.getInt(0)); + assertEquals(23, results.getInt(23)); + assertEquals(49, results.getInt(49)); + } } From 09386d9628bf3b58579d39d1a9eaa92ba8cdc11c Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 3 May 2011 14:24:44 +0100 Subject: [PATCH 019/764] Move all HTTP specific code to new client.http package Deprecate original package http specific code in preparation for removal next-but-one release. --- .../com/basho/riak/client/HttpRiakClient.java | 381 ++++++++ .../com/basho/riak/client/HttpRiakObject.java | 381 ++++++++ .../com/basho/riak/client/RiakBucketInfo.java | 9 + .../com/basho/riak/client/RiakConfig.java | 9 + .../riak/client/http/HttpRiakClient.java | 373 ++++++++ .../riak/client/http/HttpRiakObject.java | 373 ++++++++ .../riak/client/http/RiakBucketInfo.java | 171 ++++ .../basho/riak/client/http/RiakClient.java | 407 +++++++++ .../basho/riak/client/http/RiakConfig.java | 185 ++++ .../com/basho/riak/client/http/RiakLink.java | 98 +++ .../basho/riak/client/http/RiakObject.java | 831 ++++++++++++++++++ .../client/http/mapreduce/ErlangFunction.java | 54 ++ .../http/mapreduce/JavascriptFunction.java | 73 ++ .../client/http/mapreduce/LinkFunction.java | 48 + .../http/mapreduce/MapReduceFunction.java | 30 + .../http/mapreduce/filter/BetweenFilter.java | 50 ++ .../http/mapreduce/filter/EndsWithFilter.java | 30 + .../http/mapreduce/filter/EqualToFilter.java | 41 + .../mapreduce/filter/FloatToStringFilter.java | 26 + .../mapreduce/filter/GreaterThanFilter.java | 41 + .../filter/GreaterThanOrEqualFilter.java | 41 + .../mapreduce/filter/IntToStringFilter.java | 26 + .../http/mapreduce/filter/LessThanFilter.java | 41 + .../filter/LessThanOrEqualFilter.java | 41 + .../mapreduce/filter/LogicalAndFilter.java | 37 + .../mapreduce/filter/LogicalFilterGroup.java | 36 + .../mapreduce/filter/LogicalNotFilter.java | 37 + .../mapreduce/filter/LogicalOrFilter.java | 37 + .../mapreduce/filter/MapReduceFilter.java | 31 + .../http/mapreduce/filter/MatchFilter.java | 30 + .../mapreduce/filter/NotEqualToFilter.java | 41 + .../mapreduce/filter/SetMemberFilter.java | 57 ++ .../mapreduce/filter/SimilarToFilter.java | 31 + .../mapreduce/filter/StartsWithFilter.java | 30 + .../mapreduce/filter/StringToFloatFilter.java | 26 + .../mapreduce/filter/StringToIntFilter.java | 26 + .../http/mapreduce/filter/ToLowerFilter.java | 26 + .../http/mapreduce/filter/ToUpperFilter.java | 26 + .../http/mapreduce/filter/TokenizeFilter.java | 31 + .../mapreduce/filter/UrlDecodeFilter.java | 26 + .../plain/ConvertToCheckedExceptions.java | 44 + .../riak/client/http/plain/PlainClient.java | 294 +++++++ .../client/http/plain/RiakIOException.java | 27 + .../http/plain/RiakResponseException.java | 84 ++ .../client/http/request/MapReduceBuilder.java | 475 ++++++++++ .../riak/client/http/request/RequestMeta.java | 240 +++++ .../client/http/request/RiakWalkSpec.java | 112 +++ .../client/http/response/BucketResponse.java | 88 ++ .../http/response/DefaultHttpResponse.java | 124 +++ .../client/http/response/FetchResponse.java | 142 +++ .../client/http/response/HttpResponse.java | 87 ++ .../http/response/HttpResponseDecorator.java | 104 +++ .../http/response/MapReduceResponse.java | 49 ++ .../http/response/RiakExceptionHandler.java | 33 + .../http/response/RiakIORuntimeException.java | 41 + .../RiakResponseRuntimeException.java | 116 +++ .../client/http/response/StoreResponse.java | 98 +++ .../client/http/response/StreamHandler.java | 48 + .../http/response/StreamedKeysCollection.java | 68 ++ .../response/StreamedSiblingsCollection.java | 87 ++ .../client/http/response/WalkResponse.java | 101 +++ .../http/response/WithBodyResponse.java | 36 + .../http/util/BranchableInputStream.java | 167 ++++ .../riak/client/http/util/ClientHelper.java | 401 +++++++++ .../riak/client/http/util/ClientUtils.java | 475 ++++++++++ .../client/http/util/CollectionWrapper.java | 143 +++ .../riak/client/http/util/Constants.java | 92 ++ .../riak/client/http/util/LinkHeader.java | 108 +++ .../riak/client/http/util/Multipart.java | 255 ++++++ .../client/http/util/OneTokenInputStream.java | 92 ++ .../client/http/util/StreamedMultipart.java | 173 ++++ .../riak/client/mapreduce/ErlangFunction.java | 8 + .../client/mapreduce/JavascriptFunction.java | 9 + .../riak/client/mapreduce/LinkFunction.java | 10 + .../client/mapreduce/MapReduceFunction.java | 12 +- .../mapreduce/filter/BetweenFilter.java | 10 + .../mapreduce/filter/EndsWithFilter.java | 10 + .../mapreduce/filter/EqualToFilter.java | 10 + .../mapreduce/filter/FloatToStringFilter.java | 10 + .../mapreduce/filter/GreaterThanFilter.java | 10 + .../filter/GreaterThanOrEqualFilter.java | 10 + .../mapreduce/filter/IntToStringFilter.java | 10 + .../mapreduce/filter/LessThanFilter.java | 10 + .../filter/LessThanOrEqualFilter.java | 10 + .../mapreduce/filter/LogicalAndFilter.java | 10 + .../mapreduce/filter/LogicalFilterGroup.java | 10 + .../mapreduce/filter/LogicalNotFilter.java | 10 + .../mapreduce/filter/LogicalOrFilter.java | 10 + .../mapreduce/filter/MapReduceFilter.java | 11 +- .../client/mapreduce/filter/MatchFilter.java | 10 + .../mapreduce/filter/NotEqualToFilter.java | 10 + .../mapreduce/filter/SetMemberFilter.java | 10 + .../mapreduce/filter/SimilarToFilter.java | 11 + .../mapreduce/filter/StartsWithFilter.java | 10 + .../mapreduce/filter/StringToFloatFilter.java | 10 + .../mapreduce/filter/StringToIntFilter.java | 10 + .../mapreduce/filter/ToLowerFilter.java | 10 + .../mapreduce/filter/ToUpperFilter.java | 10 + .../mapreduce/filter/TokenizeFilter.java | 10 + .../mapreduce/filter/UrlDecodeFilter.java | 11 + .../plain/ConvertToCheckedExceptions.java | 9 + .../basho/riak/client/plain/PlainClient.java | 9 + .../riak/client/plain/RiakIOException.java | 9 + .../client/plain/RiakResponseException.java | 9 + .../riak/client/request/MapReduceBuilder.java | 9 + .../riak/client/request/RequestMeta.java | 9 + .../riak/client/request/RiakWalkSpec.java | 11 +- .../riak/client/response/BucketResponse.java | 9 + .../client/response/DefaultHttpResponse.java | 9 + .../riak/client/response/FetchResponse.java | 9 + .../riak/client/response/HttpResponse.java | 9 + .../response/HttpResponseDecorator.java | 9 + .../client/response/MapReduceResponse.java | 9 + .../client/response/RiakExceptionHandler.java | 9 + .../response/RiakIORuntimeException.java | 10 + .../RiakResponseRuntimeException.java | 9 + .../riak/client/response/StoreResponse.java | 9 + .../riak/client/response/StreamHandler.java | 9 + .../response/StreamedKeysCollection.java | 9 + .../response/StreamedSiblingsCollection.java | 10 + .../riak/client/response/WalkResponse.java | 9 + .../client/response/WithBodyResponse.java | 10 +- .../client/util/BranchableInputStream.java | 11 +- .../basho/riak/client/util/ClientHelper.java | 9 + .../basho/riak/client/util/ClientUtils.java | 9 + .../riak/client/util/CollectionWrapper.java | 12 + .../com/basho/riak/client/util/Constants.java | 10 + .../basho/riak/client/util/LinkHeader.java | 9 + .../com/basho/riak/client/util/Multipart.java | 9 + .../riak/client/util/OneTokenInputStream.java | 9 + .../riak/client/util/StreamedMultipart.java | 10 + .../java/com/basho/riak/pbc/RiakClient.java | 2 +- .../basho/riak/client/{ => http}/Hosts.java | 2 +- .../client/{ => http}/TestRiakBucketInfo.java | 5 +- .../client/{ => http}/TestRiakClient.java | 23 +- .../client/{ => http}/TestRiakConfig.java | 4 +- .../riak/client/{ => http}/TestRiakLink.java | 4 +- .../client/{ => http}/TestRiakObject.java | 17 +- .../client/{ => http}/itest/ITestBasic.java | 36 +- .../{ => http}/itest/ITestDataLoad.java | 12 +- .../{ => http}/itest/ITestMapReduce.java | 28 +- .../{ => http}/itest/ITestStreaming.java | 24 +- .../client/{ => http}/itest/ITestWalk.java | 18 +- .../riak/client/{ => http}/itest/Utils.java | 6 +- .../mapreduce/TestMapReduceBuilder.java | 56 +- .../mapreduce/TestMapReduceFunctions.java | 5 +- .../plain/TestConvertToCheckedExceptions.java | 9 +- .../{ => http}/plain/TestPlainClient.java | 26 +- .../{ => http}/request/TestRequestMeta.java | 4 +- .../response/TestBucketResponse.java | 5 +- .../response/TestDefaultHttpResponse.java | 4 +- .../response/TestFetchResponse.java | 13 +- .../response/TestHttpResponseDecorator.java | 5 +- .../response/TestStoreResponse.java | 5 +- .../response/TestStreamedKeysCollection.java | 4 +- .../TestStreamedSiblingsCollection.java | 14 +- .../{ => http}/response/TestWalkResponse.java | 9 +- .../util/TestBranchableInputStream.java | 8 +- .../{ => http}/util/TestClientHelper.java | 21 +- .../{ => http}/util/TestClientUtils.java | 11 +- .../util/TestCollectionWrapper.java | 4 +- .../{ => http}/util/TestLinkHeader.java | 4 +- .../client/{ => http}/util/TestMultipart.java | 5 +- .../util/TestOneTokenInputStream.java | 5 +- .../util/TestStreamedMultipart.java | 6 +- .../com/basho/riak/pbc/itest/ITestBasic.java | 10 +- .../basho/riak/pbc/itest/ITestDataLoad.java | 8 +- .../basho/riak/pbc/itest/ITestMapReduce.java | 8 +- .../java/com/basho/riak/pbc/itest/Utils.java | 4 +- .../basho/riak/test/util/ExpectedValues.java | 2 +- 170 files changed, 9518 insertions(+), 193 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/HttpRiakClient.java create mode 100644 src/main/java/com/basho/riak/client/HttpRiakObject.java create mode 100644 src/main/java/com/basho/riak/client/http/HttpRiakClient.java create mode 100644 src/main/java/com/basho/riak/client/http/HttpRiakObject.java create mode 100644 src/main/java/com/basho/riak/client/http/RiakBucketInfo.java create mode 100644 src/main/java/com/basho/riak/client/http/RiakClient.java create mode 100644 src/main/java/com/basho/riak/client/http/RiakConfig.java create mode 100644 src/main/java/com/basho/riak/client/http/RiakLink.java create mode 100644 src/main/java/com/basho/riak/client/http/RiakObject.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/ErlangFunction.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/JavascriptFunction.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/LinkFunction.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/MapReduceFunction.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/BetweenFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/EndsWithFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/EqualToFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/FloatToStringFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanOrEqualFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/IntToStringFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanOrEqualFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalAndFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalFilterGroup.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalNotFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalOrFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/MapReduceFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/MatchFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/NotEqualToFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/SetMemberFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/SimilarToFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/StartsWithFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/StringToFloatFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/StringToIntFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/ToLowerFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/ToUpperFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/TokenizeFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/UrlDecodeFilter.java create mode 100644 src/main/java/com/basho/riak/client/http/plain/ConvertToCheckedExceptions.java create mode 100644 src/main/java/com/basho/riak/client/http/plain/PlainClient.java create mode 100644 src/main/java/com/basho/riak/client/http/plain/RiakIOException.java create mode 100644 src/main/java/com/basho/riak/client/http/plain/RiakResponseException.java create mode 100644 src/main/java/com/basho/riak/client/http/request/MapReduceBuilder.java create mode 100644 src/main/java/com/basho/riak/client/http/request/RequestMeta.java create mode 100644 src/main/java/com/basho/riak/client/http/request/RiakWalkSpec.java create mode 100644 src/main/java/com/basho/riak/client/http/response/BucketResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/FetchResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/HttpResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/HttpResponseDecorator.java create mode 100644 src/main/java/com/basho/riak/client/http/response/MapReduceResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/RiakExceptionHandler.java create mode 100644 src/main/java/com/basho/riak/client/http/response/RiakIORuntimeException.java create mode 100644 src/main/java/com/basho/riak/client/http/response/RiakResponseRuntimeException.java create mode 100644 src/main/java/com/basho/riak/client/http/response/StoreResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/StreamHandler.java create mode 100644 src/main/java/com/basho/riak/client/http/response/StreamedKeysCollection.java create mode 100644 src/main/java/com/basho/riak/client/http/response/StreamedSiblingsCollection.java create mode 100644 src/main/java/com/basho/riak/client/http/response/WalkResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/response/WithBodyResponse.java create mode 100644 src/main/java/com/basho/riak/client/http/util/BranchableInputStream.java create mode 100644 src/main/java/com/basho/riak/client/http/util/ClientHelper.java create mode 100644 src/main/java/com/basho/riak/client/http/util/ClientUtils.java create mode 100644 src/main/java/com/basho/riak/client/http/util/CollectionWrapper.java create mode 100644 src/main/java/com/basho/riak/client/http/util/Constants.java create mode 100644 src/main/java/com/basho/riak/client/http/util/LinkHeader.java create mode 100644 src/main/java/com/basho/riak/client/http/util/Multipart.java create mode 100644 src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java create mode 100644 src/main/java/com/basho/riak/client/http/util/StreamedMultipart.java rename src/test/java/com/basho/riak/client/{ => http}/Hosts.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/TestRiakBucketInfo.java (96%) rename src/test/java/com/basho/riak/client/{ => http}/TestRiakClient.java (93%) rename src/test/java/com/basho/riak/client/{ => http}/TestRiakConfig.java (96%) rename src/test/java/com/basho/riak/client/{ => http}/TestRiakLink.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/TestRiakObject.java (98%) rename src/test/java/com/basho/riak/client/{ => http}/itest/ITestBasic.java (89%) rename src/test/java/com/basho/riak/client/{ => http}/itest/ITestDataLoad.java (90%) rename src/test/java/com/basho/riak/client/{ => http}/itest/ITestMapReduce.java (86%) rename src/test/java/com/basho/riak/client/{ => http}/itest/ITestStreaming.java (88%) rename src/test/java/com/basho/riak/client/{ => http}/itest/ITestWalk.java (86%) rename src/test/java/com/basho/riak/client/{ => http}/itest/Utils.java (91%) rename src/test/java/com/basho/riak/client/{ => http}/mapreduce/TestMapReduceBuilder.java (92%) rename src/test/java/com/basho/riak/client/{ => http}/mapreduce/TestMapReduceFunctions.java (92%) rename src/test/java/com/basho/riak/client/{ => http}/plain/TestConvertToCheckedExceptions.java (75%) rename src/test/java/com/basho/riak/client/{ => http}/plain/TestPlainClient.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/request/TestRequestMeta.java (97%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestBucketResponse.java (97%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestDefaultHttpResponse.java (97%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestFetchResponse.java (96%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestHttpResponseDecorator.java (94%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestStoreResponse.java (93%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestStreamedKeysCollection.java (97%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestStreamedSiblingsCollection.java (91%) rename src/test/java/com/basho/riak/client/{ => http}/response/TestWalkResponse.java (94%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestBranchableInputStream.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestClientHelper.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestClientUtils.java (98%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestCollectionWrapper.java (95%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestLinkHeader.java (98%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestMultipart.java (98%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestOneTokenInputStream.java (94%) rename src/test/java/com/basho/riak/client/{ => http}/util/TestStreamedMultipart.java (96%) diff --git a/src/main/java/com/basho/riak/client/HttpRiakClient.java b/src/main/java/com/basho/riak/client/HttpRiakClient.java new file mode 100644 index 000000000..e1e03b33a --- /dev/null +++ b/src/main/java/com/basho/riak/client/HttpRiakClient.java @@ -0,0 +1,381 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpClient; + +import com.basho.riak.client.request.MapReduceBuilder; +import com.basho.riak.client.request.RequestMeta; +import com.basho.riak.client.request.RiakWalkSpec; +import com.basho.riak.client.response.BucketResponse; +import com.basho.riak.client.response.FetchResponse; +import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.response.MapReduceResponse; +import com.basho.riak.client.response.RiakExceptionHandler; +import com.basho.riak.client.response.RiakIORuntimeException; +import com.basho.riak.client.response.RiakResponseRuntimeException; +import com.basho.riak.client.response.StoreResponse; +import com.basho.riak.client.response.StreamHandler; +import com.basho.riak.client.response.WalkResponse; +import com.basho.riak.client.util.ClientUtils; + +/** + * @author russell + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.HttpRiakClient + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.HttpRiakClient + */ +@Deprecated +public interface HttpRiakClient { + + RiakConfig getConfig(); + + /** + * Set the properties for a Riak bucket. + * + * @param bucket + * The bucket name. + * @param bucketInfo + * Contains the schema to use for the bucket. Refer to the Riak + * documentation for a list of the recognized properties and the + * format of their values. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link HttpResponse} containing HTTP response information. + * + * @throws IllegalArgumentException + * If the provided schema values cannot be serialized to send to + * Riak. + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta); + + HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo); + + /** + * Return the properties for a Riak bucket without listing the keys in it. + * + * @param bucket + * The target bucket. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link BucketResponse} containing HTTP response information and + * the parsed schema + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + BucketResponse getBucketSchema(String bucket, RequestMeta meta); + + BucketResponse getBucketSchema(String bucket); + + /** + * Return the properties and keys for a Riak bucket. + * + * @param bucket + * The bucket to list. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link BucketResponse} containing HTTP response information and + * the parsed schema and keys + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + BucketResponse listBucket(String bucket, RequestMeta meta); + + BucketResponse listBucket(String bucket); + + /** + * Same as {@link RiakClient#listBucket(String, RequestMeta)}, except + * streams the response, so the user must remember to call + * {@link BucketResponse#close()} on the return value. + */ + BucketResponse streamBucket(String bucket, RequestMeta meta); + + BucketResponse streamBucket(String bucket); + + /** + * Store a {@link RiakObject}. + * + * @param object + * The {@link RiakObject} to store. + * @param meta + * Extra metadata to attach to the request such as w and dw + * values for the request, HTTP headers, and other query + * parameters. See + * {@link RequestMeta#writeParams(Integer, Integer)}. + * + * @return A {@link StoreResponse} containing HTTP response information and + * any updated information returned by the server such as the + * vclock, last modified date. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + StoreResponse store(RiakObject object, RequestMeta meta); + + StoreResponse store(RiakObject object); + + /** + * Fetch metadata (e.g. vclock, last modified, vtag) for the + * {@link RiakObject} stored at bucket and key. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * {@link RequestMeta#readParams(int)}. + * + * @return {@link FetchResponse} containing HTTP response information and a + * {@link RiakObject} containing only metadata and no value. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + FetchResponse fetchMeta(String bucket, String key, RequestMeta meta); + + FetchResponse fetchMeta(String bucket, String key); + + /** + * Fetch the {@link RiakObject} (which can include sibling objects) stored + * at bucket and key. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * {@link RequestMeta#readParams(int)}. + * + * @return {@link FetchResponse} containing HTTP response information and a + * {@link RiakObject} or sibling objects. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + FetchResponse fetch(String bucket, String key, RequestMeta meta); + + FetchResponse fetch(String bucket, String key); + + /** + * Similar to fetch(), except the HTTP connection is left open for + * successful responses, and the Riak response is provided as a stream. + * The user must remember to call {@link FetchResponse#close()} on the + * return value. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * RequestMeta.readParams(). + * + * @return A streaming {@link FetchResponse} containing HTTP response + * information and the response stream. The HTTP connection must be + * closed manually by the user by calling + * {@link FetchResponse#close()}. + */ + FetchResponse stream(String bucket, String key, RequestMeta meta); + + FetchResponse stream(String bucket, String key); + + /** + * Fetch and process the object stored at bucket and + * key as a stream. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param handler + * A {@link StreamHandler} to process the Riak response. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * RequestMeta.readParams(). + * + * @return Result from calling handler.process() or true if handler is null. + * + * @throws IOException + * If an error occurs during communication with the Riak server. + * + * @see StreamHandler + */ + boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException; + + /** + * Delete the object at bucket and key. + * + * @param bucket + * The bucket containing the object. + * @param key + * The key of the object + * @param meta + * Extra metadata to attach to the request such as w and dw + * values for the request, HTTP headers, and other query + * parameters. See + * {@link RequestMeta#writeParams(Integer, Integer)}. + * + * @return {@link HttpResponse} containing HTTP response information. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + HttpResponse delete(String bucket, String key, RequestMeta meta); + + HttpResponse delete(String bucket, String key); + + /** + * Perform a map/reduce link walking operation and return the objects for + * which the "accumulate" flag is true. + * + * @param bucket + * The bucket of the "starting object" + * @param key + * The key of the "starting object" + * @param walkSpec + * A URL-path (omit beginning /) of the form + * bucket,tag-spec,accumulateFlag The + * tag-spec "_" matches all tags. + * accumulateFlag is either the String "1" or "0". + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * or query parameters. + * + * @return {@link WalkResponse} containing HTTP response information and a + * List of Lists, where each sub-list + * corresponds to a walkSpec element that had + * accumulateFlag equal to 1. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + * + * @see RiakWalkSpec + */ + WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta); + + WalkResponse walk(String bucket, String key, String walkSpec); + + WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec); + + /** + * Execute a map reduce job on the Riak server. + * + * @param job + * JSON string representing the map reduce job to run, which can + * be created using {@link MapReduceBuilder} + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * or query parameters. + * + * @return {@link MapReduceResponse} containing HTTP response information + * and the result of the map reduce job + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server does not return a valid JSON array. + */ + MapReduceResponse mapReduce(String job, RequestMeta meta); + + MapReduceResponse mapReduce(String job); + + /** + * A convenience method for creating a MapReduceBuilder used for building a + * map reduce job to submission to this client + * + * @param bucket + * The bucket to perform the map reduce job over + * @return A {@link MapReduceBuilder} to build the map reduce job + */ + MapReduceBuilder mapReduceOverBucket(String bucket); + + /** + * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a set + * of objects instead of a bucket. + * + * @param objects + * A set of objects represented as a map of { bucket : [ list of + * keys in bucket ] } + */ + MapReduceBuilder mapReduceOverObjects(Map> objects); + + /** + * The installed exception handler or null if not installed + */ + RiakExceptionHandler getExceptionHandler(); + + /** + * If an exception handler is provided, then the Riak client will hand + * exceptions to the handler rather than throwing them. + * {@link ClientUtils#throwChecked(Throwable)} can be used to throw + * undeclared checked exceptions to effectively "convert" RiakClient's + * unchecked exceptions to checked exceptions. + */ + void setExceptionHandler(RiakExceptionHandler exceptionHandler); + + /** + * Return the {@link HttpClient} used to make requests, which can be + * configured. + */ + HttpClient getHttpClient(); + + /** + * A 4-byte unique ID for this client. The ID is base 64 encoded and sent to + * Riak to generating the object vclock on store operations. Refer to the + * Riak documentation and + * http://lists.basho.com/pipermail/riak-users_lists.basho.com/2009- + * November/000153.html for information about the client ID. + */ + byte[] getClientId(); + + void setClientId(String clientId); + +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/HttpRiakObject.java b/src/main/java/com/basho/riak/client/HttpRiakObject.java new file mode 100644 index 000000000..afe33a5ba --- /dev/null +++ b/src/main/java/com/basho/riak/client/HttpRiakObject.java @@ -0,0 +1,381 @@ +/* + * This file is provided 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.basho.riak.client; + +import java.io.InputStream; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +import com.basho.riak.client.RiakObject.LinkBuilder; +import com.basho.riak.client.request.RequestMeta; +import com.basho.riak.client.request.RiakWalkSpec; +import com.basho.riak.client.response.FetchResponse; +import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.response.StoreResponse; + +/** + * @author russell + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.HttpRiakObject + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.HttpRiakObject + */ +@Deprecated +public interface HttpRiakObject { + + /** + * A {@link RiakObject} can be loosely attached to the {@link RiakClient} + * from which retrieve it was retrieved. Calling convenience methods like + * {@link RiakObject#store()} will store this object use that client. + */ + RiakClient getRiakClient(); + + RiakObject setRiakClient(RiakClient client); + + /** + * Copy the metadata and value from object. The bucket and key + * are not copied. + * + * @param object + * The source object to copy from + */ + void copyData(RiakObject object); + + /** + * Update the object's metadata. This usually happens when Riak returns + * updated metadata from a store operation. + * + * @param response + * Response from a store operation containing an updated vclock, + * last modified date, and vtag + */ + void updateMeta(StoreResponse response); + + /** + * Update the object's metadata from a fetch or fetchMeta operation + * + * @param response + * Response from a fetch or fetchMeta operation containing a + * vclock, last modified date, and vtag + */ + void updateMeta(FetchResponse response); + + /** + * The object's bucket + */ + String getBucket(); + + /** + * The object's key + */ + String getKey(); + + /** + * The object's value + */ + String getValue(); + + byte[] getValueAsBytes(); + + void setValue(String value); + + void setValue(byte[] value); + + /** + * Set the object's value as a stream. A value set here is independent of + * and has precedent over any value set using setValue(): + * {@link RiakObject#writeToHttpMethod(HttpMethod)} will always write the + * value from getValueStream() if it is not null. Calling getValue() will + * always return values set via setValue(), and calling getValueStream() + * will always return the stream set via setValueStream. + * + * @param in + * Input stream representing the object's value + * @param len + * Length of the InputStream or null if unknown. If null, the + * value will be buffered in memory to determine its size before + * sending to the server. + */ + void setValueStream(InputStream in, Long len); + + void setValueStream(InputStream in); + + InputStream getValueStream(); + + void setValueStreamLength(Long len); + + Long getValueStreamLength(); + + /** + * The object's links -- may be empty, but never be null. + * + * @see {@link RiakObject#addLink()}, {@link RiakObject#removeLink()}, {@link RiakObject#iterator()}, {@link RiakObject#hasLinks()} and , {@link RiakObject#numLinks()} + * + * @return the list of {@link RiakLink}s for this + * RiakObject + * @deprecated please use {@link RiakObject#iterableLinks())} to iterate over the + * collection of {@link RiakLink}s. Attempting to mutate the + * collection will result in UnsupportedOperationException in + * future versions. Use {@link RiakObject#addLink()} and {@link RiakObject#removeLink()} instead. + * Use {@link RiakObject#hasLinks()}, {@link RiakObject#numLinks()} and {@link RiakObject#hasLink(RiakLink)} + * to query state of links. + */ + @Deprecated List getLinks(); + + /** + * Makes a *deep* copy of links. + * + * Changes made to the original collection and its contents will not be reflected + * in this RiakObject's links. Use {@link RiakObject#addLink(RiakLink)}, + * {@link RiakObject#removeLink(RiakLink)} and {@link RiakObject#setLinks(List)} to alter the collection. + * @param links a List of {@link RiakLink} + */ + void setLinks(List links); + + /** + * Add link to this RiakObject's links. + * @param link a {@link RiakLink} to add. + * @return this RiakObject. + */ + RiakObject addLink(RiakLink link); + + /** + * Remove a {@link RiakLink} from this RiakObject. + * @param link the {@link RiakLink} to remove + * @return this RiakObject + */ + RiakObject removeLink(final RiakLink link); + + /** + * Does this RiakObject have any {@link RiakLink}s? + * @return true if there are links, false otherwise + */ + boolean hasLinks(); + + /** + * How many {@link RiakLink}s does this RiakObject have? + * @return the number of {@link RiakLink}s this object has. + */ + int numLinks(); + + /** + * Checks if the collection of RiakLinks contains the one passed in. + * @param riakLink a RiakLink + * @return true if the RiakObject's link collection contains riakLink. + */ + boolean hasLink(final RiakLink riakLink); + + /** + * User-specified metadata for the object in the form of key-value pairs -- + * may be empty, but never be null. New key-value pairs can be added using + * addUsermeta() + * + * @deprecated Future versions will return an unmodifiable view of the user meta. Please use + * {@link RiakObject#addUsermeta(String, String)}, + * {@link RiakObject#removeUsermetaItem(String)}, + * {@link RiakObject#setUsermeta(Map)}, + * {@link RiakObject#hasUsermetaItem(String)}, + * {@link RiakObject#hasUsermeta()} and + * {@link RiakObject#getUsermetaItem(String)} to mutate and query the User meta collection + */ + @Deprecated Map getUsermeta(); + + /** + * Creates a copy of userMetaData. Changes made to the original collection will not be + * reflected in the RiakObject's state. + * @param userMetaData + */ + void setUsermeta(final Map userMetaData); + + /** + * Adds the key, value to the collection of user meta for this object. + * @param key + * @param value + * @return this RiakObject. + */ + RiakObject addUsermetaItem(String key, String value); + + /** + * @return true if there are any user meta data set on this RiakObject. + */ + boolean hasUsermeta(); + + /** + * @return how many user meta data items this RiakObject has. + */ + int numUsermetaItems(); + + /** + * @param key + * @return + */ + boolean hasUsermetaItem(String key); + + /** + * Get an item of user meta data. + * @param key the user meta data item key + * @return The value for the given key or null. + */ + String getUsermetaItem(String key); + + /** + * @param key the key of the item to remove + */ + void removeUsermetaItem(String key); + + Iterable usermetaKeys(); + + /** + * The object's content type as a MIME type + */ + String getContentType(); + + void setContentType(String contentType); + + /** + * The object's opaque vclock assigned by Riak + */ + String getVclock(); + + /** + * The modification date of the object determined by Riak + */ + String getLastmod(); + + /** + * Convenience method to get the last modified header parsed into a Date + * object. Returns null if header is null, malformed, or cannot be parsed. + */ + Date getLastmodAsDate(); + + /** + * An entity tag for the object assigned by Riak + */ + String getVtag(); + + /** + * Convenience method for calling + * {@link RiakClient#store(RiakObject, RequestMeta)} followed by + * {@link RiakObject#updateMeta(StoreResponse)} + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to store it with. + */ + StoreResponse store(RequestMeta meta); + + StoreResponse store(); + + /** + * Store this object to a different Riak instance. + * + * @param riak + * Riak instance to store this object to + * @param meta + * Same as {@link RiakClient#store(RiakObject, RequestMeta)} + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to store it with. + */ + StoreResponse store(RiakClient riak, RequestMeta meta); + + /** + * Convenience method for calling {@link RiakClient#fetch(String, String)} + * followed by {@link RiakObject#copyData(RiakObject)} + * + * @param meta + * Same as {@link RiakClient#fetch(String, String, RequestMeta)} + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to refetch it from. + */ + FetchResponse fetch(RequestMeta meta); + + FetchResponse fetch(); + + /** + * Convenience method for calling + * {@link RiakClient#fetchMeta(String, String, RequestMeta)} followed by + * {@link RiakObject#updateMeta(FetchResponse)} + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to refetch meta from. + */ + FetchResponse fetchMeta(RequestMeta meta); + + FetchResponse fetchMeta(); + + /** + * Convenience method for calling + * {@link RiakClient#delete(String, String, RequestMeta)}. + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to delete from. + */ + HttpResponse delete(RequestMeta meta); + + HttpResponse delete(); + + /** + * Convenience methods for building a link walk specification starting from + * this object and calling + * {@link RiakClient#walk(String, String, RiakWalkSpec)} + * + * @param bucket + * The bucket to follow object links to + * @param tag + * The link tags to follow from this object + * @param keep + * Whether to keep the output from this link walking step. If not + * specified, then the output is only kept from the last step. + * @return A {@link LinkBuilder} object to continue building the walk query + * or to run it. + */ + LinkBuilder walk(String bucket, String tag, boolean keep); + + LinkBuilder walk(String bucket, String tag); + + LinkBuilder walk(String bucket, boolean keep); + + LinkBuilder walk(String bucket); + + LinkBuilder walk(); + + LinkBuilder walk(boolean keep); + + /** + * Serializes this object to an existing {@link HttpMethod} which can be + * sent as an HTTP request. Specifically, sends the object's link, + * user-defined metadata and vclock as HTTP headers and the value as the + * body. Used by {@link RiakClient} to create PUT requests. + */ + void writeToHttpMethod(HttpMethod httpMethod); + + /** + * A thread safe, snapshot Iterable view of the state of this RiakObject's {@link RiakLink}s at call time. + * Modifications are *NOT* supported. + * @return Iterable for this RiakObject's {@link RiakLink}s + */ + Iterable iterableLinks(); + +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/RiakBucketInfo.java b/src/main/java/com/basho/riak/client/RiakBucketInfo.java index 30f6f4efd..b5b7d6f59 100644 --- a/src/main/java/com/basho/riak/client/RiakBucketInfo.java +++ b/src/main/java/com/basho/riak/client/RiakBucketInfo.java @@ -24,7 +24,16 @@ /** * Represents the metadata stored in a bucket including its schema and the list * of keys contained in the bucket. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.RiakBucketInfo + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.RiakBucketInfo */ +@Deprecated public class RiakBucketInfo { private JSONObject schema; diff --git a/src/main/java/com/basho/riak/client/RiakConfig.java b/src/main/java/com/basho/riak/client/RiakConfig.java index 59f03f2b2..73272d8f5 100644 --- a/src/main/java/com/basho/riak/client/RiakConfig.java +++ b/src/main/java/com/basho/riak/client/RiakConfig.java @@ -25,7 +25,16 @@ * Configuration settings for connecting to a Riak instance such as the base * Riak URL and HttpClient settings. A pre-constructed HttpClient can also be * provided. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.RiakConfig + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.RiakConfig */ +@Deprecated public class RiakConfig { public static Pattern BASE_URL_PATTERN = Pattern.compile("^((?:[^:]*://)?[^/]*)"); diff --git a/src/main/java/com/basho/riak/client/http/HttpRiakClient.java b/src/main/java/com/basho/riak/client/http/HttpRiakClient.java new file mode 100644 index 000000000..910168a4d --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/HttpRiakClient.java @@ -0,0 +1,373 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpClient; + +import com.basho.riak.client.http.request.MapReduceBuilder; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.MapReduceResponse; +import com.basho.riak.client.http.response.RiakExceptionHandler; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.StreamHandler; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.ClientUtils; + +/** + * @author russell + * + */ +public interface HttpRiakClient { + + RiakConfig getConfig(); + + /** + * Set the properties for a Riak bucket. + * + * @param bucket + * The bucket name. + * @param bucketInfo + * Contains the schema to use for the bucket. Refer to the Riak + * documentation for a list of the recognized properties and the + * format of their values. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link HttpResponse} containing HTTP response information. + * + * @throws IllegalArgumentException + * If the provided schema values cannot be serialized to send to + * Riak. + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta); + + HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo); + + /** + * Return the properties for a Riak bucket without listing the keys in it. + * + * @param bucket + * The target bucket. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link BucketResponse} containing HTTP response information and + * the parsed schema + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + BucketResponse getBucketSchema(String bucket, RequestMeta meta); + + BucketResponse getBucketSchema(String bucket); + + /** + * Return the properties and keys for a Riak bucket. + * + * @param bucket + * The bucket to list. + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * and query parameters. + * + * @return {@link BucketResponse} containing HTTP response information and + * the parsed schema and keys + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + BucketResponse listBucket(String bucket, RequestMeta meta); + + BucketResponse listBucket(String bucket); + + /** + * Same as {@link RiakClient#listBucket(String, RequestMeta)}, except + * streams the response, so the user must remember to call + * {@link BucketResponse#close()} on the return value. + */ + BucketResponse streamBucket(String bucket, RequestMeta meta); + + BucketResponse streamBucket(String bucket); + + /** + * Store a {@link RiakObject}. + * + * @param object + * The {@link RiakObject} to store. + * @param meta + * Extra metadata to attach to the request such as w and dw + * values for the request, HTTP headers, and other query + * parameters. See + * {@link RequestMeta#writeParams(Integer, Integer)}. + * + * @return A {@link StoreResponse} containing HTTP response information and + * any updated information returned by the server such as the + * vclock, last modified date. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + StoreResponse store(RiakObject object, RequestMeta meta); + + StoreResponse store(RiakObject object); + + /** + * Fetch metadata (e.g. vclock, last modified, vtag) for the + * {@link RiakObject} stored at bucket and key. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * {@link RequestMeta#readParams(int)}. + * + * @return {@link FetchResponse} containing HTTP response information and a + * {@link RiakObject} containing only metadata and no value. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + FetchResponse fetchMeta(String bucket, String key, RequestMeta meta); + + FetchResponse fetchMeta(String bucket, String key); + + /** + * Fetch the {@link RiakObject} (which can include sibling objects) stored + * at bucket and key. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * {@link RequestMeta#readParams(int)}. + * + * @return {@link FetchResponse} containing HTTP response information and a + * {@link RiakObject} or sibling objects. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + FetchResponse fetch(String bucket, String key, RequestMeta meta); + + FetchResponse fetch(String bucket, String key); + + /** + * Similar to fetch(), except the HTTP connection is left open for + * successful responses, and the Riak response is provided as a stream. + * The user must remember to call {@link FetchResponse#close()} on the + * return value. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * RequestMeta.readParams(). + * + * @return A streaming {@link FetchResponse} containing HTTP response + * information and the response stream. The HTTP connection must be + * closed manually by the user by calling + * {@link FetchResponse#close()}. + */ + FetchResponse stream(String bucket, String key, RequestMeta meta); + + FetchResponse stream(String bucket, String key); + + /** + * Fetch and process the object stored at bucket and + * key as a stream. + * + * @param bucket + * The bucket containing the {@link RiakObject} to fetch. + * @param key + * The key of the {@link RiakObject} to fetch. + * @param handler + * A {@link StreamHandler} to process the Riak response. + * @param meta + * Extra metadata to attach to the request such as an r- value + * for the request, HTTP headers, and other query parameters. See + * RequestMeta.readParams(). + * + * @return Result from calling handler.process() or true if handler is null. + * + * @throws IOException + * If an error occurs during communication with the Riak server. + * + * @see StreamHandler + */ + boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException; + + /** + * Delete the object at bucket and key. + * + * @param bucket + * The bucket containing the object. + * @param key + * The key of the object + * @param meta + * Extra metadata to attach to the request such as w and dw + * values for the request, HTTP headers, and other query + * parameters. See + * {@link RequestMeta#writeParams(Integer, Integer)}. + * + * @return {@link HttpResponse} containing HTTP response information. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + HttpResponse delete(String bucket, String key, RequestMeta meta); + + HttpResponse delete(String bucket, String key); + + /** + * Perform a map/reduce link walking operation and return the objects for + * which the "accumulate" flag is true. + * + * @param bucket + * The bucket of the "starting object" + * @param key + * The key of the "starting object" + * @param walkSpec + * A URL-path (omit beginning /) of the form + * bucket,tag-spec,accumulateFlag The + * tag-spec "_" matches all tags. + * accumulateFlag is either the String "1" or "0". + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * or query parameters. + * + * @return {@link WalkResponse} containing HTTP response information and a + * List of Lists, where each sub-list + * corresponds to a walkSpec element that had + * accumulateFlag equal to 1. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + * + * @see RiakWalkSpec + */ + WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta); + + WalkResponse walk(String bucket, String key, String walkSpec); + + WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec); + + /** + * Execute a map reduce job on the Riak server. + * + * @param job + * JSON string representing the map reduce job to run, which can + * be created using {@link MapReduceBuilder} + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * or query parameters. + * + * @return {@link MapReduceResponse} containing HTTP response information + * and the result of the map reduce job + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server does not return a valid JSON array. + */ + MapReduceResponse mapReduce(String job, RequestMeta meta); + + MapReduceResponse mapReduce(String job); + + /** + * A convenience method for creating a MapReduceBuilder used for building a + * map reduce job to submission to this client + * + * @param bucket + * The bucket to perform the map reduce job over + * @return A {@link MapReduceBuilder} to build the map reduce job + */ + MapReduceBuilder mapReduceOverBucket(String bucket); + + /** + * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a set + * of objects instead of a bucket. + * + * @param objects + * A set of objects represented as a map of { bucket : [ list of + * keys in bucket ] } + */ + MapReduceBuilder mapReduceOverObjects(Map> objects); + + /** + * The installed exception handler or null if not installed + */ + RiakExceptionHandler getExceptionHandler(); + + /** + * If an exception handler is provided, then the Riak client will hand + * exceptions to the handler rather than throwing them. + * {@link ClientUtils#throwChecked(Throwable)} can be used to throw + * undeclared checked exceptions to effectively "convert" RiakClient's + * unchecked exceptions to checked exceptions. + */ + void setExceptionHandler(RiakExceptionHandler exceptionHandler); + + /** + * Return the {@link HttpClient} used to make requests, which can be + * configured. + */ + HttpClient getHttpClient(); + + /** + * A 4-byte unique ID for this client. The ID is base 64 encoded and sent to + * Riak to generating the object vclock on store operations. Refer to the + * Riak documentation and + * http://lists.basho.com/pipermail/riak-users_lists.basho.com/2009- + * November/000153.html for information about the client ID. + */ + byte[] getClientId(); + + void setClientId(String clientId); + +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/HttpRiakObject.java b/src/main/java/com/basho/riak/client/http/HttpRiakObject.java new file mode 100644 index 000000000..0282677e6 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/HttpRiakObject.java @@ -0,0 +1,373 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.io.InputStream; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +import com.basho.riak.client.http.RiakObject.LinkBuilder; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.StoreResponse; + +/** + * @author russell + * + */ +public interface HttpRiakObject { + + /** + * A {@link RiakObject} can be loosely attached to the {@link RiakClient} + * from which retrieve it was retrieved. Calling convenience methods like + * {@link RiakObject#store()} will store this object use that client. + */ + RiakClient getRiakClient(); + + RiakObject setRiakClient(RiakClient client); + + /** + * Copy the metadata and value from object. The bucket and key + * are not copied. + * + * @param object + * The source object to copy from + */ + void copyData(RiakObject object); + + /** + * Update the object's metadata. This usually happens when Riak returns + * updated metadata from a store operation. + * + * @param response + * Response from a store operation containing an updated vclock, + * last modified date, and vtag + */ + void updateMeta(StoreResponse response); + + /** + * Update the object's metadata from a fetch or fetchMeta operation + * + * @param response + * Response from a fetch or fetchMeta operation containing a + * vclock, last modified date, and vtag + */ + void updateMeta(FetchResponse response); + + /** + * The object's bucket + */ + String getBucket(); + + /** + * The object's key + */ + String getKey(); + + /** + * The object's value + */ + String getValue(); + + byte[] getValueAsBytes(); + + void setValue(String value); + + void setValue(byte[] value); + + /** + * Set the object's value as a stream. A value set here is independent of + * and has precedent over any value set using setValue(): + * {@link RiakObject#writeToHttpMethod(HttpMethod)} will always write the + * value from getValueStream() if it is not null. Calling getValue() will + * always return values set via setValue(), and calling getValueStream() + * will always return the stream set via setValueStream. + * + * @param in + * Input stream representing the object's value + * @param len + * Length of the InputStream or null if unknown. If null, the + * value will be buffered in memory to determine its size before + * sending to the server. + */ + void setValueStream(InputStream in, Long len); + + void setValueStream(InputStream in); + + InputStream getValueStream(); + + void setValueStreamLength(Long len); + + Long getValueStreamLength(); + + /** + * The object's links -- may be empty, but never be null. + * + * @see {@link RiakObject#addLink()}, {@link RiakObject#removeLink()}, {@link RiakObject#iterator()}, {@link RiakObject#hasLinks()} and , {@link RiakObject#numLinks()} + * + * @return the list of {@link RiakLink}s for this + * RiakObject + * @deprecated please use {@link RiakObject#iterableLinks())} to iterate over the + * collection of {@link RiakLink}s. Attempting to mutate the + * collection will result in UnsupportedOperationException in + * future versions. Use {@link RiakObject#addLink()} and {@link RiakObject#removeLink()} instead. + * Use {@link RiakObject#hasLinks()}, {@link RiakObject#numLinks()} and {@link RiakObject#hasLink(RiakLink)} + * to query state of links. + */ + @Deprecated List getLinks(); + + /** + * Makes a *deep* copy of links. + * + * Changes made to the original collection and its contents will not be reflected + * in this RiakObject's links. Use {@link RiakObject#addLink(RiakLink)}, + * {@link RiakObject#removeLink(RiakLink)} and {@link RiakObject#setLinks(List)} to alter the collection. + * @param links a List of {@link RiakLink} + */ + void setLinks(List links); + + /** + * Add link to this RiakObject's links. + * @param link a {@link RiakLink} to add. + * @return this RiakObject. + */ + RiakObject addLink(RiakLink link); + + /** + * Remove a {@link RiakLink} from this RiakObject. + * @param link the {@link RiakLink} to remove + * @return this RiakObject + */ + RiakObject removeLink(final RiakLink link); + + /** + * Does this RiakObject have any {@link RiakLink}s? + * @return true if there are links, false otherwise + */ + boolean hasLinks(); + + /** + * How many {@link RiakLink}s does this RiakObject have? + * @return the number of {@link RiakLink}s this object has. + */ + int numLinks(); + + /** + * Checks if the collection of RiakLinks contains the one passed in. + * @param riakLink a RiakLink + * @return true if the RiakObject's link collection contains riakLink. + */ + boolean hasLink(final RiakLink riakLink); + + /** + * User-specified metadata for the object in the form of key-value pairs -- + * may be empty, but never be null. New key-value pairs can be added using + * addUsermeta() + * + * @deprecated Future versions will return an unmodifiable view of the user meta. Please use + * {@link RiakObject#addUsermeta(String, String)}, + * {@link RiakObject#removeUsermetaItem(String)}, + * {@link RiakObject#setUsermeta(Map)}, + * {@link RiakObject#hasUsermetaItem(String)}, + * {@link RiakObject#hasUsermeta()} and + * {@link RiakObject#getUsermetaItem(String)} to mutate and query the User meta collection + */ + @Deprecated Map getUsermeta(); + + /** + * Creates a copy of userMetaData. Changes made to the original collection will not be + * reflected in the RiakObject's state. + * @param userMetaData + */ + void setUsermeta(final Map userMetaData); + + /** + * Adds the key, value to the collection of user meta for this object. + * @param key + * @param value + * @return this RiakObject. + */ + RiakObject addUsermetaItem(String key, String value); + + /** + * @return true if there are any user meta data set on this RiakObject. + */ + boolean hasUsermeta(); + + /** + * @return how many user meta data items this RiakObject has. + */ + int numUsermetaItems(); + + /** + * @param key + * @return + */ + boolean hasUsermetaItem(String key); + + /** + * Get an item of user meta data. + * @param key the user meta data item key + * @return The value for the given key or null. + */ + String getUsermetaItem(String key); + + /** + * @param key the key of the item to remove + */ + void removeUsermetaItem(String key); + + Iterable usermetaKeys(); + + /** + * The object's content type as a MIME type + */ + String getContentType(); + + void setContentType(String contentType); + + /** + * The object's opaque vclock assigned by Riak + */ + String getVclock(); + + /** + * The modification date of the object determined by Riak + */ + String getLastmod(); + + /** + * Convenience method to get the last modified header parsed into a Date + * object. Returns null if header is null, malformed, or cannot be parsed. + */ + Date getLastmodAsDate(); + + /** + * An entity tag for the object assigned by Riak + */ + String getVtag(); + + /** + * Convenience method for calling + * {@link RiakClient#store(RiakObject, RequestMeta)} followed by + * {@link RiakObject#updateMeta(StoreResponse)} + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to store it with. + */ + StoreResponse store(RequestMeta meta); + + StoreResponse store(); + + /** + * Store this object to a different Riak instance. + * + * @param riak + * Riak instance to store this object to + * @param meta + * Same as {@link RiakClient#store(RiakObject, RequestMeta)} + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to store it with. + */ + StoreResponse store(RiakClient riak, RequestMeta meta); + + /** + * Convenience method for calling {@link RiakClient#fetch(String, String)} + * followed by {@link RiakObject#copyData(RiakObject)} + * + * @param meta + * Same as {@link RiakClient#fetch(String, String, RequestMeta)} + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to refetch it from. + */ + FetchResponse fetch(RequestMeta meta); + + FetchResponse fetch(); + + /** + * Convenience method for calling + * {@link RiakClient#fetchMeta(String, String, RequestMeta)} followed by + * {@link RiakObject#updateMeta(FetchResponse)} + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to refetch meta from. + */ + FetchResponse fetchMeta(RequestMeta meta); + + FetchResponse fetchMeta(); + + /** + * Convenience method for calling + * {@link RiakClient#delete(String, String, RequestMeta)}. + * + * @throws IllegalStateException + * if this object was not fetched from a Riak instance, so there + * is not associated server to delete from. + */ + HttpResponse delete(RequestMeta meta); + + HttpResponse delete(); + + /** + * Convenience methods for building a link walk specification starting from + * this object and calling + * {@link RiakClient#walk(String, String, RiakWalkSpec)} + * + * @param bucket + * The bucket to follow object links to + * @param tag + * The link tags to follow from this object + * @param keep + * Whether to keep the output from this link walking step. If not + * specified, then the output is only kept from the last step. + * @return A {@link LinkBuilder} object to continue building the walk query + * or to run it. + */ + LinkBuilder walk(String bucket, String tag, boolean keep); + + LinkBuilder walk(String bucket, String tag); + + LinkBuilder walk(String bucket, boolean keep); + + LinkBuilder walk(String bucket); + + LinkBuilder walk(); + + LinkBuilder walk(boolean keep); + + /** + * Serializes this object to an existing {@link HttpMethod} which can be + * sent as an HTTP request. Specifically, sends the object's link, + * user-defined metadata and vclock as HTTP headers and the value as the + * body. Used by {@link RiakClient} to create PUT requests. + */ + void writeToHttpMethod(HttpMethod httpMethod); + + /** + * A thread safe, snapshot Iterable view of the state of this RiakObject's {@link RiakLink}s at call time. + * Modifications are *NOT* supported. + * @return Iterable for this RiakObject's {@link RiakLink}s + */ + Iterable iterableLinks(); + +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/RiakBucketInfo.java b/src/main/java/com/basho/riak/client/http/RiakBucketInfo.java new file mode 100644 index 000000000..b9304fe80 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/RiakBucketInfo.java @@ -0,0 +1,171 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.util.ArrayList; +import java.util.Collection; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.basho.riak.client.http.util.Constants; + +/** + * Represents the metadata stored in a bucket including its schema and the list + * of keys contained in the bucket. + */ +public class RiakBucketInfo { + + private JSONObject schema; + private Collection keys; + + /** + * Returns the bucket's properties. + */ + public JSONObject getSchema() { + return schema; + } + + /** + * The object keys in this bucket. + */ + public Collection getKeys() { + return keys; + } + + /** + * Construct a bucket info to populate for a writeSchema request. + */ + public RiakBucketInfo() { + this(null, null); + } + + /** + * Construct a bucket info using the JSON data from a listBucket() response. + * + * @param schema + * The JSON object containing the bucket's schema + * @param keys + * The keys in the bucket + */ + public RiakBucketInfo(JSONObject schema, Collection keys) { + + if (schema != null) { + this.schema = schema; + } else { + this.schema = new JSONObject(); + } + if (keys != null) { + this.keys = keys; + } else { + this.keys = new ArrayList(); + } + } + + /** + * Allow siblings to be returned for an object. If false, last write wins. + */ + public void setAllowMult(boolean allowMult) { + try { + getSchema().put(Constants.FL_SCHEMA_ALLOW_MULT, allowMult); + } catch (JSONException unreached) { + throw new IllegalStateException("operation is valid json", unreached); + } + } + + public Boolean getAllowMult() { + return getSchema().optBoolean(Constants.FL_SCHEMA_ALLOW_MULT); + } + + /** + * Number of replicas per object in this bucket. + */ + public void setNVal(int n) { + try { + getSchema().put(Constants.FL_SCHEMA_NVAL, n); + } catch (JSONException unreached) { + throw new IllegalStateException("operation is valid json", unreached); + } + } + + public Integer getNVal() { + return getSchema().optInt(Constants.FL_SCHEMA_NVAL); + } + + /** + * Erlang module and name of the function to use to hash object keys. See + * Riak's documentation. + */ + public void setCHashFun(String mod, String fun) { + if (mod == null) { + mod = ""; + } + if (fun == null) { + fun = ""; + } + try { + JSONObject chashfun = new JSONObject(); + chashfun.put(Constants.FL_SCHEMA_CHASHFUN_MOD, mod); + chashfun.put(Constants.FL_SCHEMA_CHASHFUN_FUN, fun); + getSchema().put(Constants.FL_SCHEMA_CHASHFUN, chashfun); + } catch (JSONException unreached) { + throw new IllegalStateException("operation is valid json", unreached); + } + } + + /** + * The chash_keyfun property as {@literal :} + */ + public String getCHashFun() { + JSONObject chashfun = getSchema().optJSONObject(Constants.FL_SCHEMA_CHASHFUN); + if (chashfun == null) + return null; + String mod = chashfun.optString(Constants.FL_SCHEMA_CHASHFUN_MOD, ""); + String fun = chashfun.optString(Constants.FL_SCHEMA_CHASHFUN_FUN, ""); + return mod + ":" + fun; + } + + /** + * Erlang module and name of the function to use to walk object links. See + * Riak's documentation. + */ + public void setLinkFun(String mod, String fun) { + if (mod == null) { + mod = ""; + } + if (fun == null) { + fun = ""; + } + try { + JSONObject linkfun = new JSONObject(); + linkfun.put(Constants.FL_SCHEMA_LINKFUN_MOD, mod); + linkfun.put(Constants.FL_SCHEMA_LINKFUN_FUN, fun); + getSchema().put(Constants.FL_SCHEMA_LINKFUN, linkfun); + } catch (JSONException unreached) { + throw new IllegalStateException("operation is valid json", unreached); + } + } + + /** + * The linkfun property as {@literal :} + */ + public String getLinkFun() { + JSONObject linkfun = getSchema().optJSONObject(Constants.FL_SCHEMA_LINKFUN); + if (linkfun == null) + return null; + String mod = linkfun.optString(Constants.FL_SCHEMA_LINKFUN_MOD, ""); + String fun = linkfun.optString(Constants.FL_SCHEMA_LINKFUN_FUN, ""); + return mod + ":" + fun; + } +} diff --git a/src/main/java/com/basho/riak/client/http/RiakClient.java b/src/main/java/com/basho/riak/client/http/RiakClient.java new file mode 100644 index 000000000..2ee2ceb62 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/RiakClient.java @@ -0,0 +1,407 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpClient; +import org.json.JSONException; +import org.json.JSONObject; + +import com.basho.riak.client.http.request.MapReduceBuilder; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.MapReduceResponse; +import com.basho.riak.client.http.response.RiakExceptionHandler; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.StreamHandler; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.ClientHelper; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; + +/** + * Primary interface for interacting with Riak via HTTP. + */ +public class RiakClient implements HttpRiakClient { + + private ClientHelper helper; + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getConfig() + */ + public RiakConfig getConfig() { + return helper.getConfig(); + } + + public RiakClient(RiakConfig config) { + this(config, null); + } + + public RiakClient(RiakConfig config, String clientId) { + helper = new ClientHelper(config, clientId); + } + + public RiakClient(String url) { + this(new RiakConfig(url), null); + } + + public RiakClient(String url, String clientId) { + this(new RiakConfig(url), clientId); + } + + // Package protected constructor used for testing + RiakClient(ClientHelper helper) { + this.helper = helper; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#setBucketSchema(java.lang.String, com.basho.riak.client.RiakBucketInfo, com.basho.riak.client.request.RequestMeta) + */ + public HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta) { + JSONObject schema = null; + try { + schema = new JSONObject().put(Constants.FL_SCHEMA, bucketInfo.getSchema()); + } catch (JSONException unreached) { + throw new IllegalStateException("wrapping valid json should be valid", unreached); + } + + return helper.setBucketSchema(bucket, schema, meta); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#setBucketSchema(java.lang.String, com.basho.riak.client.RiakBucketInfo) + */ + public HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo) { + return setBucketSchema(bucket, bucketInfo, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getBucketSchema(java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public BucketResponse getBucketSchema(String bucket, RequestMeta meta) { + HttpResponse r = helper.getBucketSchema(bucket, meta); + try { + return getBucketResponse(r); + } catch (JSONException e) { + try { + return new BucketResponse(helper.toss(new RiakResponseRuntimeException(r, e))); + } catch (Exception e1) { + throw new IllegalStateException( + "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw"); + } + } catch (IOException e) { + try { + return new BucketResponse(helper.toss(new RiakIORuntimeException(e))); + } catch (Exception e1) { + throw new IllegalStateException( + "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to read it or throw"); + } + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getBucketSchema(java.lang.String) + */ + public BucketResponse getBucketSchema(String bucket) { + return getBucketSchema(bucket, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#listBucket(java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public BucketResponse listBucket(String bucket, RequestMeta meta) { + return listBucket(bucket, meta, false); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#listBucket(java.lang.String) + */ + public BucketResponse listBucket(String bucket) { + return listBucket(bucket, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#streamBucket(java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public BucketResponse streamBucket(String bucket, RequestMeta meta) { + return listBucket(bucket, meta, true); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#streamBucket(java.lang.String) + */ + public BucketResponse streamBucket(String bucket) { + return streamBucket(bucket, null); + } + + BucketResponse listBucket(String bucket, RequestMeta meta, boolean streamResponse) { + HttpResponse r = helper.listBucket(bucket, meta, streamResponse); + try { + return getBucketResponse(r); + } catch (JSONException e) { + try { + return new BucketResponse(helper.toss(new RiakResponseRuntimeException(r, e))); + } catch (Exception e1) { + throw new IllegalStateException( + "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to parse it or throw"); + } + } catch (IOException e) { + try { + return new BucketResponse(helper.toss(new RiakIORuntimeException(e))); + } catch (Exception e1) { + throw new IllegalStateException( + "helper.toss() returns a unsuccessful result, so BucketResponse shouldn't try to read it or throw"); + } + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#store(com.basho.riak.client.RiakObject, com.basho.riak.client.request.RequestMeta) + */ + public StoreResponse store(RiakObject object, RequestMeta meta) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_RETURN_BODY) == null) { + meta.setQueryParam(Constants.QP_RETURN_BODY, "true"); + } + + setAcceptHeader(meta); + HttpResponse r = helper.store(object, meta); + return new StoreResponse(new FetchResponse(r, this)); + } + + /** + * @param meta + */ + private void setAcceptHeader(RequestMeta meta) { + String accept = meta.getHeader(Constants.HDR_ACCEPT); + if (accept == null) { + meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_ANY + ", " + Constants.CTYPE_MULTIPART_MIXED); + } else { + meta.setHeader(Constants.HDR_ACCEPT, accept + ", " + Constants.CTYPE_MULTIPART_MIXED); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#store(com.basho.riak.client.RiakObject) + */ + public StoreResponse store(RiakObject object) { + return store(object, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#fetchMeta(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public FetchResponse fetchMeta(String bucket, String key, RequestMeta meta) { + try { + return getFetchResponse(helper.fetchMeta(bucket, key, meta)); + } catch (RiakResponseRuntimeException e) { + return new FetchResponse(helper.toss(e), this); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#fetchMeta(java.lang.String, java.lang.String) + */ + public FetchResponse fetchMeta(String bucket, String key) { + return fetchMeta(bucket, key, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#fetch(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public FetchResponse fetch(String bucket, String key, RequestMeta meta) { + return fetch(bucket, key, meta, false); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#fetch(java.lang.String, java.lang.String) + */ + public FetchResponse fetch(String bucket, String key) { + return fetch(bucket, key, null, false); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public FetchResponse stream(String bucket, String key, RequestMeta meta) { + return fetch(bucket, key, meta, true); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String) + */ + public FetchResponse stream(String bucket, String key) { + return fetch(bucket, key, null, true); + } + + FetchResponse fetch(String bucket, String key, RequestMeta meta, boolean streamResponse) { + if (meta == null) { + meta = new RequestMeta(); + } + + setAcceptHeader(meta); + HttpResponse r = helper.fetch(bucket, key, meta, streamResponse); + + try { + return getFetchResponse(r); + } catch (RiakResponseRuntimeException e) { + return new FetchResponse(helper.toss(e), this); + } + + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String, com.basho.riak.client.response.StreamHandler, com.basho.riak.client.request.RequestMeta) + */ + public boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException { + return helper.stream(bucket, key, handler, meta); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#delete(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public HttpResponse delete(String bucket, String key, RequestMeta meta) { + return helper.delete(bucket, key, meta); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#delete(java.lang.String, java.lang.String) + */ + public HttpResponse delete(String bucket, String key) { + return delete(bucket, key, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta) { + HttpResponse r = helper.walk(bucket, key, walkSpec, meta); + + try { + return getWalkResponse(r); + } catch (RiakResponseRuntimeException e) { + return new WalkResponse(helper.toss(e), this); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, java.lang.String) + */ + public WalkResponse walk(String bucket, String key, String walkSpec) { + return walk(bucket, key, walkSpec, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#walk(java.lang.String, java.lang.String, com.basho.riak.client.request.RiakWalkSpec) + */ + public WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec) { + return walk(bucket, key, walkSpec.toString(), null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#mapReduce(java.lang.String, com.basho.riak.client.request.RequestMeta) + */ + public MapReduceResponse mapReduce(String job, RequestMeta meta) { + HttpResponse r = helper.mapReduce(job, meta); + try { + return getMapReduceResponse(r); + } catch (JSONException e) { + helper.toss(new RiakResponseRuntimeException(r, e)); + return null; + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#mapReduce(java.lang.String) + */ + public MapReduceResponse mapReduce(String job) { + return mapReduce(job, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#mapReduceOverBucket(java.lang.String) + */ + public MapReduceBuilder mapReduceOverBucket(String bucket) { + return new MapReduceBuilder(this).setBucket(bucket); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#mapReduceOverObjects(java.util.Map) + */ + public MapReduceBuilder mapReduceOverObjects(Map> objects) { + return new MapReduceBuilder(this).setRiakObjects(objects); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getExceptionHandler() + */ + public RiakExceptionHandler getExceptionHandler() { + return helper.getExceptionHandler(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#setExceptionHandler(com.basho.riak.client.response.RiakExceptionHandler) + */ + public void setExceptionHandler(RiakExceptionHandler exceptionHandler) { + helper.setExceptionHandler(exceptionHandler); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getHttpClient() + */ + public HttpClient getHttpClient() { + return helper.getHttpClient(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#getClientId() + */ + public byte[] getClientId() { + return helper.getClientId(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakClient#setClientId(java.lang.String) + */ + public void setClientId(String clientId) { + helper.setClientId(clientId); + } + + // Encapsulate response creation so it can be stubbed for testing + BucketResponse getBucketResponse(HttpResponse r) throws JSONException, IOException { + return new BucketResponse(r); + } + + FetchResponse getFetchResponse(HttpResponse r) throws RiakResponseRuntimeException { + return new FetchResponse(r, this); + } + + WalkResponse getWalkResponse(HttpResponse r) throws RiakResponseRuntimeException { + return new WalkResponse(r, this); + } + + MapReduceResponse getMapReduceResponse(HttpResponse r) throws JSONException { + return new MapReduceResponse(r); + } +} diff --git a/src/main/java/com/basho/riak/client/http/RiakConfig.java b/src/main/java/com/basho/riak/client/http/RiakConfig.java new file mode 100644 index 000000000..557f81afb --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/RiakConfig.java @@ -0,0 +1,185 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethodRetryHandler; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; + +/** + * Configuration settings for connecting to a Riak instance such as the base + * Riak URL and HttpClient settings. A pre-constructed HttpClient can also be + * provided. + */ +public class RiakConfig { + + public static Pattern BASE_URL_PATTERN = Pattern.compile("^((?:[^:]*://)?[^/]*)"); + + private String url = null; + private String baseUrl = null; + private String mapredPath = "/mapred"; + private HttpClient httpClient = null; + private Integer timeout = null; + private Integer maxConnections = null; + private HttpMethodRetryHandler retryHandler = null; + + public RiakConfig() {} + + public RiakConfig(String url) { + if (url == null || url.length() == 0) + throw new IllegalArgumentException(); + + this.setUrl(url); + } + + public RiakConfig(URL url) { + if (url == null) { + throw new IllegalArgumentException(); + } + + String protocol = url.getProtocol().toLowerCase(); + if(!protocol.equals("http") && !protocol.equals("https")) { + throw new IllegalArgumentException(); + } + + this.setUrl(url.toExternalForm()); + } + + public RiakConfig(String ip, String port, String prefix) { + if (prefix == null) { + prefix = ""; + } + + this.setUrl("http://" + ip + ":" + port + prefix); + } + + /** + * The base URL used by a client to construct object URLs + */ + public String getUrl() { + return url; + } + + /** + * Set the base URL that clients should use to construct object URLs (e.g. + * http://localhost:8098/riak). + */ + public void setUrl(String url) { + this.url = url.endsWith("/") ? url.substring(0, url.length() - 1) : url; + + Matcher m = BASE_URL_PATTERN.matcher(url); + if (m.find()) { + baseUrl = m.group(); + } else { + baseUrl = this.url; + } + } + + /** + * The full URL of Riak map reduce resource, which is calculated by + * combining the host and port from the Riak URL and the map reduce path. + */ + public String getMapReduceUrl() { + return baseUrl + mapredPath; + } + + /** + * The host and port of the Riak server, which is extracted from the + * specified Riak URL. + */ + public String getBaseUrl() { + return baseUrl; + } + + /** + * The path to the Riak map reduce resource, which defaults to /mapred + */ + public String getMapReducePath() { + return mapredPath; + } + + public void setMapReducePath(String path) { + if (!path.startsWith("/")) { + path = "/" + path; + } + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + mapredPath = path; + } + + /** + * The pre-constructed HttpClient for a client to use if one was provided + */ + public HttpClient getHttpClient() { + return httpClient; + } + + /** + * Provide a pre-constructed HttpClient for clients to use to connect to + * Riak + */ + public void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Value to set for the properties: + * {@link HttpClientParams#CONNECTION_MANAGER_TIMEOUT}, + * {@link HttpClientParams#SO_TIMEOUT}, + * {@link HttpConnectionManagerParams#CONNECTION_TIMEOUT} which sets the + * timeout milliseconds for retrieving an HTTP connection and data over the + * connection. Null for default. + */ + public void setTimeout(final Integer timeout) { + this.timeout = timeout; + } + + public Integer getTimeout() { + return timeout; + } + + /** + * Value to set for the HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS + * and the HttpConnectionManagerParams.MAX_HOST_CONNECTIONS properties: + * overall maximum number of connections used by the HttpClient and the + * maximum number of connections per host. The latter is set to overcome + * the default 2 connections per host in HttpClient. + */ + public void setMaxConnections(Integer maxConnections) { + this.maxConnections = maxConnections; + } + + public Integer getMaxConnections() { + return maxConnections; + } + + /** + * Value to set for the HttpClientParams.RETRY_HANDLER property: the default + * retry handler for requests. + * + * @see org.apache.commons.httpclient.DefaultHttpMethodRetryHandler + */ + public HttpMethodRetryHandler getRetryHandler() { + return retryHandler; + } + + public void setRetryHandler(HttpMethodRetryHandler retryHandler) { + this.retryHandler = retryHandler; + } +} diff --git a/src/main/java/com/basho/riak/client/http/RiakLink.java b/src/main/java/com/basho/riak/client/http/RiakLink.java new file mode 100644 index 000000000..d3b79a2fe --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/RiakLink.java @@ -0,0 +1,98 @@ +/* + * This file is provided 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.basho.riak.client.http; + +/** + * Represents a link to a Riak object. The target object is identified by its + * bucket and key and the link is classified by a tag. + */ +public class RiakLink { + + private String bucket; + private String key; + private String tag; + + public RiakLink(String bucket, String key, String tag) { + this.bucket = bucket; + this.key = key; + this.tag = tag; + } + + /** Copy constructor */ + public RiakLink(RiakLink link) { + bucket = link.bucket; + key = link.key; + tag = link.tag; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#getBucket() + */ + public String getBucket() { + return bucket; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#setBucket(java.lang.String) + */ + @Deprecated + public void setBucket(String bucket) { + this.bucket = bucket; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#getKey() + */ + public String getKey() { + return key; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#setKey(java.lang.String) + */ + @Deprecated + public void setKey(String key) { + this.key = key; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#getTag() + */ + public String getTag() { + return tag; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakLink#setTag(java.lang.String) + */ + @Deprecated + public void setTag(String tag) { + this.tag = tag; + } + + @Override public boolean equals(Object obj) { + if (!(obj instanceof RiakLink)) + return false; + RiakLink other = (RiakLink) obj; + + boolean bucketEq = (bucket != null && bucket.equals(other.bucket)) || (bucket == null && other.bucket == null); + boolean keyEq = (key != null && key.equals(other.key)) || (key == null && other.key == null); + boolean tagEq = (tag != null && tag.equals(other.tag)) || (tag == null && other.tag == null); + return bucketEq && keyEq && tagEq; + } + + @Override public String toString() { + return new StringBuilder("[").append(bucket).append(",").append(key).append(",").append(tag).append("]").toString(); + } +} diff --git a/src/main/java/com/basho/riak/client/http/RiakObject.java b/src/main/java/com/basho/riak/client/http/RiakObject.java new file mode 100644 index 000000000..ae3b49af1 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/RiakObject.java @@ -0,0 +1,831 @@ +/* + * This file is provided 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.basho.riak.client.http; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.EntityEnclosingMethod; +import org.apache.commons.httpclient.methods.InputStreamRequestEntity; +import org.apache.commons.httpclient.util.DateParseException; +import org.apache.commons.httpclient.util.DateUtil; + +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.Constants; + +/** + * A Riak object. + */ +public class RiakObject implements HttpRiakObject { + + private RiakClient riak; + private String bucket; + private String key; + private byte[] value; + private List links; + private Map userMetaData; + private String contentType; + private String vclock; + private String lastmod; + private String vtag; + private InputStream valueStream; + private Long valueStreamLength; + + /** + * Create an empty object. The content type defaults to + * application/octet-stream. + * + * @param riak + * Riak instance this object is associated with, which is used by + * the convenience methods in this class (e.g. + * {@link RiakObject#store()}). + * @param bucket + * The object's bucket + * @param key + * The object's key + * @param value + * The object's value + * @param contentType + * The object's content type which defaults to + * application/octet-stream if null. + * @param links + * Links to other objects + * @param userMetaData + * Custom metadata key-value pairs for this object + * @param vclock + * An opaque vclock assigned by Riak + * @param lastmod + * The last time this object was modified according to Riak + * @param vtag + * This object's entity tag assigned by Riak + */ + public RiakObject(RiakClient riak, String bucket, String key, byte[] value, String contentType, + List links, Map userMetaData, String vclock, String lastmod, String vtag) { + this.riak = riak; + this.bucket = bucket; + this.key = key; + this.vclock = vclock; + this.lastmod = lastmod; + this.vtag = vtag; + + safeSetValue(value); + this.contentType = contentType == null ? Constants.CTYPE_OCTET_STREAM : contentType; + safeSetLinks(links); + safeSetUsermetaData(userMetaData); + } + + public RiakObject(RiakClient riak, String bucket, String key) { + this(riak, bucket, key, null, null, null, null, null, null, null); + } + + public RiakObject(RiakClient riak, String bucket, String key, byte[] value) { + this(riak, bucket, key, value, null, null, null, null, null, null); + } + + public RiakObject(RiakClient riak, String bucket, String key, byte[] value, String contentType) { + this(riak, bucket, key, value, contentType, null, null, null, null, null); + } + + public RiakObject(RiakClient riak, String bucket, String key, byte[] value, String contentType, List links) { + this(riak, bucket, key, value, contentType, links, null, null, null, null); + } + + public RiakObject(RiakClient riak, String bucket, String key, byte[] value, String contentType, + List links, Map userMetaData) { + this(riak, bucket, key, value, contentType, links, userMetaData, null, null, null); + } + + public RiakObject(String bucket, String key) { + this(null, bucket, key, null, null, null, null, null, null, null); + } + + public RiakObject(String bucket, String key, byte[] value) { + this(null, bucket, key, value, null, null, null, null, null, null); + } + + public RiakObject(String bucket, String key, byte[] value, String contentType) { + this(null, bucket, key, value, contentType, null, null, null, null, null); + } + + public RiakObject(String bucket, String key, byte[] value, String contentType, List links) { + this(null, bucket, key, value, contentType, links, null, null, null, null); + } + + public RiakObject(String bucket, String key, byte[] value, String contentType, List links, + Map userMetaData) { + this(null, bucket, key, value, contentType, links, userMetaData, null, null, null); + } + + public RiakObject(String bucket, String key, byte[] value, String contentType, List links, + Map userMetaData, String vclock, String lastmod, String vtag) { + this(null, bucket, key, value, contentType, links, userMetaData, vclock, lastmod, vtag); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getRiakClient() + */ + public RiakClient getRiakClient() { + return riak; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setRiakClient(com.basho.riak.client.RiakClient) + */ + public RiakObject setRiakClient(RiakClient client) { + riak = client; + return this; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#copyData(com.basho.riak.client.RiakObject) + */ + public void copyData(RiakObject object) { + if (object == null) + return; + + if (object.value != null) { + value = object.value.clone(); + } else { + value = null; + } + + valueStream = object.valueStream; + valueStreamLength = object.valueStreamLength; + + setLinks(object.links); + + userMetaData = new HashMap(); + if (object.userMetaData != null) { + userMetaData.putAll(object.userMetaData); + } + contentType = object.contentType; + vclock = object.vclock; + lastmod = object.lastmod; + vtag = object.vtag; + } + + /** + * Perform a shallow copy of the object + */ + void shallowCopy(RiakObject object) { + value = object.value; + this.links = object.links; + userMetaData = object.userMetaData; + contentType = object.contentType; + vclock = object.vclock; + lastmod = object.lastmod; + vtag = object.vtag; + valueStream = object.valueStream; + valueStreamLength = object.valueStreamLength; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#updateMeta(com.basho.riak.client.response.StoreResponse) + */ + public void updateMeta(StoreResponse response) { + if (response == null) { + vclock = null; + lastmod = null; + vtag = null; + } else { + vclock = response.getVclock(); + lastmod = response.getLastmod(); + vtag = response.getVtag(); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#updateMeta(com.basho.riak.client.response.FetchResponse) + */ + public void updateMeta(FetchResponse response) { + if (response == null || response.getObject() == null) { + vclock = null; + lastmod = null; + vtag = null; + } else { + vclock = response.getObject().getVclock(); + lastmod = response.getObject().getLastmod(); + vtag = response.getObject().getVtag(); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getBucket() + */ + public String getBucket() { + return bucket; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getKey() + */ + public String getKey() { + return key; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getValue() + */ + public String getValue() { + return (value == null ? null : new String(value)); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getValueAsBytes() + */ + public byte[] getValueAsBytes() { + return value == null ? value : value.clone(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setValue(java.lang.String) + */ + public void setValue(String value) { + if (value != null) { + this.value = value.getBytes(); + } else { + this.value = null; + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setValue(byte[]) + */ + public void setValue(byte[] value) { + safeSetValue(value); + } + + /** + * + * @param value + */ + private void safeSetValue(final byte[] value) { + if(value != null) { + this.value = value.clone(); + } else { + this.value = null; + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setValueStream(java.io.InputStream, java.lang.Long) + */ + public void setValueStream(InputStream in, Long len) { + valueStream = in; + valueStreamLength = len; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setValueStream(java.io.InputStream) + */ + public void setValueStream(InputStream in) { + valueStream = in; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getValueStream() + */ + public InputStream getValueStream() { + return valueStream; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setValueStreamLength(java.lang.Long) + */ + public void setValueStreamLength(Long len) { + valueStreamLength = len; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getValueStreamLength() + */ + public Long getValueStreamLength() { + return valueStreamLength; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getLinks() + */ + @Deprecated + public List getLinks() { + return this.links; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setLinks(java.util.List) + */ + public void setLinks(List links) { + safeSetLinks(links); + } + + private void safeSetLinks(final List links) { + if (links == null) { + this.links = new CopyOnWriteArrayList(); + } else { + this.links = new CopyOnWriteArrayList(deepCopy(links)); + } + } + + /** + * Creates a new RiakLink for each RiakLink in links and adds it to a new List. + * + * @param links a List of {@link RiakLink}s + * @return a deep copy of List. + */ + private List deepCopy(List links) { + final ArrayList copyLinks = new ArrayList(); + + for(RiakLink link : links) { + copyLinks.add(new RiakLink(link)); + } + + return copyLinks; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#addLink(com.basho.riak.client.RiakLink) + */ + public RiakObject addLink(RiakLink link) { + if (link != null) { + links.add(link); + } + return this; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#removeLink(com.basho.riak.client.RiakLink) + */ + public RiakObject removeLink(final RiakLink link) { + this.links.remove(link); + return this; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#hasLinks() + */ + public boolean hasLinks() { + return !links.isEmpty(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#numLinks() + */ + public int numLinks() { + return links.size(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#hasLink(com.basho.riak.client.RiakLink) + */ + public boolean hasLink(final RiakLink riakLink) { + return links.contains(riakLink); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getUsermeta() + */ + @Deprecated + public Map getUsermeta() { + return userMetaData; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setUsermeta(java.util.Map) + */ + public void setUsermeta(final Map userMetaData) { + safeSetUsermetaData(userMetaData); + } + + private void safeSetUsermetaData(final Map userMetaData) { + if (userMetaData == null) { + this.userMetaData = new ConcurrentHashMap(); + } else { + this.userMetaData = new ConcurrentHashMap(userMetaData); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#addUsermetaItem(java.lang.String, java.lang.String) + */ + public RiakObject addUsermetaItem(String key, String value) { + userMetaData.put(key, value); + return this; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#hasUsermeta() + */ + public boolean hasUsermeta() { + return !userMetaData.isEmpty(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#numUsermetaItems() + */ + public int numUsermetaItems() { + return userMetaData.size(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#hasUsermetaItem(java.lang.String) + */ + public boolean hasUsermetaItem(String key) { + return userMetaData.containsKey(key); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getUsermetaItem(java.lang.String) + */ + public String getUsermetaItem(String key) { + return userMetaData.get(key); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#removeUsermetaItem(java.lang.String) + */ + public void removeUsermetaItem(String key) { + userMetaData.remove(key); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#usermetaKeys() + */ + public Iterable usermetaKeys() { + return userMetaData.keySet(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getContentType() + */ + public String getContentType() { + return contentType; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#setContentType(java.lang.String) + */ + public void setContentType(String contentType) { + if (contentType != null) { + this.contentType = contentType; + } else { + this.contentType = Constants.CTYPE_OCTET_STREAM; + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getVclock() + */ + public String getVclock() { + return vclock; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getLastmod() + */ + public String getLastmod() { + return lastmod; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getLastmodAsDate() + */ + public Date getLastmodAsDate() { + try { + return DateUtil.parseDate(lastmod); + } catch (DateParseException e) { + return null; + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#getVtag() + */ + public String getVtag() { + return vtag; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#store(com.basho.riak.client.request.RequestMeta) + */ + public StoreResponse store(RequestMeta meta) { + return store(riak, meta); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#store() + */ + public StoreResponse store() { + return store(riak, null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#store(com.basho.riak.client.RiakClient, com.basho.riak.client.request.RequestMeta) + */ + public StoreResponse store(RiakClient riak, RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot store an object without a RiakClient"); + + StoreResponse r = riak.store(this, meta); + if (r.isSuccess()) { + this.updateMeta(r); + } + return r; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#fetch(com.basho.riak.client.request.RequestMeta) + */ + public FetchResponse fetch(RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot fetch an object without a RiakClient"); + + FetchResponse r = riak.fetch(bucket, key, meta); + if (r.getObject() != null) { + RiakObject other = r.getObject(); + shallowCopy(other); + r.setObject(this); + } + return r; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#fetch() + */ + public FetchResponse fetch() { + return fetch(null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#fetchMeta(com.basho.riak.client.request.RequestMeta) + */ + public FetchResponse fetchMeta(RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot fetch meta for an object without a RiakClient"); + + FetchResponse r = riak.fetchMeta(bucket, key, meta); + if (r.isSuccess()) { + this.updateMeta(r); + } + return r; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#fetchMeta() + */ + public FetchResponse fetchMeta() { + return fetchMeta(null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#delete(com.basho.riak.client.request.RequestMeta) + */ + public HttpResponse delete(RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot delete an object without a RiakClient"); + + return riak.delete(bucket, key, meta); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#delete() + */ + public HttpResponse delete() { + return delete(null); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk(java.lang.String, java.lang.String, boolean) + */ + public LinkBuilder walk(String bucket, String tag, boolean keep) { + return new LinkBuilder().walk(bucket, tag, keep); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk(java.lang.String, java.lang.String) + */ + public LinkBuilder walk(String bucket, String tag) { + return new LinkBuilder().walk(bucket, tag); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk(java.lang.String, boolean) + */ + public LinkBuilder walk(String bucket, boolean keep) { + return new LinkBuilder().walk(bucket, keep); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk(java.lang.String) + */ + public LinkBuilder walk(String bucket) { + return new LinkBuilder().walk(bucket); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk() + */ + public LinkBuilder walk() { + return new LinkBuilder().walk(); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#walk(boolean) + */ + public LinkBuilder walk(boolean keep) { + return new LinkBuilder().walk(keep); + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#writeToHttpMethod(org.apache.commons.httpclient.HttpMethod) + */ + public void writeToHttpMethod(HttpMethod httpMethod) { + // Serialize headers + String basePath = getBasePathFromHttpMethod(httpMethod); + writeLinks(httpMethod, basePath); + for (String name : userMetaData.keySet()) { + httpMethod.setRequestHeader(Constants.HDR_USERMETA_REQ_PREFIX + name, userMetaData.get(name)); + } + if (vclock != null) { + httpMethod.setRequestHeader(Constants.HDR_VCLOCK, vclock); + } + + // Serialize body + if (httpMethod instanceof EntityEnclosingMethod) { + EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) httpMethod; + + // Any value set using setValueAsStream() has precedent over value + // set using setValue() + if (valueStream != null) { + if (valueStreamLength != null && valueStreamLength >= 0) { + entityEnclosingMethod.setRequestEntity(new InputStreamRequestEntity(valueStream, valueStreamLength, + contentType)); + } else { + entityEnclosingMethod.setRequestEntity(new InputStreamRequestEntity(valueStream, contentType)); + } + } else if (value != null) { + entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity(value, contentType)); + } else { + entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity("".getBytes(), contentType)); + } + } + } + + private void writeLinks(HttpMethod httpMethod, String basePath) { + StringBuilder linkHeader = new StringBuilder(); + + for (RiakLink link : this.links) { + if (linkHeader.length() > 0) { + linkHeader.append(", "); + } + linkHeader.append("<"); + linkHeader.append(basePath); + linkHeader.append("/"); + linkHeader.append(link.getBucket()); + linkHeader.append("/"); + linkHeader.append(link.getKey()); + linkHeader.append(">; "); + linkHeader.append(Constants.LINK_TAG); + linkHeader.append("=\""); + linkHeader.append(link.getTag()); + linkHeader.append("\""); + + // To avoid (MochiWeb) problems with too long headers, flush if + // it grows too big: + if (linkHeader.length() > 2000) { + httpMethod.addRequestHeader(Constants.HDR_LINK, linkHeader.toString()); + linkHeader = new StringBuilder(); + } + } + if (linkHeader.length() > 0) { + httpMethod.addRequestHeader(Constants.HDR_LINK, linkHeader.toString()); + } + } + + String getBasePathFromHttpMethod(HttpMethod httpMethod) { + if (httpMethod == null || httpMethod.getPath() == null) + return ""; + + String path = httpMethod.getPath(); + int idx = path.length() - 1; + + // ignore any trailing slash + if (path.endsWith("/")) { + idx--; + } + + // trim off last two path components + idx = path.lastIndexOf('/', idx); + idx = path.lastIndexOf('/', idx - 1); + + if (idx <= 0) + return ""; + + return path.substring(0, idx); + } + + /** + * Created by links() as a convenient way to build up link walking queries + */ + public class LinkBuilder { + + private RiakWalkSpec walkSpec = new RiakWalkSpec(); + + public LinkBuilder walk() { + walkSpec.addStep(RiakWalkSpec.WILDCARD, RiakWalkSpec.WILDCARD); + return this; + } + + public LinkBuilder walk(boolean keep) { + walkSpec.addStep(RiakWalkSpec.WILDCARD, RiakWalkSpec.WILDCARD, keep); + return this; + } + + public LinkBuilder walk(String bucket) { + walkSpec.addStep(bucket, RiakWalkSpec.WILDCARD); + return this; + } + + public LinkBuilder walk(String bucket, boolean keep) { + walkSpec.addStep(bucket, RiakWalkSpec.WILDCARD, keep); + return this; + } + + public LinkBuilder walk(String bucket, String tag) { + walkSpec.addStep(bucket, tag); + return this; + } + + public LinkBuilder walk(String bucket, String tag, boolean keep) { + walkSpec.addStep(bucket, tag, keep); + return this; + } + + public String getWalkSpec() { + return walkSpec.toString(); + } + + /** + * Execute the link walking query by calling + * {@link RiakClient#walk(String, String, String, RequestMeta)}. + * + * @param meta + * Extra metadata to attach to the request such as HTTP + * headers or query parameters. + * @return See + * {@link RiakClient#walk(String, String, String, RequestMeta)}. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak + * server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + public WalkResponse run(RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot perform object link walk without a RiakClient"); + return riak.walk(bucket, key, getWalkSpec(), meta); + } + + public WalkResponse run() { + return run(null); + } + } + + /* (non-Javadoc) + * @see com.basho.riak.client.HttpRiakObject#iterableLinks() + */ + public Iterable iterableLinks() { + return new Iterable() { + public Iterator iterator() { + return links.iterator(); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/ErlangFunction.java b/src/main/java/com/basho/riak/client/http/mapreduce/ErlangFunction.java new file mode 100644 index 000000000..4f6612b6f --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/ErlangFunction.java @@ -0,0 +1,54 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Represents an Erlang function used in a map or reduce phase + * of a map/reduce job + * + */ +public class ErlangFunction implements MapReduceFunction { + + private String module; + private String function; + + /** + * Constructs a new ErlangFunction instance + * @param module Erlang module name + * @param functionName Erlang function name + */ + public ErlangFunction(String module, String functionName) { + this.module = module; + this.function = functionName; + } + + /** + * Converts the function definition to JSON + */ + public JSONObject toJson() { + try { + JSONObject retval = new JSONObject(); + retval.put("language", "erlang"); + retval.put("module", this.module); + retval.put("function", this.function); + return retval; + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a string"); + } + } + +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/JavascriptFunction.java b/src/main/java/com/basho/riak/client/http/mapreduce/JavascriptFunction.java new file mode 100644 index 000000000..89714dfc8 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/JavascriptFunction.java @@ -0,0 +1,73 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Represents a Javascript function used in a map or reduce phase + * of a map/reduce job + * + */ +public class JavascriptFunction implements MapReduceFunction { + + private String source; + private MapReduceFunction.Types type; + + /** + * Shortcut for creating a reference to a named + * Javascript function + * @param functionName Name of Javascript function ("Riak.mapValuesJson") + */ + public static JavascriptFunction named(String functionName) { + return new JavascriptFunction(MapReduceFunction.Types.NAMED, functionName); + } + + /** + * Shortcut for creating a reference to an anonymous + * Javascript function + * @param functionSource Javascript function source ("function(v) { return [v]; }") + */ + public static JavascriptFunction anon(String functionSource) { + return new JavascriptFunction(MapReduceFunction.Types.ANONYMOUS, functionSource); + } + + /** + * Converts the function definition to JSON + */ + public JSONObject toJson() { + try { + JSONObject retval = new JSONObject(); + retval.put("language", "javascript"); + if (type == MapReduceFunction.Types.NAMED) { + retval.put("name", this.source); + } + else { + retval.put("source", this.source); + } + + return retval; + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a string"); + } + } + + private JavascriptFunction(MapReduceFunction.Types functionType, + String functionSource) { + this.type = functionType; + this.source = functionSource; + } + +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/LinkFunction.java b/src/main/java/com/basho/riak/client/http/mapreduce/LinkFunction.java new file mode 100644 index 000000000..cda4d59ec --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/LinkFunction.java @@ -0,0 +1,48 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce; + +import org.json.JSONException; +import org.json.JSONObject; + +public class LinkFunction implements MapReduceFunction { + + private String bucket = null; + private String tag = null; + + public LinkFunction(String bucket) { + this.bucket = bucket; + } + + public LinkFunction(String bucket, String tag) { + this.bucket = bucket; + this.tag = tag; + } + + public JSONObject toJson() { + try { + JSONObject link = new JSONObject(); + link.put("bucket", this.bucket); + + if (this.tag != null) { + link.put("tag", this.tag); + } + + return link; + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a string"); + } + } + +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/MapReduceFunction.java b/src/main/java/com/basho/riak/client/http/mapreduce/MapReduceFunction.java new file mode 100644 index 000000000..f9a1bfe46 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/MapReduceFunction.java @@ -0,0 +1,30 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce; + +import org.json.JSONObject; + +/** + * Interface for describing functions used in + * map/reduce jobs + */ +public interface MapReduceFunction { + + public static enum Types { + ANONYMOUS, + NAMED + } + + public JSONObject toJson(); +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/BetweenFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/BetweenFilter.java new file mode 100644 index 000000000..9901d091f --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/BetweenFilter.java @@ -0,0 +1,50 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class BetweenFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + JSONArray args = new JSONArray(); + + public BetweenFilter(String from, String to) { + args.put("between"); + args.put(from); + args.put(to); + } + + public BetweenFilter(int from, int to) { + args.put("between"); + args.put(from); + args.put(to); + } + + public BetweenFilter(long from, long to) { + args.put("between"); + args.put(from); + args.put(to); + } + + public BetweenFilter(double from, double to) throws JSONException { + args.put("between"); + args.put(from); + args.put(to); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/EndsWithFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/EndsWithFilter.java new file mode 100644 index 000000000..339865d39 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/EndsWithFilter.java @@ -0,0 +1,30 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class EndsWithFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public EndsWithFilter(String endsWith) { + args.put("ends_with"); + args.put(endsWith); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/EqualToFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/EqualToFilter.java new file mode 100644 index 000000000..e5fe5408b --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/EqualToFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class EqualToFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public EqualToFilter(String equalTo) { + args.put("eq"); + args.put(equalTo); + } + + public EqualToFilter(int equalTo) { + args.put("eq"); + args.put(equalTo); + } + + public EqualToFilter(double equalTo) throws JSONException { + args.put("eq"); + args.put(equalTo); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/FloatToStringFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/FloatToStringFilter.java new file mode 100644 index 000000000..8e09a0243 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/FloatToStringFilter.java @@ -0,0 +1,26 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class FloatToStringFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; + + public JSONArray toJson() { + JSONArray filter = new JSONArray(); + filter.put("float_to_string"); + return filter; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanFilter.java new file mode 100644 index 000000000..227fc07a6 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class GreaterThanFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public GreaterThanFilter(String greaterThan) { + args.put("greater_than"); + args.put(greaterThan); + } + + public GreaterThanFilter(int greaterThan) { + args.put("greater_than"); + args.put(greaterThan); + } + + public GreaterThanFilter(double greaterThan) throws JSONException { + args.put("greater_than"); + args.put(greaterThan); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanOrEqualFilter.java new file mode 100644 index 000000000..3570e388f --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/GreaterThanOrEqualFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class GreaterThanOrEqualFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public GreaterThanOrEqualFilter(String greaterThanOrEqualTo) { + args.put("greater_than_eq"); + args.put(greaterThanOrEqualTo); + } + + public GreaterThanOrEqualFilter(int greaterThanOrEqualTo) { + args.put("greater_than_eq"); + args.put(greaterThanOrEqualTo); + } + + public GreaterThanOrEqualFilter(double greaterThanOrEqualTo) throws JSONException { + args.put("greater_than_eq"); + args.put(greaterThanOrEqualTo); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/IntToStringFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/IntToStringFilter.java new file mode 100644 index 000000000..c21a0b6f7 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/IntToStringFilter.java @@ -0,0 +1,26 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class IntToStringFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; + + public JSONArray toJson() { + JSONArray filter = new JSONArray(); + filter.put("int_to_string"); + return filter; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanFilter.java new file mode 100644 index 000000000..f44983e8c --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class LessThanFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public LessThanFilter(String lessThan) { + args.put("less_than"); + args.put(lessThan); + } + + public LessThanFilter(int lessThan) { + args.put("less_than"); + args.put(lessThan); + } + + public LessThanFilter(double lessThan) throws JSONException { + args.put("less_than"); + args.put(lessThan); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanOrEqualFilter.java new file mode 100644 index 000000000..b49482a1e --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LessThanOrEqualFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class LessThanOrEqualFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public LessThanOrEqualFilter(String lessThanOrEqualTo) { + args.put("less_than_eq"); + args.put(lessThanOrEqualTo); + } + + public LessThanOrEqualFilter(int lessThanOrEqualTo) { + args.put("less_than_eq"); + args.put(lessThanOrEqualTo); + } + + public LessThanOrEqualFilter(double lessThanOrEqualTo) throws JSONException { + args.put("less_than_eq"); + args.put(lessThanOrEqualTo); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalAndFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalAndFilter.java new file mode 100644 index 000000000..63afcdd8e --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalAndFilter.java @@ -0,0 +1,37 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class LogicalAndFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; + private JSONArray args = new JSONArray(); + + public LogicalAndFilter(MapReduceFilter... filters) { + args.put("and"); + for(MapReduceFilter filter: filters) { + args.put(filter.toJson()); + } + } + + public LogicalAndFilter add(MapReduceFilter filter) { + args.put(filter.toJson()); + return this; + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalFilterGroup.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalFilterGroup.java new file mode 100644 index 000000000..13488c669 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalFilterGroup.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class LogicalFilterGroup implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; + private JSONArray filterArray = new JSONArray(); + + public LogicalFilterGroup(MapReduceFilter... filters) { + for(MapReduceFilter filter: filters) { + filterArray.put(filter.toJson()); + } + } + + public LogicalFilterGroup add(MapReduceFilter filter) { + filterArray.put(filter.toJson()); + return this; + } + + public JSONArray toJson() { + return filterArray; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalNotFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalNotFilter.java new file mode 100644 index 000000000..757061b57 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalNotFilter.java @@ -0,0 +1,37 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class LogicalNotFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; + private JSONArray args = new JSONArray(); + + public LogicalNotFilter(MapReduceFilter... filters) { + args.put("not"); + for(MapReduceFilter filter: filters) { + args.put(filter.toJson()); + } + } + + public LogicalNotFilter add(MapReduceFilter filter) { + args.put(filter.toJson()); + return this; + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalOrFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalOrFilter.java new file mode 100644 index 000000000..637f74015 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/LogicalOrFilter.java @@ -0,0 +1,37 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class LogicalOrFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; + private JSONArray args = new JSONArray(); + + public LogicalOrFilter(MapReduceFilter... filters) { + args.put("or"); + for(MapReduceFilter filter: filters) { + args.put(filter.toJson()); + } + } + + public LogicalOrFilter add(MapReduceFilter filter) { + args.put(filter.toJson()); + return this; + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/MapReduceFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/MapReduceFilter.java new file mode 100644 index 000000000..8d6a023e2 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/MapReduceFilter.java @@ -0,0 +1,31 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +/* + * Interface for filter functions used for + * key filtering + */ +public interface MapReduceFilter { + + public static enum Types { + LOGICAL, + TRANSFORM, + FILTER + } + + public JSONArray toJson(); +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/MatchFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/MatchFilter.java new file mode 100644 index 000000000..c0d6923a1 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/MatchFilter.java @@ -0,0 +1,30 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONArray; + +public class MatchFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public MatchFilter(String matchFilter) { + args.put("matches"); + args.put(matchFilter); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/NotEqualToFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/NotEqualToFilter.java new file mode 100644 index 000000000..ef27b203f --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/NotEqualToFilter.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import org.json.JSONException; +import org.json.JSONArray; + +public class NotEqualToFilter implements MapReduceFilter { + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public NotEqualToFilter(String notEqualToFilter) { + args.put("neq"); + args.put(notEqualToFilter); + } + + public NotEqualToFilter(int notEqualToFilter) { + args.put("neq"); + args.put(notEqualToFilter); + } + + public NotEqualToFilter(double notEqualToFilter) throws JSONException { + args.put("neq"); + args.put(notEqualToFilter); + } + + public JSONArray toJson() { + return args; + } +} diff --git a/src/main/java/com/basho/riak/client/http/mapreduce/filter/SetMemberFilter.java b/src/main/java/com/basho/riak/client/http/mapreduce/filter/SetMemberFilter.java new file mode 100644 index 000000000..49a29cc3f --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/mapreduce/filter/SetMemberFilter.java @@ -0,0 +1,57 @@ +/* + * This file is provided 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.basho.riak.client.http.mapreduce.filter; + +import java.util.List; + +import org.json.JSONException; +import org.json.JSONArray; + +public class SetMemberFilter implements MapReduceFilter { + private static final String NAME = "set_member"; + private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; + private JSONArray args = new JSONArray(); + + public SetMemberFilter(List setMembers) { + args.put("set_member"); + for(String setMember: setMembers) { + args.put(setMember); + } + } + + public SetMemberFilter(JSONArray setMembers) throws JSONException { + args.put("set_member"); + for(int i=0; i fetchAll(String bucket, String key, RequestMeta meta) + throws RiakIOException, RiakResponseException { + FetchResponse r = impl.fetch(bucket, key, meta); + + if (r.getStatusCode() == 404) + return null; + + if (r.getStatusCode() != 200 && r.getStatusCode() != 304) + throw new RiakResponseException(new RiakResponseRuntimeException(r, r.getBodyAsString())); + + if (r.getStatusCode() == 200 && !(r.hasObject() || r.hasSiblings())) + throw new RiakResponseException(new RiakResponseRuntimeException(r, "Failed to parse object")); + + if (r.hasSiblings()) + return r.getSiblings(); + return Arrays.asList(r.getObject()); + } + + public Collection fetchAll(String bucket, String key) throws RiakIOException, + RiakResponseException { + return fetchAll(bucket, key, null); + } + + /** + * Identical to + * {@link RiakClient#stream(String, String, StreamHandler, RequestMeta)}. + */ + public boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException { + return impl.stream(bucket, key, handler, meta); + } + + /** + * Like {@link RiakClient#delete(String, String, RequestMeta)}, except + * throws on a non-200 or 404 response. Note that delete succeeds if the + * object did not previously exist (404 response). + * + * @throws RiakIOException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseException + * If the object was not deleted. + */ + public void delete(String bucket, String key, RequestMeta meta) throws RiakIOException, RiakResponseException { + HttpResponse r = impl.delete(bucket, key, meta); + + if (r.getStatusCode() != 204 && r.getStatusCode() != 404) + throw new RiakResponseException(new RiakResponseRuntimeException(r, r.getBodyAsString())); + } + + public void delete(String bucket, String key) throws RiakIOException, RiakResponseException { + delete(bucket, key, null); + } + + /** + * Like {@link RiakClient#walk(String, String, String, RequestMeta)}, except + * throws on a non-200 or 404 response. + * + * @return list of lists of {@link RiakObject}s corresponding to steps of + * the walk. Returns null if the source object doesn't exist. + * @throws RiakIOException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseException + * If the links could not be walked or the result steps were not + * returned. + */ + public List> walk(String bucket, String key, String walkSpec, RequestMeta meta) + throws RiakIOException, RiakResponseException { + WalkResponse r = impl.walk(bucket, key, walkSpec, meta); + + if (r.getStatusCode() == 404) + return null; + + if (r.getStatusCode() != 200) + throw new RiakResponseException(new RiakResponseRuntimeException(r, r.getBodyAsString())); + + if (!r.hasSteps()) + throw new RiakResponseException(new RiakResponseRuntimeException(r, "Failed to parse walk results")); + + return r.getSteps(); + } + + public List> walk(String bucket, String key, String walkSpec) + throws RiakIOException, RiakResponseException { + return walk(bucket, key, walkSpec, null); + } + + public List> walk(String bucket, String key, RiakWalkSpec walkSpec) + throws RiakIOException, RiakResponseException { + return walk(bucket, key, walkSpec.toString(), null); + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/plain/RiakIOException.java b/src/main/java/com/basho/riak/client/http/plain/RiakIOException.java new file mode 100644 index 000000000..4da083276 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/plain/RiakIOException.java @@ -0,0 +1,27 @@ +/* + * This file is provided 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.basho.riak.client.http.plain; + +import com.basho.riak.client.http.response.RiakIORuntimeException; + +/** + * A checked wrapper for {@link RiakIORuntimeException}. + */ +public class RiakIOException extends Exception { + private static final long serialVersionUID = 2179229841757644538L; + + public RiakIOException(RiakIORuntimeException e) { + super(e.getMessage(), e.getCause()); + } +} diff --git a/src/main/java/com/basho/riak/client/http/plain/RiakResponseException.java b/src/main/java/com/basho/riak/client/http/plain/RiakResponseException.java new file mode 100644 index 000000000..707880684 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/plain/RiakResponseException.java @@ -0,0 +1,84 @@ +/* + * This file is provided 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.basho.riak.client.http.plain; + +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; + +/** + * A checked decorator for {@link RiakResponseRuntimeException} + */ +public class RiakResponseException extends Exception implements HttpResponse { + + private static final long serialVersionUID = 5932513075276473483L; + private RiakResponseRuntimeException impl; + + public RiakResponseException(RiakResponseRuntimeException e) { + super(e.getMessage(), e.getCause()); + impl = e; + } + + public byte[] getBody() { + return impl.getBody(); + } + + public String getBodyAsString() { + return impl.getBodyAsString(); + } + + public InputStream getStream() { + return impl.getStream(); + } + + public boolean isStreamed() { + return impl.isStreamed(); + } + + public String getBucket() { + return impl.getBucket(); + } + + public Map getHttpHeaders() { + return impl.getHttpHeaders(); + } + + public HttpMethod getHttpMethod() { + return impl.getHttpMethod(); + } + + public String getKey() { + return impl.getKey(); + } + + public int getStatusCode() { + return impl.getStatusCode(); + } + + public boolean isError() { + return impl.isError(); + } + + public boolean isSuccess() { + return impl.isSuccess(); + } + + public void close() { + impl.close(); + } +} diff --git a/src/main/java/com/basho/riak/client/http/request/MapReduceBuilder.java b/src/main/java/com/basho/riak/client/http/request/MapReduceBuilder.java new file mode 100644 index 000000000..8e2f6275e --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/request/MapReduceBuilder.java @@ -0,0 +1,475 @@ +/* + * This file is provided 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.basho.riak.client.http.request; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.mapreduce.LinkFunction; +import com.basho.riak.client.http.mapreduce.MapReduceFunction; +import com.basho.riak.client.http.mapreduce.filter.MapReduceFilter; +import com.basho.riak.client.http.response.MapReduceResponse; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; + +/** + * Builds a map/reduce job description and submits it Uses the same chained + * method metaphor as StringBuilder or StringBuffer + */ +public class MapReduceBuilder { + + private static enum Types { + MAP, REDUCE, LINK + } + + private String bucket = null; + private Map> objects = new LinkedHashMap>(); + private List keyFilters = new ArrayList(); + private List phases = new LinkedList(); + private int timeout = -1; + private RiakClient riak = null; + + /** + * @param riak + * RiakClient instance which is pointing to the map/reduce URL + */ + public MapReduceBuilder(RiakClient riak) { + this.riak = riak; + } + + public MapReduceBuilder() { /* nop */ } + + /** + * The {@link RiakClient} to which this map reduce job will be submitted to + * when {@link MapReduceBuilder#submit()} is called. + */ + public RiakClient getRiakClient() { + return riak; + } + + public MapReduceBuilder setRiakClient(RiakClient client) { + riak = client; + return this; + } + + /** + * Gets the name of the Riak bucket the map/reduce job will process + */ + public String getBucket() { + return bucket; + } + + /** + * Sets the name of the Riak bucket the map/reduce job will process + * + * @throws IllegalStateException + * - If objects have already been added to the job + */ + public MapReduceBuilder setBucket(String newBucket) { + if (objects.size() > 0) + throw new IllegalStateException("Cannot map/reduce over buckets and objects"); + bucket = newBucket; + return this; + } + + /** + * Adds a Riak object (bucket name/key pair) to the map/reduce job as inputs + * + * @throws IllegalStateException + * - If a bucket name has already been set on the job + */ + public void addRiakObject(String bucket, String key) { + if (this.bucket != null) + throw new IllegalStateException("Cannot map/reduce over buckets and objects"); + Set keys = objects.get(bucket); + if (keys == null) { + keys = new LinkedHashSet(); + objects.put(bucket, keys); + } + keys.add(key); + } + + /** + * Removes a Riak object (bucket name/key pair) for the job's input list + */ + public void removeRiakObject(String bucket, String key) { + Set keys = objects.get(bucket); + if (keys != null) { + keys.remove(key); + if (keys.size() == 0) { + objects.remove(bucket); + } + } + } + + /** + * Returns a copy of the Riak objects on the input list for a map/reduce job + */ + public Map> getRiakObjects() { + return new HashMap>(objects); + } + + /** + * Sets a collection of Riak object (bucket name/key pair) as the map/reduce + * job as inputs + * + * @throws IllegalStateException + * - If a bucket name has already been set on the job + */ + public MapReduceBuilder setRiakObjects(Map> objects) { + if (bucket != null) + throw new IllegalStateException("Cannot map/reduce over buckets and objects"); + + if (objects == null) { + clearRiakObjects(); + } else { + this.objects = new HashMap>(objects); + } + + return this; + } + + public MapReduceBuilder setRiakObjects(Collection objects) { + if (bucket != null) + throw new IllegalStateException("Cannot map/reduce over buckets and objects"); + + clearRiakObjects(); + if (objects != null) { + for (RiakObject o : objects) { + addRiakObject(o.getBucket(), o.getKey()); + } + } + + return this; + } + + /** + * Remove all Riak objects from the input list + */ + public void clearRiakObjects() { + objects.clear(); + } + + /** + * How long the map/reduce job is allowed to execute Time is in milliseconds + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + /** + * Gets the currently assigned timeout + */ + public int getTimeout() { + return timeout; + } + + /** + * Adds a map phase to the job + * + * @param function + * function to run for the phase + * + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder keyFilter(MapReduceFilter... filters) { + for(MapReduceFilter filter: filters) { + this.keyFilters.add(filter); + } + return this; + } + + /** + * Adds a map phase to the job + * + * @param function + * function to run for the phase + * + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder map(MapReduceFunction function, boolean keep) { + return this.map(function, null, keep); + } + + + /** + * Adds a map phase to the job + * + * @param function + * function to run for the phase + * + * @param arg + * Static argument to pass to the function. Should be an + * object easily converted to JSON + * + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder map(MapReduceFunction function, Object arg, boolean keep) { + this.addPhase(MapReduceBuilder.Types.MAP, function, arg, keep); + return this; + } + + /** + * Adds a reduce phase to the job + * + * @param function + * function to run for the phase + * + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder reduce(MapReduceFunction function, boolean keep) { + return this.reduce(function, null, keep); + } + + + /** + * Adds a reduce phase to the job + * + * @param function + * function to run for the phase + * + * @param arg + * Static argument to pass to the function. Should be an + * object easily converted to JSON + * + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder reduce(MapReduceFunction function, Object arg, boolean keep) { + this.addPhase(MapReduceBuilder.Types.REDUCE, function, arg, keep); + return this; + } + + /** + * Adds a link phase to the job + * + * @param bucket + * bucket to link walk + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + * + * Pointing at a bucket without specifying a link tag will follow + * all links pointing to objects in the bucket + */ + public MapReduceBuilder link(String bucket, boolean keep) { + this.addPhase(MapReduceBuilder.Types.LINK, new LinkFunction(bucket), keep); + return this; + } + + /** + * Adds a link phase to the job + * + * @param bucket + * bucket to link walk + * @param tag + * link tag to match + * @param keep + * should the server keep and return the results + * @return current MapReduceBuilder instance. This is done so multiple calls + * to map, reduce, and link can be chained together a la + * StringBuffer + */ + public MapReduceBuilder link(String bucket, String tag, boolean keep) { + this.addPhase(MapReduceBuilder.Types.LINK, new LinkFunction(bucket, tag), keep); + return this; + } + + /** + * Submits the job to the Riak server + * + * @param meta + * Extra metadata to attach to the request such as HTTP headers + * or query parameters. + * + * @return {@link MapReduceResponse} containing job results + * + * @throws IllegalStateException + * If this job has not been associated with a Riak instance by + * calling {@link MapReduceBuilder#setRiakClient(RiakClient)} + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + * @throws RiakResponseRuntimeException + * If the Riak server returns a malformed response. + */ + public MapReduceResponse submit(RequestMeta meta) { + if (riak == null) + throw new IllegalStateException("Cannot perform map reduce without a RiakClient"); + return riak.mapReduce(toJSON().toString(), meta); + } + + public MapReduceResponse submit() throws JSONException { + return submit(null); + } + + /** + * Builds the JSON representation of a map/reduce job + */ + public JSONObject toJSON() { + JSONObject job = new JSONObject(); + JSONArray query = new JSONArray(); + + for (MapReducePhase phase : phases) { + renderPhase(phase, query); + } + buildInputs(job); + try { + job.put("query", query); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a valid JSONArray"); + } + if (timeout > 0) { + try { + job.put("timeout", timeout); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to an int"); + } + } + return job; + } + + private MapReduceBuilder addPhase(Types phaseType, MapReduceFunction function, boolean keep) { + return addPhase(phaseType, function, null, keep); + } + + private MapReduceBuilder addPhase(Types phaseType, MapReduceFunction function, Object arg, boolean keep) { + MapReducePhase phase = new MapReducePhase(); + phase.type = phaseType; + phase.function = function; + phase.arg = arg; + phase.keep = keep; + phases.add(phase); + return this; + } + + private JSONArray buildFilters(List filterList) { + JSONArray filters = new JSONArray(); + for(MapReduceFilter filter: filterList) { + filters.put(filter.toJson()); + } + return filters; + } + + private void buildInputs(JSONObject job) { + if (bucket != null) { + if (keyFilters.size() > 0) { + try { + JSONObject jobInputs = new JSONObject(); + jobInputs.put("bucket", bucket); + jobInputs.put("key_filters", buildFilters(this.keyFilters)); + job.put("inputs", jobInputs); + } catch (JSONException e) { + throw new RuntimeException("Can always map a collection of MapReduceFilter objects to a JSONArray"); + } + } else { + try { + job.put("inputs", bucket); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a string"); + } + } + } else { + JSONArray inputs = new JSONArray(); + for (String bucket : objects.keySet()) { + Set keys = objects.get(bucket); + for (String key : keys) { + String[] pair = { bucket, key }; + inputs.put(pair); + } + } + try { + job.put("inputs", inputs); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a valid JSONArray"); + } + } + } + + private void renderPhase(MapReducePhase phase, JSONArray query) { + JSONObject phaseJson = new JSONObject(); + JSONObject functionJson = phase.function.toJson(); + try { + functionJson.put("keep", phase.keep); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a boolean"); + } + try { + if (phase.arg != null) { + functionJson.put("arg", phase.arg); + } + } catch (JSONException e) { + throw new RuntimeException("Cannot convert phase arg to JSON"); + } + String type = null; + switch (phase.type) { + case MAP: + type = "map"; + break; + case REDUCE: + type = "reduce"; + break; + case LINK: + type = "link"; + break; + } + try { + phaseJson.put(type, functionJson); + } catch (JSONException e) { + throw new RuntimeException("Can always map a string to a valid JSONObject"); + } + query.put(phaseJson); + } + + private class MapReducePhase { + Types type; + MapReduceFunction function; + Object arg; + boolean keep; + } + +} diff --git a/src/main/java/com/basho/riak/client/http/request/RequestMeta.java b/src/main/java/com/basho/riak/client/http/request/RequestMeta.java new file mode 100644 index 000000000..b00203757 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/request/RequestMeta.java @@ -0,0 +1,240 @@ +/* + * This file is provided 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.basho.riak.client.http.request; + +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.httpclient.util.DateUtil; + +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; + +/** + * Extra headers and query parameters to send with a Riak operation. + */ +public class RequestMeta { + + private Map queryParams = new LinkedHashMap(); + private Map headers = new HashMap(); + + /** + * Use the given r parameter for fetchMeta, fetch, or stream operations + * + * @param r + * r- parameter for fetchMeta, fetch, or stream: the number of + * successful read response required for a successful overall + * response + * @return A {@link RequestMeta} object with the appropriate query + * parameters + */ + public static RequestMeta readParams(int r) { + RequestMeta meta = new RequestMeta(); + meta.setQueryParam(Constants.QP_R, Integer.toString(r)); + return meta; + } + + /** + * Use the given w and dw params for store or delete operations. + * + * @param w + * w- parameter for store and delete: the number of successful + * write responses required for a successful store operation + * @param dw + * dw- parameter for store and delete: The number of successful + * durable write responses required for a successful store + * operation + * @return A {@link RequestMeta} object with the appropriate query + * parameters + */ + public static RequestMeta writeParams(Integer w, Integer dw) { + RequestMeta meta = new RequestMeta(); + if (w != null) { + meta.setQueryParam(Constants.QP_W, Integer.toString(w)); + } + if (dw != null) { + meta.setQueryParam(Constants.QP_DW, Integer.toString(dw)); + } + return meta; + } + + /** + * Use the given rw parameter for delete operations + * + * @param rw + * rw- parameter for delete: the number of + * successful read/write response required for a successful overall + * response + * @return A {@link RequestMeta} object with the appropriate query + * parameters + */ + public static RequestMeta deleteParams(int rw) { + RequestMeta meta = new RequestMeta(); + meta.setQueryParam(Constants.QP_RW, Integer.toString(rw)); + return meta; + } + + /** + * Add the specified HTTP header + * + * @param key + * header name + * @param value + * header value + */ + public RequestMeta setHeader(String key, String value) { + headers.put(key, value); + return this; + } + + /** + * Return the value for the HTTP header or null if not set + * + * @param key + * header name + * @return value of header or null if not set + */ + public String getHeader(String key) { + return headers.get(key); + } + + /** + * Whether the HTTP header has been set + * + * @param key + * header name + */ + public boolean hasHeader(String key) { + return headers.containsKey(key); + } + + /** + * Map of HTTP header names to values + */ + public Map getHeaders() { + return headers; + } + + /** + * Query parameter value or null if not set + * + * @param param + * query parameter name + */ + public String getQueryParam(String param) { + return queryParams.get(param); + } + + /** + * Add the given query parameter to the request + * + * @param param + * query parameter name + * @param value + * query parameter value + */ + public RequestMeta setQueryParam(String param, String value) { + queryParams.put(param, value); + return this; + } + + /** + * A string containing all the specified query parameters in this + * {@link RequestMeta} in the form: p1=v1&p2=v2 + */ + public String getQueryParams() { + StringBuilder qp = new StringBuilder(); + for (String param : queryParams.keySet()) { + if (queryParams.get(param) != null) { + if (qp.length() > 0) { + qp.append("&"); + } + qp.append(param).append("=").append(queryParams.get(param)); + } + } + return qp.toString(); + } + + /** Convenience method for the X-Riak-ClientId HTTP header */ + public String getClientId() { + return getHeader(Constants.HDR_CLIENT_ID); + } + + public RequestMeta setClientId(String clientId) { + return setHeader(Constants.HDR_CLIENT_ID, clientId); + } + + /** Convenience method for the If-Modified-Since HTTP header */ + public String getIfModifiedSince() { + return getHeader(Constants.HDR_IF_MODIFIED_SINCE); + } + + public RequestMeta setIfModifiedSince(String lastmod) { + return setHeader(Constants.HDR_IF_MODIFIED_SINCE, lastmod); + } + + public RequestMeta setIfModifiedSince(Date lastmod) { + return setHeader(Constants.HDR_IF_MODIFIED_SINCE, DateUtil.formatDate(lastmod)); + } + + /** Convenience method for the If-Unmodified-Since HTTP header */ + public String getIfUnmodifiedSince() { + return getHeader(Constants.HDR_IF_UNMODIFIED_SINCE); + } + + public RequestMeta setIfUnmodifiedSince(String lastmod) { + return setHeader(Constants.HDR_IF_UNMODIFIED_SINCE, lastmod); + } + + public RequestMeta setIfUnmodifiedSince(Date lastmod) { + return setHeader(Constants.HDR_IF_UNMODIFIED_SINCE, DateUtil.formatDate(lastmod)); + } + + /** Convenience method for the If-Match HTTP header */ + public String getIfMatch() { + return getHeader(Constants.HDR_IF_MATCH); + } + + public RequestMeta setIfMatch(String etags) { + return setHeader(Constants.HDR_IF_MATCH, etags); + } + + public RequestMeta setIfMatch(String[] etags) { + return setHeader(Constants.HDR_IF_MATCH, ClientUtils.join(etags, ",")); + } + + /** Convenience method for the If-None-Match HTTP header */ + public String getIfNoneMatch() { + return getHeader(Constants.HDR_IF_NONE_MATCH); + } + + public RequestMeta setIfNoneMatch(String etags) { + return setHeader(Constants.HDR_IF_NONE_MATCH, etags); + } + + public RequestMeta setIfNoneMatch(String[] etags) { + return setHeader(Constants.HDR_IF_NONE_MATCH, ClientUtils.join(etags, ",")); + } + + /** Convenience method for the Accept HTTP header */ + public String getAccept() { + return getHeader(Constants.HDR_ACCEPT); + } + + public RequestMeta setAccept(String contentTypes) { + return setHeader(Constants.HDR_ACCEPT, contentTypes); + } +} diff --git a/src/main/java/com/basho/riak/client/http/request/RiakWalkSpec.java b/src/main/java/com/basho/riak/client/http/request/RiakWalkSpec.java new file mode 100644 index 000000000..1eea70095 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/request/RiakWalkSpec.java @@ -0,0 +1,112 @@ +/* + * This file is provided 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.basho.riak.client.http.request; + +import java.util.ArrayList; + +import com.basho.riak.client.http.util.ClientUtils; + +/** + * Taken from Jiak client in Riak source 12/1/09. + * + * RiakWalkSpecStep is the internal representation of a RiakWalkSpec segment. It + * should not be used directly. + */ +class RiakWalkSpecStep { + public final String bucket; + public final String tag; + public final String accumulateFlag; + + public RiakWalkSpecStep(final String b, final String t, final String a) { + bucket = b; + tag = t; + accumulateFlag = a; + } +} + +/** + * Tool for building Riak/Jaywalker specs. Using this class to specify walk + * specs ensures that bucket and tag names will be properly URL-escaped. + * + * @author Bryan Fink + * @version 0.1 + */ +public class RiakWalkSpec extends ArrayList { + + private static final long serialVersionUID = 7896627605420162292L; + + /** + * The "don't care" signifier. Pass this as the bucket, tag, or accumulate + * flag to select the default, or match-all option. + */ + public static final String WILDCARD = "_"; + + /** + * Create an empty Riak walk spec. + */ + public RiakWalkSpec() { + super(); + } + + /** + * Append a step to this walk spec. + * + * @param bucket + * The bucket of the step, or the wildcard. + * @param tag + * The tag of the step, or the wildcard. + * @param accumulateFlag + * The string "1" to force this step to be accumulated in the + * results. "0" to force this step not to be accumulated. + * WILDCARD to accept the default accumulation setting ("yes" for + * the last step, "no" for all others). + */ + public void addStep(final String bucket, final String tag, final String accumulateFlag) { + this.add(new RiakWalkSpecStep(bucket, tag, accumulateFlag)); + } + + /** + * Append a step to this walk spec. Same as the other addStep function, but + * allows the use of a boolean instead of a string for the accumulateFlag + * parameter. + */ + public void addStep(final String bucket, final String tag, boolean accumulateFlag) { + addStep(bucket, tag, accumulateFlag ? "1" : "0"); + } + + /** + * Append a step to this walk spec, and take the default option for the + * accumulate flag. + */ + public void addStep(final String bucket, final String tag) { + addStep(bucket, tag, WILDCARD); + } + + /** + * Convert this walk step to a string. All bucket and tag names will be + * URL-escaped in the return value. + */ + @Override public String toString() { + StringBuilder result = new StringBuilder(); + for (RiakWalkSpecStep s : this) { + result.append(ClientUtils.urlEncode(s.bucket)); + result.append(','); + result.append(ClientUtils.urlEncode(s.tag)); + result.append(','); + result.append(s.accumulateFlag); + result.append('/'); + } + return result.toString(); + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/BucketResponse.java b/src/main/java/com/basho/riak/client/http/response/BucketResponse.java new file mode 100644 index 000000000..324a00598 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/BucketResponse.java @@ -0,0 +1,88 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Collection; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; + +/** + * Response from a GET request at a bucket's URL. Decorates an HttpResponse to + * interpret listBucket response from Riak, which is a JSON object with the keys + * "props" and "keys". + */ +public class BucketResponse extends HttpResponseDecorator implements HttpResponse { + + private RiakBucketInfo bucketInfo = null; + + /** + * On a 2xx response, parses the JSON response into a {@link RiakBucketInfo} + * + * @param r + * The HTTP response from a GET at a bucket + * @throws JSONException + * If the response is a 2xx but contains invalid JSON + * @throws IOException + * If a communication error with the Riak server while trying to + * read the streamed response + */ + public BucketResponse(HttpResponse r) throws JSONException, IOException { + super(r); + + if (r != null && r.isSuccess()) { + JSONObject props; + Collection keys; + if (!r.isStreamed()) { + JSONObject json = new JSONObject(r.getBodyAsString()); + JSONArray jsonKeys = json.optJSONArray(Constants.FL_KEYS); + props = json.optJSONObject(Constants.FL_SCHEMA); + keys = ClientUtils.jsonArrayAsList(jsonKeys); + } else { + InputStream stream = r.getStream(); + JSONTokener tokens = new JSONTokener(new InputStreamReader(stream)); + + // suck in the first object from the stream, which is the schema + // and give the rest to the streamed keys collection + props = new JSONObject(tokens).optJSONObject(Constants.FL_SCHEMA); + keys = new StreamedKeysCollection(tokens); + } + bucketInfo = new RiakBucketInfo(props, keys); + } + } + + /** + * Whether the bucket's schema and keys were returned in the response from + * Riak + */ + public boolean hasBucketInfo() { + return bucketInfo != null; + } + + /** + * The bucket's schema and keys + */ + public RiakBucketInfo getBucketInfo() { + return bucketInfo; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java b/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java new file mode 100644 index 000000000..a89b7e81c --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java @@ -0,0 +1,124 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +import com.basho.riak.client.http.util.Constants; + +/** + * Simple implementation of HttpResponse interface. Simply stores and returns + * the various fields. + */ +public class DefaultHttpResponse implements HttpResponse { + + private String bucket; + private String key; + private int status = -1; + private Map headers = null; + private byte[] body = null; + private InputStream stream = null; + private HttpMethod httpMethod = null; + + public DefaultHttpResponse(String bucket, String key, int status, Map headers, byte[] body, + InputStream stream, HttpMethod httpMethod) { + if (headers == null) { + headers = new HashMap(); + } + + this.bucket = bucket; + this.key = key; + this.status = status; + this.headers = headers; + if(body != null) { + this.body = body.clone(); + } + this.stream = stream; + this.httpMethod = httpMethod; + } + + public String getBucket() { + return bucket; + } + + public String getKey() { + return key; + } + + public int getStatusCode() { + return status; + } + + public Map getHttpHeaders() { + return headers; + } + + public byte[] getBody() { + if (body != null) { + return body.clone(); + } + return null; + } + + public String getBodyAsString() { + if (body == null) { + return null; + } + return new String(body); + } + + public InputStream getStream() { + return stream; + } + + public boolean isStreamed() { + return stream != null; + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public boolean isSuccess() { + String method = null; + if (httpMethod != null) { + method = httpMethod.getName(); + } + + return (status >= 200 && status < 300) || + ((status == 300 || status == 304) && Constants.HTTP_HEAD_METHOD.equals(method)) || + ((status == 300 || status == 304) && Constants.HTTP_GET_METHOD.equals(method)) || + ((status == 300) && Constants.HTTP_PUT_METHOD.equals(method)) || + ((status == 404) && Constants.HTTP_DELETE_METHOD.equals(method)); + } + + public boolean isError() { + String method = null; + if (httpMethod != null) { + method = httpMethod.getName(); + } + + return (status < 100 || status >= 400) && !((status == 404) && Constants.HTTP_DELETE_METHOD.equals(method)); + } + + public void close() { + if (httpMethod != null) { + httpMethod.releaseConnection(); + } + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/FetchResponse.java b/src/main/java/com/basho/riak/client/http/response/FetchResponse.java new file mode 100644 index 000000000..07faf677d --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/FetchResponse.java @@ -0,0 +1,142 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.http.util.StreamedMultipart; + +/** + * Response from a HEAD or GET request for an object. Decorates an HttpResponse + * to interpret fetch and fetchMeta responses from Riak's HTTP interface which + * returns object metadata in HTTP headers and value in the body. + */ +public class FetchResponse extends HttpResponseDecorator implements WithBodyResponse { + + private RiakObject object = null; + private Collection siblings = new ArrayList(); + + /** + * On a 2xx response, parse the HTTP response from Riak into a + * {@link RiakObject}. On a 300 response, parse the multipart/mixed HTTP + * body into a collection of sibling {@link RiakObject}s. + * + * A streaming response (i.e. r.isStreaming() == true), will have a null + * body and non-null stream. The resulting {@link RiakObject}(s) will return + * null for getValue() and the stream for getValueStream(). Users must + * remember to release the return value's underlying stream by calling + * close(). + * + * Sibling objects are also streamed. The values of the objects are buffered + * in memory as the stream is read. Consume and/or close each + * {@link RiakObject}'s stream as the collection is iterated to allow the + * buffers to be freed. + * + * @throws RiakResponseRuntimeException + * If the server returns a 300 without a proper multipart/mixed + * body + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + public FetchResponse(HttpResponse r, RiakClient riak) throws RiakResponseRuntimeException, RiakIORuntimeException { + super(r); + + if (r == null) + return; + + Map headers = r.getHttpHeaders(); + List links = ClientUtils.parseLinkHeader(headers.get(Constants.HDR_LINK)); + Map usermeta = ClientUtils.parseUsermeta(headers); + + if (r.getStatusCode() == 300) { + String contentType = headers.get(Constants.HDR_CONTENT_TYPE); + + if (contentType == null || !(contentType.trim().toLowerCase().startsWith(Constants.CTYPE_MULTIPART_MIXED))) { + throw new RiakResponseRuntimeException(r, "multipart/mixed content expected when object has siblings"); + } + + if (r.isStreamed()) { + try { + StreamedMultipart multipart = new StreamedMultipart(headers, r.getStream()); + siblings = new StreamedSiblingsCollection(riak, r.getBucket(), r.getKey(), multipart); + } catch (IOException e) { + throw new RiakIORuntimeException("Error finding initial boundary", e); + } + } else { + siblings = ClientUtils.parseMultipart(riak, r.getBucket(), r.getKey(), headers, r.getBody()); + } + + object = siblings.iterator().next(); + } else if (r.isSuccess()) { + object = new RiakObject(riak, r.getBucket(), r.getKey(), r.getBody(), + headers.get(Constants.HDR_CONTENT_TYPE), links, usermeta, + headers.get(Constants.HDR_VCLOCK), headers.get(Constants.HDR_LAST_MODIFIED), + headers.get(Constants.HDR_ETAG)); + + Long contentLength = null; + try { + contentLength = Long.parseLong(headers + .get(Constants.HDR_CONTENT_LENGTH)); + } catch (NumberFormatException ignored) {} + + object.setValueStream(r.getStream(), contentLength); + } + } + + public FetchResponse(HttpResponse r) throws RiakResponseRuntimeException { + this(r, null); + } + + /** + * Whether response contained a Riak object + */ + public boolean hasObject() { + return getObject() != null; + } + + /** + * Returns the first Riak object contained in the response. Equivalent to + * the first object in getSiblings() when hasSiblings() is true. + */ + public RiakObject getObject() { + return object; + } + + public void setObject(RiakObject object) { + this.object = object; + } + + /** + * Whether response contained a multiple Riak objects + */ + public boolean hasSiblings() { + return getSiblings().size() > 0; + } + + /** + * Returns a collection of the Riak objects contained in the response. + */ + public Collection getSiblings() { + return siblings; + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/HttpResponse.java b/src/main/java/com/basho/riak/client/http/response/HttpResponse.java new file mode 100644 index 000000000..5c136732a --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/HttpResponse.java @@ -0,0 +1,87 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +/** + * HTTP response information resulting from some HTTP operation + */ +public interface HttpResponse { + + /** + * The target object's bucket + */ + public String getBucket(); + + /** + * The target object's key or null if bucket is target + */ + public String getKey(); + + /** + * Resulting status code from the HTTP request. + */ + public int getStatusCode(); + + /** + * The HTTP response headers. + */ + public Map getHttpHeaders(); + + /** + * The HTTP response body or null if isStreamed() + */ + public byte[] getBody(); + + public String getBodyAsString(); + + /** + * The HTTP response body as an input stream if isStreamed(); null otherwise + */ + public InputStream getStream(); + + /** + * Whether the response body is available as an input stream + */ + public boolean isStreamed(); + + /** + * The actual {@link HttpMethod} used to make the HTTP request. Most of the + * data here can be retrieved more simply using methods in this class. Also, + * note that the connection will already be closed, so calling + * getHttpMethod().getResponseBodyAsStream() will return null. + */ + public HttpMethod getHttpMethod(); + + /** + * Whether the HTTP response is considered a success. Generally this + * translates to a 2xx for any request, a 304 for GET and HEAD requests, or + * 404 for DELETE requests. + */ + public boolean isSuccess(); + + /** + * Whether the HTTP request returned a 4xx or 5xx response + */ + public boolean isError(); + + /** + * Releases the underlying the HTTP connection when the response is streamed + */ + public void close(); +} diff --git a/src/main/java/com/basho/riak/client/http/response/HttpResponseDecorator.java b/src/main/java/com/basho/riak/client/http/response/HttpResponseDecorator.java new file mode 100644 index 000000000..0d4964351 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/HttpResponseDecorator.java @@ -0,0 +1,104 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +/** + * A default decorator implementation for HttpResponse + */ +public class HttpResponseDecorator implements HttpResponse { + + protected HttpResponse impl = null; + + public HttpResponseDecorator(HttpResponse r) { + impl = r; + } + + public String getBucket() { + if (impl == null) + return null; + return impl.getBucket(); + } + + public String getKey() { + if (impl == null) + return null; + return impl.getKey(); + } + + public byte[] getBody() { + if (impl == null) + return null; + return impl.getBody(); + } + + public String getBodyAsString() { + if (impl == null) + return null; + return impl.getBodyAsString(); + } + + public InputStream getStream() { + if (impl == null) + return null; + return impl.getStream(); + } + + public boolean isStreamed() { + if (impl == null) + return false; + return impl.isStreamed(); + } + + public Map getHttpHeaders() { + if (impl == null) + return new HashMap(); + return impl.getHttpHeaders(); + } + + public HttpMethod getHttpMethod() { + if (impl == null) + return null; + return impl.getHttpMethod(); + } + + public int getStatusCode() { + if (impl == null) + return -1; + return impl.getStatusCode(); + } + + public boolean isError() { + if (impl == null) + return true; + return impl.isError(); + } + + public boolean isSuccess() { + if (impl == null) + return false; + return impl.isSuccess(); + } + + public void close() { + if (impl != null) { + impl.close(); + } + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/MapReduceResponse.java b/src/main/java/com/basho/riak/client/http/response/MapReduceResponse.java new file mode 100644 index 000000000..59360d54a --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/MapReduceResponse.java @@ -0,0 +1,49 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import org.json.JSONArray; +import org.json.JSONException; + +/** + * Response from a map-reduce query (POST to /mapred). Decorates an HttpResponse + * and parses returned JSON array returned from Riak. + */ +public class MapReduceResponse extends HttpResponseDecorator implements HttpResponse { + + JSONArray result = null; + + /** + * On a 2xx response, parses the response into a {@link JSONArray} + * + * @param r + * The HTTP response query POST'd to the map-reduce resource + * @throws JSONException + * Response is a 2xx but doesn't contain a valid JSON array + */ + public MapReduceResponse(HttpResponse r) throws JSONException { + super(r); + + if (r != null && r.isSuccess() && (r.getBody() != null)) { + result = new JSONArray(r.getBodyAsString()); + } + } + + /** + * The result of the map-reduce query as a JSON array + */ + public JSONArray getResults() { + return result; + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/RiakExceptionHandler.java b/src/main/java/com/basho/riak/client/http/response/RiakExceptionHandler.java new file mode 100644 index 000000000..9d566dc0b --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/RiakExceptionHandler.java @@ -0,0 +1,33 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +/** + * Allows clients to handle exceptions in a separate class rather than inline + * with the requests. If an RiakExceptionHandler is installed (use the client's + * setExceptionHandler() method), then exceptions RiakIOExceptions and + * RiakResponseExceptions will be passed to the handler rather than being + * thrown. If exceptions can be handled centrally by the caller, using an + * exception handler can result in cleaner code by avoiding repeated try/catch + * blocks for every operation. + */ +public interface RiakExceptionHandler { + + /** Handle exceptions caused by communication errors with the sever */ + public void handle(RiakIORuntimeException e); + + /** Handle exceptions caused by malformed responses from the sever */ + public void handle(RiakResponseRuntimeException e); + +} diff --git a/src/main/java/com/basho/riak/client/http/response/RiakIORuntimeException.java b/src/main/java/com/basho/riak/client/http/response/RiakIORuntimeException.java new file mode 100644 index 000000000..e964eb510 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/RiakIORuntimeException.java @@ -0,0 +1,41 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.IOException; + +/** + * Thrown when an error occurs during communication with the Riak server. + */ +public class RiakIORuntimeException extends RuntimeException { + + private static final long serialVersionUID = -3451479917953961929L; + + public RiakIORuntimeException() { + super(); + } + + public RiakIORuntimeException(String message, IOException cause) { + super(message, cause); + } + + public RiakIORuntimeException(String message) { + super(message); + } + + public RiakIORuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/basho/riak/client/http/response/RiakResponseRuntimeException.java b/src/main/java/com/basho/riak/client/http/response/RiakResponseRuntimeException.java new file mode 100644 index 000000000..40b35b652 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/RiakResponseRuntimeException.java @@ -0,0 +1,116 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +/** + * Thrown when the Riak server returns a malformed response. The HTTP response + * is returned in the exception. + */ +public class RiakResponseRuntimeException extends RuntimeException implements HttpResponse { + + private static final long serialVersionUID = 2853253336513247178L; + private HttpResponse response = null; + + public RiakResponseRuntimeException(HttpResponse response) { + super(); + this.response = response; + } + + public RiakResponseRuntimeException(HttpResponse response, String message, Throwable cause) { + super(message, cause); + this.response = response; + } + + public RiakResponseRuntimeException(HttpResponse response, String message) { + super(message); + this.response = response; + } + + public RiakResponseRuntimeException(HttpResponse response, Throwable cause) { + super(cause); + this.response = response; + } + + public byte[] getBody() { + if (response == null) + return null; + return response.getBody(); + } + + public String getBodyAsString() { + if (response == null) + return null; + return response.getBodyAsString(); + } + + public InputStream getStream() { + if (response == null) + return null; + return response.getStream(); + } + + public boolean isStreamed() { + if (response == null) + return false; + return response.isStreamed(); + } + + public String getBucket() { + if (response == null) + return null; + return response.getBucket(); + } + + public Map getHttpHeaders() { + if (response == null) + return null; + return response.getHttpHeaders(); + } + + public HttpMethod getHttpMethod() { + if (response == null) + return null; + return response.getHttpMethod(); + } + + public String getKey() { + if (response == null) + return null; + return response.getKey(); + } + + public int getStatusCode() { + if (response == null) + return -1; + return response.getStatusCode(); + } + + public boolean isError() { + return true; + } + + public boolean isSuccess() { + return false; + } + + public void close() { + if (response != null) + response.close(); + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/StoreResponse.java b/src/main/java/com/basho/riak/client/http/response/StoreResponse.java new file mode 100644 index 000000000..e90d4c5e5 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/StoreResponse.java @@ -0,0 +1,98 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.util.Collection; +import java.util.Map; + +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.util.Constants; + +/** + * Response from a PUT request for an object. Decorates an HttpResponse to + * interpret store responses from Riak which returns updated object metadata in + * HTTP headers. + */ +public class StoreResponse extends HttpResponseDecorator implements WithBodyResponse { + + private final FetchResponse fetchResponse; + private String vclock = null; + private String lastmod = null; + private String vtag = null; + + /** + * On a 2xx response, parses the HTTP headers into updated object metadata. + */ + public StoreResponse(FetchResponse fetchResponse) { + super(fetchResponse); + + this.fetchResponse = fetchResponse; + + if (fetchResponse != null && fetchResponse.isSuccess()) { + Map headers = fetchResponse.getHttpHeaders(); + vclock = headers.get(Constants.HDR_VCLOCK); + lastmod = headers.get(Constants.HDR_LAST_MODIFIED); + vtag = headers.get(Constants.HDR_ETAG); + } + } + + /** The object's updated vclock or null if Riak didn't return one. */ + public String getVclock() { + return vclock; + } + + /** + * The object's last modified date or null if Riak didn't return one. + */ + public String getLastmod() { + return lastmod; + } + + /** The object's updated etag or null if Riak didn't return one. */ + public String getVtag() { + return vtag; + } + + /** + * @return + * @see com.basho.riak.client.http.response.FetchResponse#hasObject() + */ + public boolean hasObject() { + return fetchResponse.hasObject(); + } + + /** + * @return + * @see com.basho.riak.client.http.response.FetchResponse#getObject() + */ + public RiakObject getObject() { + return fetchResponse.getObject(); + } + + /** + * @return + * @see com.basho.riak.client.http.response.FetchResponse#hasSiblings() + */ + public boolean hasSiblings() { + return fetchResponse.hasSiblings(); + } + + /** + * @return + * @see com.basho.riak.client.http.response.FetchResponse#getSiblings() + */ + public Collection getSiblings() { + return fetchResponse.getSiblings(); + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/StreamHandler.java b/src/main/java/com/basho/riak/client/http/response/StreamHandler.java new file mode 100644 index 000000000..2bc74b3b0 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/StreamHandler.java @@ -0,0 +1,48 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.httpclient.HttpMethod; + +/** + * Used with RiakClient.stream() to process the HTTP responses for fetch + * requests as a stream. + */ +public interface StreamHandler { + + /** + * Process the HTTP response whose value is given as a stream. + * + * @param bucket + * The object's bucket + * @param key + * The object's key + * @param status + * The HTTP status code returned for the request + * @param headers + * The HTTP headers returned in the response + * @param in + * InputStream of the object's value (body) + * @param httpMethod + * The original {@link HttpMethod} used to make the request. Its + * connection is still open and will be closed by the caller on + * return. + * @return true if the object was processed; false otherwise + */ + public boolean process(String bucket, String key, int status, Map headers, InputStream in, + HttpMethod httpMethod); +} diff --git a/src/main/java/com/basho/riak/client/http/response/StreamedKeysCollection.java b/src/main/java/com/basho/riak/client/http/response/StreamedKeysCollection.java new file mode 100644 index 000000000..0d98f8ede --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/StreamedKeysCollection.java @@ -0,0 +1,68 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import org.json.JSONException; +import org.json.JSONTokener; + +import com.basho.riak.client.http.util.CollectionWrapper; + +/** + * Presents the stream of keys from a Riak bucket response with query parameter + * keys=stream as a collection. Keys are read from the stream as needed. Note, + * this class is NOT thread-safe! + */ +public class StreamedKeysCollection extends CollectionWrapper { + + JSONTokener tokens; + boolean readingArray = false; + + public StreamedKeysCollection(JSONTokener tokens) { + this.tokens = tokens; + } + + /** + * Tries to read and cache another set of keys from the input stream. This + * function is actually just a hacked-up implementation that finds the next + * available array in the stream and sucks elements out of it. + */ + @Override protected boolean cacheNext() { + if (tokens == null) + return false; + + try { + while (!tokens.end()) { + char c = tokens.nextClean(); + if ((!readingArray && c == '[') || (readingArray && c == ',')) { + if (tokens.nextClean() != ']') { + tokens.back(); + readingArray = true; + cache(tokens.nextValue().toString()); + return true; + } + } else if (readingArray && c == ']') { + readingArray = false; + } else if (c == '\\') { + tokens.nextClean(); // skip over escaped chars + } + } + } catch (JSONException e) { /* nop */} + + return false; + } + + @Override protected void closeBackend() { + tokens = null; + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/StreamedSiblingsCollection.java b/src/main/java/com/basho/riak/client/http/response/StreamedSiblingsCollection.java new file mode 100644 index 000000000..593a7f430 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/StreamedSiblingsCollection.java @@ -0,0 +1,87 @@ +package com.basho.riak.client.http.response; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.CollectionWrapper; +import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.http.util.Multipart; +import com.basho.riak.client.http.util.StreamedMultipart; + +public class StreamedSiblingsCollection extends CollectionWrapper { + + String bucket; + String key; + RiakClient riak; + StreamedMultipart multipart; + + public StreamedSiblingsCollection(RiakClient riak, String bucket, String key, StreamedMultipart multipart) { + this.bucket = bucket; + this.key = key; + this.riak = riak; + this.multipart = multipart; + } + + /** + * Tries to read and cache another part of the multipart/mixed stream. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server. + */ + @Override protected boolean cacheNext() { + if (multipart == null) + return false; + + String vclock = null; + + if (multipart.getHeaders() != null) { + vclock = multipart.getHeaders().get(Constants.HDR_VCLOCK); + } + + Multipart.Part part; + try { + part = multipart.next(); + } catch (RuntimeException e) { + if (e.getCause() instanceof IOException) { + throw new RiakIORuntimeException(e); + } + throw e; + } + + if (part != null) { + Map headers = part.getHeaders(); + List links = ClientUtils.parseLinkHeader(headers.get(Constants.HDR_LINK)); + Map usermeta = ClientUtils.parseUsermeta(headers); + String location = headers.get(Constants.HDR_LOCATION); + String partBucket = bucket; + String partKey = key; + + if (location != null) { + String[] locationParts = location.split("/"); + if (locationParts.length >= 2) { + partBucket = locationParts[locationParts.length - 2]; + partKey = locationParts[locationParts.length - 1]; + } + } + + RiakObject o = new RiakObject(riak, partBucket, partKey, null, headers.get(Constants.HDR_CONTENT_TYPE), + links, usermeta, vclock, headers.get(Constants.HDR_LAST_MODIFIED), + headers.get(Constants.HDR_ETAG)); + o.setValueStream(part.getStream()); + cache(o); + return true; + } + + return false; + } + + @Override protected void closeBackend() { + riak = null; + multipart = null; + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/WalkResponse.java b/src/main/java/com/basho/riak/client/http/response/WalkResponse.java new file mode 100644 index 000000000..5b28e4c1b --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/WalkResponse.java @@ -0,0 +1,101 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.http.util.Multipart; + +/** + * Response from a GET request for an object with link walking. Decorates an + * HttpResponse to interpret walk responses from Riak which returns + * multipart/mixed documents. + */ +public class WalkResponse extends HttpResponseDecorator implements HttpResponse { + + private List> steps = new ArrayList>(); + + /** + * On a 2xx response, parses the HTTP body into a list of steps. Each step + * contains a list of objects returned in that step. The HTTP body is a + * multipart/mixed message with multipart/mixed subparts + */ + public WalkResponse(HttpResponse r, RiakClient riak) throws RiakResponseRuntimeException { + super(r); + + if (r != null && r.isSuccess()) { + steps = parseSteps(r, riak); + } + } + + public WalkResponse(HttpResponse r) throws RiakResponseRuntimeException { + this(r, null); + } + + /** Whether objects were contained in the response */ + public boolean hasSteps() { + return steps.size() > 0; + } + + /** + * Steps accumulated from link walking. See RiakClient.walk() for more + * information. + */ + public List> getSteps() { + return steps; + } + + /** + * Parse a multipart/mixed message with multipart/mixed subparts into a list + * of lists. + * + * @param r + * HTTP response from Riak + * @param riak + * {@link RiakClient} to associate this object with + * @return A list of lists of {@link RiakObject}s represented by the + * response. + * @throws RiakResponseRuntimeException + * If one of the parts of the body doesn't contain a proper + * multipart/mixed message + */ + private static List> parseSteps(HttpResponse r, RiakClient riak) + throws RiakResponseRuntimeException { + String bucket = r.getBucket(); + String key = r.getKey(); + List> parsedSteps = new ArrayList>(); + List parts = Multipart.parse(r.getHttpHeaders(), r.getBody()); + + if (parts != null) { + for (Multipart.Part part : parts) { + Map partHeaders = part.getHeaders(); + String contentType = partHeaders.get(Constants.HDR_CONTENT_TYPE); + + if (contentType == null || + !(contentType.trim().toLowerCase().startsWith(Constants.CTYPE_MULTIPART_MIXED))) + throw new RiakResponseRuntimeException(r, "multipart/mixed subparts expected in link walk results"); + + parsedSteps.add(ClientUtils.parseMultipart(riak, bucket, key, partHeaders, part.getBody())); + } + } + + return parsedSteps; + } +} diff --git a/src/main/java/com/basho/riak/client/http/response/WithBodyResponse.java b/src/main/java/com/basho/riak/client/http/response/WithBodyResponse.java new file mode 100644 index 000000000..2ff479322 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/response/WithBodyResponse.java @@ -0,0 +1,36 @@ +/* + * This file is provided 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.basho.riak.client.http.response; + +import java.util.Collection; + +import com.basho.riak.client.http.RiakObject; + +/** + * A unified interface for responses that may return one, or more RiakObjects + * + * @see {@link FetchResponse}, {@link StoreResponse} + * @author russell + * + */ +public interface WithBodyResponse extends HttpResponse { + + public boolean hasObject(); + + public RiakObject getObject(); + + public boolean hasSiblings(); + + public Collection getSiblings(); +} diff --git a/src/main/java/com/basho/riak/client/http/util/BranchableInputStream.java b/src/main/java/com/basho/riak/client/http/util/BranchableInputStream.java new file mode 100644 index 000000000..0d6ce0393 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/BranchableInputStream.java @@ -0,0 +1,167 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +import java.io.IOException; + +import java.io.InputStream; + +/** + * An input stream that can be branched into other InputStreams, each + * maintaining its own location, with the main read() method always returning + * bytes from the furthest advanced branch. + * + * @author jlee + */ +public class BranchableInputStream extends InputStream { + + static final int DEFAULT_BASE_CHUNK_SIZE = 1024; + static final int MAX_BYTES_PER_READ = 1024; + int nextChunkSize; + + InputStream impl; + LinkedChunk lastChunk = null; + int dataLen = 0; + int pos; + boolean eof = false; + + public BranchableInputStream(InputStream in) { + this(in, DEFAULT_BASE_CHUNK_SIZE); + } + + public BranchableInputStream(InputStream in, int initialBufferSize) { + impl = in; + lastChunk = new LinkedChunk(0, 0); + nextChunkSize = initialBufferSize; + } + + @Override public int read() throws IOException { + int curpos = pos; + if (readUntil(curpos)) + return lastChunk.get(curpos); + return -1; + } + + @Override public void close() throws IOException { + eof = true; + impl.close(); + } + + public int peek() throws IOException { + int curpos = pos; + int c = read(); + pos = curpos; + return c; + } + + public InputStream branch() { + return new InputStreamBranch(lastChunk, pos); + } + + boolean readUntil(int pos) throws IOException { + if (!eof) { + while ((pos >= dataLen) && !eof) { + if (lastChunk.full()) { + lastChunk.setNext(new LinkedChunk(lastChunk.lastIndex() + 1, nextChunkSize)); + lastChunk = lastChunk.next(); + nextChunkSize *= 2; + } + + int bytesRead = lastChunk.readFrom(impl, MAX_BYTES_PER_READ); + if (bytesRead < 0) { + eof = true; + } else { + dataLen += bytesRead; + } + } + } + if (pos < dataLen) { + this.pos = Math.max(this.pos, pos + 1); + return true; + } + return false; + } + + class InputStreamBranch extends InputStream { + + LinkedChunk chunk; + int pos; + + InputStreamBranch(LinkedChunk chunk, int pos) { + this.chunk = chunk; + this.pos = pos; + } + + @Override public int read() throws IOException { + if (chunk == null || !readUntil(pos)) + return -1; + + while (pos > chunk.lastIndex()) { + chunk = chunk.next; + } + return chunk.get(pos++); + } + + @Override public void close() { + chunk = null; + } + } + + class LinkedChunk { + int offset; + int len; + byte[] buf; + LinkedChunk next = null; + + LinkedChunk(int offset, int size) { + this.offset = offset; + buf = new byte[size]; + len = 0; + } + + int readFrom(InputStream in, int maxBytes) throws IOException { + int bytesRead = in.read(buf, len, Math.min(remaining(), maxBytes)); + if (bytesRead > 0) { + len += bytesRead; + } + return bytesRead; + } + + int get(int index) { + if ((index < offset) || (index - offset >= len)) + return -1; + return buf[index - offset] & 0xff; + } + + int lastIndex() { + return offset + buf.length - 1; + } + + boolean full() { + return (len == buf.length); + } + + int remaining() { + return (buf.length - len); + } + + LinkedChunk next() { + return next; + } + + void setNext(LinkedChunk next) { + this.next = next; + } + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/ClientHelper.java b/src/main/java/com/basho/riak/client/http/util/ClientHelper.java new file mode 100644 index 000000000..404d68792 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/ClientHelper.java @@ -0,0 +1,401 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Map; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.HeadMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.json.JSONObject; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakConfig; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.DefaultHttpResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakExceptionHandler; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StreamHandler; + +/** + * This class performs the actual HTTP requests underlying the operations in + * RiakClient and returns the resulting HTTP responses. It is up to RiakClient + * to interpret the responses and translate them into the appropriate format. + */ +public class ClientHelper { + + private RiakConfig config; + private HttpClient httpClient; + private String clientId = null; + private RiakExceptionHandler exceptionHandler = null; + + public ClientHelper(RiakConfig config, String clientId) { + this.config = config; + httpClient = ClientUtils.newHttpClient(config); + setClientId(clientId); + } + + /** Used for testing -- inject an HttpClient */ + void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * See {@link RiakClient#getClientId()} + */ + public byte[] getClientId() { + try { + return Base64.decodeBase64(clientId.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF-8 support required in JVM"); + } + } + + public void setClientId(String clientId) { + if (clientId != null) { + this.clientId = ClientUtils.encodeClientId(clientId); + } else { + this.clientId = ClientUtils.randomClientId(); + } + } + + /** + * See + * {@link RiakClient#setBucketSchema(String, com.basho.riak.client.http.RiakBucketInfo, RequestMeta)} + */ + public HttpResponse setBucketSchema(String bucket, JSONObject schema, RequestMeta meta) { + if (schema == null) { + schema = new JSONObject(); + } + if (meta == null) { + meta = new RequestMeta(); + } + + meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_JSON); + + PutMethod put = new PutMethod(ClientUtils.makeURI(config, bucket)); + put.setRequestEntity(new ByteArrayRequestEntity(schema.toString().getBytes(), Constants.CTYPE_JSON)); + + return executeMethod(bucket, null, put, meta); + } + + /** + * Same as {@link RiakClient#getBucketSchema(String, RequestMeta)}, except + * only returning the HTTP response. + */ + public HttpResponse getBucketSchema(String bucket, RequestMeta meta) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_KEYS) == null) { + meta.setQueryParam(Constants.QP_KEYS, Constants.NO_KEYS); + } + return listBucket(bucket, meta, false); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response, and + * if streamResponse==true, the response will be streamed back, so the user + * is responsible for calling {@link BucketResponse#close()} + */ + public HttpResponse listBucket(String bucket, RequestMeta meta, boolean streamResponse) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_KEYS) == null) { + if (streamResponse) { + meta.setQueryParam(Constants.QP_KEYS, Constants.STREAM_KEYS); + } else { + meta.setQueryParam(Constants.QP_KEYS, Constants.INCLUDE_KEYS); + } + } + if (meta.getHeader(Constants.HDR_CONTENT_TYPE) == null) { + meta.setHeader(Constants.HDR_CONTENT_TYPE, Constants.CTYPE_JSON); + } + if (meta.getHeader(Constants.HDR_ACCEPT) == null) { + meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_JSON); + } + + GetMethod get = new GetMethod(ClientUtils.makeURI(config, bucket)); + return executeMethod(bucket, null, get, meta, streamResponse); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public HttpResponse store(RiakObject object, RequestMeta meta) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getClientId() == null) { + meta.setClientId(clientId); + } + if (meta.getHeader(Constants.HDR_CONNECTION) == null) { + meta.setHeader(Constants.HDR_CONNECTION, "keep-alive"); + } + + String bucket = object.getBucket(); + String key = object.getKey(); + String url = ClientUtils.makeURI(config, bucket, key); + PutMethod put = new PutMethod(url); + + object.writeToHttpMethod(put); + return executeMethod(bucket, key, put, meta); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public HttpResponse fetchMeta(String bucket, String key, RequestMeta meta) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_R) == null) { + meta.setQueryParam(Constants.QP_R, Constants.DEFAULT_R.toString()); + } + HeadMethod head = new HeadMethod(ClientUtils.makeURI(config, bucket, key)); + return executeMethod(bucket, key, head, meta); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response and + * allows the response to be streamed. + * + * @param bucket + * Same as {@link RiakClient} + * @param key + * Same as {@link RiakClient} + * @param meta + * Same as {@link RiakClient} + * @param streamResponse + * If true, the connection will NOT be released. Use + * HttpResponse.getHttpMethod().getResponseBodyAsStream() to get + * the response stream; HttpResponse.getBody() will return null. + * + * @return Same as {@link RiakClient} + */ + public HttpResponse fetch(String bucket, String key, RequestMeta meta, boolean streamResponse) { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_R) == null) { + meta.setQueryParam(Constants.QP_R, Constants.DEFAULT_R.toString()); + } + GetMethod get = new GetMethod(ClientUtils.makeURI(config, bucket, key)); + return executeMethod(bucket, key, get, meta, streamResponse); + } + + public HttpResponse fetch(String bucket, String key, RequestMeta meta) { + return fetch(bucket, key, meta, false); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException { + if (meta == null) { + meta = new RequestMeta(); + } + if (meta.getQueryParam(Constants.QP_R) == null) { + meta.setQueryParam(Constants.QP_R, Constants.DEFAULT_R.toString()); + } + GetMethod get = new GetMethod(ClientUtils.makeURI(config, bucket, key)); + try { + int status = httpClient.executeMethod(get); + if (handler == null) + return true; + + return handler.process(bucket, key, status, ClientUtils.asHeaderMap(get.getResponseHeaders()), + get.getResponseBodyAsStream(), get); + } finally { + get.releaseConnection(); + } + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public HttpResponse delete(String bucket, String key, RequestMeta meta) { + if (meta == null) { + meta = new RequestMeta(); + } + String url = ClientUtils.makeURI(config, bucket, key); + DeleteMethod delete = new DeleteMethod(url); + return executeMethod(bucket, key, delete, meta); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public HttpResponse walk(String bucket, String key, String walkSpec, RequestMeta meta) { + GetMethod get = new GetMethod(ClientUtils.makeURI(config, bucket, key, walkSpec)); + return executeMethod(bucket, key, get, meta); + } + + /** + * Same as {@link RiakClient}, except only returning the HTTP response + */ + public HttpResponse mapReduce(String job, RequestMeta meta) { + PostMethod post = new PostMethod(config.getMapReduceUrl()); + try { + post.setRequestEntity(new StringRequestEntity(job, Constants.CTYPE_JSON, null)); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("StringRequestEntity should always support no charset", e); + } + return executeMethod(null, null, post, meta); + } + + /** @return the installed exception handler or null if not installed */ + public RiakExceptionHandler getExceptionHandler() { + return exceptionHandler; + } + + /** + * Install an exception handler. If an exception handler is provided, then + * the Riak client will hand exceptions to the handler rather than throwing + * them. + */ + public void setExceptionHandler(RiakExceptionHandler exceptionHandler) { + this.exceptionHandler = exceptionHandler; + } + + /** + * Hands exception e to installed exception handler if there is + * one or throw it. + * + * @return A 0-status {@link HttpResponse}. + */ + public HttpResponse toss(RiakIORuntimeException e) { + if (exceptionHandler != null) { + exceptionHandler.handle(e); + return new DefaultHttpResponse(null, null, 0, null, null, null, null); + } else + throw e; + } + + public HttpResponse toss(RiakResponseRuntimeException e) { + if (exceptionHandler != null) { + exceptionHandler.handle(e); + return new DefaultHttpResponse(null, null, 0, null, null, null, null); + } else + throw e; + } + + /** + * Return the {@link HttpClient} used to make requests, which can be + * configured. + */ + public HttpClient getHttpClient() { + return httpClient; + } + + /** + * @return The config used to construct the HttpClient connecting to Riak. + */ + public RiakConfig getConfig() { + return config; + } + + /** + * Perform and HTTP request and return the resulting response using the + * internal HttpClient. + * + * @param bucket + * Bucket of the object receiving the request. + * @param key + * Key of the object receiving the request or null if the request + * is for a bucket. + * @param httpMethod + * The HTTP request to perform; must not be null. + * @param meta + * Extra HTTP headers to attach to the request. Query parameters + * are ignored; they should have already been used to construct + * httpMethod and query parameters. + * @param streamResponse + * If true, the connection will NOT be released. Use + * HttpResponse.getHttpMethod().getResponseBodyAsStream() to get + * the response stream; HttpResponse.getBody() will return null. + * + * @return The HTTP response returned by Riak from executing + * httpMethod. + * + * @throws RiakIORuntimeException + * If an error occurs during communication with the Riak server + * (i.e. HttpClient threw an IOException) + */ + HttpResponse executeMethod(String bucket, String key, HttpMethod httpMethod, RequestMeta meta, + boolean streamResponse) { + + if (meta != null) { + Map headers = meta.getHeaders(); + for (String header : headers.keySet()) { + httpMethod.setRequestHeader(header, headers.get(header)); + } + + String queryParams = meta.getQueryParams(); + if (queryParams != null && (queryParams.length() != 0)) { + String currentQuery = httpMethod.getQueryString(); + if (currentQuery != null && (currentQuery.length() != 0)) { + httpMethod.setQueryString(currentQuery + "&" + queryParams); + } else { + httpMethod.setQueryString(queryParams); + } + } + } + + try { + httpClient.executeMethod(httpMethod); + + int status = 0; + if (httpMethod.getStatusLine() != null) { + status = httpMethod.getStatusCode(); + } + + Map headers = ClientUtils.asHeaderMap(httpMethod.getResponseHeaders()); + byte[] body = null; + InputStream stream = null; + if (streamResponse) { + stream = httpMethod.getResponseBodyAsStream(); + } else { + body = httpMethod.getResponseBody(); + } + + return new DefaultHttpResponse(bucket, key, status, headers, body, stream, httpMethod); + } catch (IOException e) { + return toss(new RiakIORuntimeException(e)); + } finally { + if (!streamResponse) { + httpMethod.releaseConnection(); + } + } + } + + HttpResponse executeMethod(String bucket, String key, HttpMethod httpMethod, RequestMeta meta) { + return executeMethod(bucket, key, httpMethod, meta, false); + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/ClientUtils.java b/src/main/java/com/basho/riak/client/http/util/ClientUtils.java new file mode 100644 index 000000000..98749a9d8 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/ClientUtils.java @@ -0,0 +1,475 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Map.Entry; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.json.JSONArray; +import org.json.JSONObject; + +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakConfig; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.response.RiakExceptionHandler; + +/** + * Utility functions. + */ +public class ClientUtils { + + // Matches the scheme, host and port of a URL + private static String URL_PATH_MASK = "^(?:[A-Za-z0-9+-\\.]+://)?[^/]*"; + private static Random rng = new Random(); + /** + * Construct a new {@link HttpClient} instance given a {@link RiakConfig}. + * + * @param config + * {@link RiakConfig} containing HttpClient configuration + * specifics. + * @return A new {@link HttpClient} + */ + public static HttpClient newHttpClient(RiakConfig config) { + + HttpClient http = config.getHttpClient(); + HttpConnectionManager m; + + if (http == null) { + m = new MultiThreadedHttpConnectionManager(); + http = new HttpClient(m); + } else { + m = http.getHttpConnectionManager(); + } + + HttpConnectionManagerParams mp = m.getParams(); + if (config.getMaxConnections() != null) { + mp.setMaxTotalConnections(config.getMaxConnections()); + mp.setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, config.getMaxConnections()); + } + + HttpClientParams cp = http.getParams(); + if (config.getTimeout() != null) { + mp.setConnectionTimeout(config.getTimeout().intValue()); + cp.setConnectionManagerTimeout(config.getTimeout()); + cp.setSoTimeout(config.getTimeout().intValue()); + } + if (config.getRetryHandler() != null) { + cp.setParameter(HttpMethodParams.RETRY_HANDLER, config.getRetryHandler()); + } + + return http; + } + + /** + * Return a URL to the given bucket + * + * @param config + * RiakConfig containing the base URL to Riak + * @param bucket + * Bucket whose URL to retrieving + * @return URL to the bucket + */ + public static String makeURI(RiakConfig config, String bucket) { + return config.getUrl() + "/" + urlEncode(bucket); + } + + /** + * Return a URL to the given object + * + * @param config + * RiakConfig containing the base URL to Riak + * @param bucket + * Bucket of the object + * @param key + * Key of the object + * @return URL to the object + */ + public static String makeURI(RiakConfig config, String bucket, String key) { + if (key == null) + return makeURI(config, bucket); + return makeURI(config, bucket) + "/" + urlEncode(key); + } + + /** + * Return a URL to the given object + * + * @param config + * RiakConfig containing the base URL to Riak + * @param bucket + * Bucket of the object + * @param key + * Key of the object + * @param extra + * Extra path information beyond the bucket and key (e.g. for + * link walking or query parameters) + * @return URL to the object + */ + public static String makeURI(RiakConfig config, String bucket, String key, String extra) { + if (extra == null) + return makeURI(config, bucket, key); + + if (!extra.startsWith("?") && !extra.startsWith("/")) { + extra = "/" + extra; + } + + return makeURI(config, bucket, key) + extra; + } + + /** + * Return just the path portion of the given URL + */ + public static String getPathFromUrl(String url) { + if (url == null) + return null; + return url.replaceFirst(URL_PATH_MASK, ""); + } + + /** + * UTF-8 encode the string + */ + public static String urlEncode(String s) { + try { + return URLEncoder.encode(s, "UTF-8"); + } catch (UnsupportedEncodingException unreached) { + // UTF-8 must be supported by every Java implementation: + // http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html + throw new IllegalStateException("UTF-8 must be supported", unreached); + } + } + + /** + * Decodes a UTF-8 encoded string + */ + public static String urlDecode(String s) { + try { + return URLDecoder.decode(s, "UTF-8"); + } catch (UnsupportedEncodingException unreached) { + throw new IllegalStateException("UTF-8 must be supported", unreached); + } + } + + /** + * Base64 encodes the first 4 bytes of clientId into a value acceptable for + * the X-Riak-ClientId header. + */ + public static String encodeClientId(byte[] clientId) { + if (clientId == null || clientId.length < 4) + throw new IllegalArgumentException("ClientId must be at least 4 bytes"); + + try { + return new String(Base64.encodeBase64(new byte[] { clientId[0], clientId[1], clientId[2], clientId[3] }), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF-8 support is required by JVM"); + } + } + + public static String encodeClientId(String clientId) { + return encodeClientId(clientId.getBytes()); + } + + /** + * Returns a random X-Riak-ClientId header value. + */ + public static String randomClientId() { + byte[] rnd = new byte[4]; + rng.nextBytes(rnd); + return encodeClientId(rnd); + } + + /** + * Unquote and unescape an HTTP quoted-string: + * + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 + * + * Does nothing if s is not quoted. + * + * @param s + * quoted-string to unquote + * @return s with quotes and backslash-escaped characters unescaped + */ + public static String unquoteString(String s) { + if (s.startsWith("\"") && s.endsWith("\"")) { + s = s.substring(1, s.length() - 1); + } + return s.replaceAll("\\\\(.)", "$1"); + } + + /** + * Convert a header array returned from {@link HttpClient} to a map + * + * @param headers + * Header array returned from HttpClient + * @return Map of the header names to values + */ + public static Map asHeaderMap(Header[] headers) { + Map m = new HashMap(); + if (headers != null) { + for (Header header : headers) { + m.put(header.getName().toLowerCase(), header.getValue()); + } + } + return m; + } + + /** + * Convert a {@link JSONObject} to a map + * + * @param json + * {@link JSONObject} to convert + * @return Map of the field names to string representations of the values + */ + @SuppressWarnings("rawtypes") public static Map jsonObjectAsMap(JSONObject json) { + if (json == null) + return null; + + Map m = new HashMap(); + for (Iterator iter = json.keys(); iter.hasNext();) { + Object obj = iter.next(); + if (obj != null) { + String key = obj.toString(); + m.put(key, json.optString(key)); + } + } + return m; + } + + /** + * Convert a {@link JSONArray} to a list + * + * @param json + * {@link JSONArray} to convert + * @return List of string representations of the elements + */ + public static List jsonArrayAsList(JSONArray json) { + if (json == null) + return null; + + List l = new ArrayList(); + for (int i = 0; i < json.length(); i++) { + l.add(json.optString(i)); + } + return l; + } + + /** + * Join the elements in arr in to a single string separated by delimiter. + */ + public static String join(String[] arr, String delimiter) { + StringBuffer buf = new StringBuffer(); + if (arr == null || arr.length == 0) + return null; + + buf.append(arr[0]); + for (int i = 1; i < arr.length; i++) { + buf.append(delimiter); + buf.append(arr[i]); + } + return buf.toString(); + } + + /** + * Copies data from an {@link InputStream} to an {@link OutputStream} in + * blocks + * + * @param in + * InputStream to copy + * @param out + * OutputStream to copy to + * @throws IOException + */ + public static void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + while (true) { + final int readCount = in.read(buffer); + if (readCount == -1) { + break; + } + out.write(buffer, 0, readCount); + } + } + + /** + * Parse a link header into a {@link RiakLink}. See {@link LinkHeader}. + * + * @param header + * The HTTP Link header value. + * @return List of {@link RiakLink} objects constructed from the links in + * header in order. + */ + public static List parseLinkHeader(String header) { + List links = new ArrayList(); + Map> parsedLinks = LinkHeader.parse(header); + for (Entry> e: parsedLinks.entrySet()) { + String url = e.getKey(); + RiakLink link = parseOneLink(url, e.getValue()); + if (link != null) { + links.add(link); + } + } + return links; + } + + /** + * Create a {@link RiakLink} object from a single parsed link from the Link + * header + * + * @param url + * The link URL + * @param params + * The link parameters + * @return {@link RiakLink} object + */ + private static RiakLink parseOneLink(String url, Map params) { + String tag = params.get(Constants.LINK_TAG); + if (tag != null) { + String[] parts = url.split("/"); + if (parts.length >= 2) + return new RiakLink(parts[parts.length - 2], parts[parts.length - 1], tag); + } + return null; + } + + /** + * Extract only the user-specified metadata headers from a header set: all + * headers prefixed with X-Riak-Meta-. The prefix is removed before + * returning. + * + * @param headers + * The full HTTP header set from the response + * @return Map of all headers prefixed with X-Riak-Meta- with prefix + * removed. + */ + public static Map parseUsermeta(Map headers) { + Map usermeta = new HashMap(); + if (headers != null) { + for (Entry e : headers.entrySet()) { + String header = e.getKey(); + if (header != null && header.toLowerCase().startsWith(Constants.HDR_USERMETA_PREFIX)) { + usermeta.put(header.substring(Constants.HDR_USERMETA_PREFIX.length()), e.getValue()); + } + } + } + return usermeta; + } + + /** + * Convert a multipart/mixed document to a list of {@link RiakObject}s. + * + * @param riak + * {@link RiakClient} this object should be associate with, or + * null if none + * @param bucket + * original object's bucket + * @param key + * original object's key + * @param docHeaders + * original document's headers + * @param docBody + * original document's body + * @return List of {@link RiakObject}s represented by the multipart document + */ + public static List parseMultipart(RiakClient riak, String bucket, String key, + Map docHeaders, byte[] docBody) { + + String vclock = null; + boolean siblingVclock = false; + + if (docHeaders != null) { + vclock = docHeaders.get(Constants.HDR_VCLOCK); + if( vclock != null) { + siblingVclock = true; + } + } + + List parts = Multipart.parse(docHeaders, docBody); + List objects = new ArrayList(); + if (parts != null) { + for (Multipart.Part part : parts) { + Map headers = part.getHeaders(); + + // handles the case of link walk multi part responses where the vclock header is in the part not the top response + if (!siblingVclock) { + vclock = headers.get(Constants.HDR_VCLOCK); + } + + if(vclock == null) { + // this should never happen + // exception here to shorten path from bug occurrence + // to bug manifestation + throw new IllegalStateException("no vclock found"); + } + + List links = parseLinkHeader(headers.get(Constants.HDR_LINK)); + Map usermeta = parseUsermeta(headers); + String location = headers.get(Constants.HDR_LOCATION); + String partBucket = bucket; + String partKey = key; + + if (location != null) { + String[] locationParts = location.split("/"); + if (locationParts.length >= 2) { + partBucket = locationParts[locationParts.length - 2]; + partKey = locationParts[locationParts.length - 1]; + } + } + + RiakObject o = new RiakObject(riak, partBucket, partKey, part.getBody(), + headers.get(Constants.HDR_CONTENT_TYPE), links, usermeta, vclock, + headers.get(Constants.HDR_LAST_MODIFIED), headers.get(Constants.HDR_ETAG)); + objects.add(o); + } + } + return objects; + } + + /** + * Throws a checked {@link Exception} not declared in the method signature, + * which can be particularly useful for throwing checked exceptions within a + * {@link RiakExceptionHandler}. Clearly, this circumvents compiler + * safeguards, so use with caution. You've been warned. + * + * @param exception + * A checked (or unchecked) exception to be thrown. + */ + public static void throwChecked(final Throwable exception) { + new CheckedThrower().throwChecked(exception); + } +} + +class CheckedThrower { + @SuppressWarnings("unchecked") public void throwChecked(Throwable exception) throws T { + throw (T) exception; + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/CollectionWrapper.java b/src/main/java/com/basho/riak/client/http/util/CollectionWrapper.java new file mode 100644 index 000000000..41cc32e68 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/CollectionWrapper.java @@ -0,0 +1,143 @@ +package com.basho.riak.client.http.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +public abstract class CollectionWrapper implements Collection { + + List cache = new ArrayList(); + + /** + * Cache one or more objects from the backend by calling cache(T) + * + * @return true if an object was added to the cache; false otherwise. + */ + abstract protected boolean cacheNext(); + + /** + * Close the backend so no more objects can be read from it (getNext() + * should only return null afterwards). Called by clear(). + */ + abstract protected void closeBackend(); + + /** + * Called by subclasses to add an object to the cache when executing cacheNext(). + */ + protected void cache(T object) { + cache.add(object); + } + + public boolean add(T e) { + return cache.add(e); + } + + public boolean addAll(Collection c) { + return cache.addAll(c); + } + + public void clear() { + cache.clear(); + closeBackend(); + } + + public boolean contains(Object o) { + if (cache.contains(o)) + return true; + + cacheAll(); + return cache.contains(o); + } + + public boolean containsAll(Collection c) { + if (cache.containsAll(c)) + return true; + + cacheAll(); + return cache.containsAll(c); + } + + public boolean isEmpty() { + cacheAll(); + return cache.isEmpty(); + } + + public Iterator iterator() { + return new WrappedCollectionIterator(); + } + + public boolean remove(Object o) { + if (contains(o)) + return cache.remove(o); + + cacheAll(); + return cache.remove(o); + } + + public boolean removeAll(Collection c) { + cacheAll(); + return cache.removeAll(c); + } + + public boolean retainAll(Collection c) { + cacheAll(); + return cache.retainAll(c); + } + + public int size() { + cacheAll(); + return cache.size(); + } + + public Object[] toArray() { + cacheAll(); + return cache.toArray(); + } + + public A[] toArray(A[] a) { + cacheAll(); + return cache.toArray(a); + } + + List getCache() { + return this.cache; + } + + /** + * Reads and caches all the of keys from the input stream + */ + void cacheAll() { + while (cacheNext()) { /* nop */} + } + + class WrappedCollectionIterator implements Iterator { + + int index = 0; + boolean removed = false; + + public boolean hasNext() { + if (index < cache.size()) + return true; + + return cacheNext(); + } + + public T next() { + removed = false; + while (index >= cache.size() && cacheNext()) { /* nop */} + if (index < cache.size()) + return cache.get(index++); + return null; + } + + public void remove() { + if (!removed && (index > 0) && (index <= cache.size())) { + index--; + cache.remove(index); + removed = true; + } + } + + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/Constants.java b/src/main/java/com/basho/riak/client/http/util/Constants.java new file mode 100644 index 000000000..d6bd729d0 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/Constants.java @@ -0,0 +1,92 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +public interface Constants { + + // Default URL path prefixes Riak HTTP interface + public static String RIAK_URL_PREFIX = "/riak"; + + // JSON fields used by Riak + public static String FL_NAME = "name"; + public static String FL_KEYS = "keys"; + public static String FL_SCHEMA = "props"; + public static String FL_SCHEMA_ALLOW_MULT = "allow_mult"; + public static String FL_SCHEMA_CHASHFUN = "chash_keyfun"; + public static String FL_SCHEMA_CHASHFUN_MOD = "mod"; + public static String FL_SCHEMA_CHASHFUN_FUN = "fun"; + public static String FL_SCHEMA_LINKFUN = "linkfun"; + public static String FL_SCHEMA_LINKFUN_MOD = "mod"; + public static String FL_SCHEMA_LINKFUN_FUN = "fun"; + public static String FL_SCHEMA_NVAL = "n_val"; + + // Header directives used by Riak + public static String LINK_TAG = "riaktag"; + + // HTTP headers used in Riak + public static String HDR_ACCEPT = "accept"; + public static String HDR_CLIENT_ID = "x-riak-clientid"; + public static String HDR_CONNECTION = "connection"; + public static String HDR_CONTENT_LENGTH = "content-length"; + public static String HDR_CONTENT_TYPE = "content-type"; + public static String HDR_ETAG = "etag"; + public static String HDR_IF_MATCH = "if-match"; + public static String HDR_IF_MODIFIED_SINCE = "if-modified-since"; + public static String HDR_IF_UNMODIFIED_SINCE = "if-unmodified-since"; + public static String HDR_IF_NONE_MATCH = "if-none-match"; + public static String HDR_LAST_MODIFIED = "last-modified"; + public static String HDR_LINK = "link"; + public static String HDR_LOCATION = "location"; + public static String HDR_VCLOCK = "x-riak-vclock"; + // Declared twice because of Erlang has bizarre HTTP header case handling. + // If a header name is 21 chars or shorteer, it is auto-capitalized between + // dashes. Otherwise, it is passed as is. Therefore, we just make sure this + // headers prefix is correctly capitalized in requests. + public static String HDR_USERMETA_PREFIX = "x-riak-meta-"; + public static String HDR_USERMETA_REQ_PREFIX = "X-Riak-Meta-"; + + // Content types used in Riak + public static String CTYPE_ANY = "*/*"; + public static String CTYPE_JSON = "application/json"; + public static String CTYPE_OCTET_STREAM = "application/octet-stream"; + public static String CTYPE_MULTIPART_MIXED = "multipart/mixed"; + public static String CTYPE_TEXT = "text/plain"; + + // Default r, w, and dw values to use when not specified + public static Integer DEFAULT_R = 2; + public static Integer DEFAULT_W = null; + public static Integer DEFAULT_DW = null; + + // Values for the "keys" query parameter + public static String NO_KEYS = "false"; + public static String INCLUDE_KEYS = "true"; + public static String STREAM_KEYS = "stream"; + + // Query parameters used in Riak + public static String QP_RETURN_BODY = "returnbody"; + public static String QP_R = "r"; + public static String QP_W = "w"; + public static String QP_DW = "dw"; + public static String QP_RW = "rw"; + public static String QP_KEYS = "keys"; + + // HTTP method names + public static String HTTP_HEAD_METHOD = "HEAD"; + public static String HTTP_GET_METHOD = "GET"; + public static String HTTP_PUT_METHOD = "PUT"; + public static String HTTP_DELETE_METHOD = "DELETE"; + + // Riak magic numbers + public static int RIAK_CLIENT_ID_LENGTH = 4; +} diff --git a/src/main/java/com/basho/riak/client/http/util/LinkHeader.java b/src/main/java/com/basho/riak/client/http/util/LinkHeader.java new file mode 100644 index 000000000..94331fb96 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/LinkHeader.java @@ -0,0 +1,108 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Parses the HTTP Link header as described here: + * + * http://tools.ietf.org/html/draft-nottingham-http-link-header + * + * This implementation is more or less a direct port of mnot's Python + * implementation here: + * + * http://gist.github.com/210535 + * + * @author jlee + */ +public class LinkHeader { + + private static String TOKEN = "(?:[^\\(\\)<>@,;:\\\\\"/\\[\\]\\?={} \\t]+?)"; + private static String QUOTED_STRING = "(?:\"(?:\\\\\"|[^\"])*\")"; + private static String PARAMETER = String.format("(?:%s(?:=(?:%s|%s))?)", TOKEN, TOKEN, QUOTED_STRING); + private static String LINK = "<[^>]*>\\s*(?:;\\s*" + PARAMETER + "?\\s*)*"; + private static String COMMA = "(?:\\s*(?:,\\s*)+)"; + private static String SEMICOLON = "(?:\\s*(?:;\\s*)+)"; + private static String LINK_SPLIT = LINK + "(?=" + COMMA + "|\\s*$)"; + private static String PARAM_SPLIT = PARAMETER + "(?=" + SEMICOLON + "|\\s*$)"; + private static Pattern LINK_SPLITTER = Pattern.compile(LINK_SPLIT); + private static Pattern PARAM_SPLITTER = Pattern.compile(PARAM_SPLIT); + + /** + * Returns a map of links to their parameters. Parameters are a map of + * parameter name to value. + * + * @param header + * Value of the Link header in the format described here: + * + * http://tools.ietf.org/html/draft-nottingham-http-link-header + * + * e.g. {@literal ; param="value", + * } + * + * @return A map of links to their parameters. Parameters are a map of + * parameter name to value. + */ + public static Map> parse(String header) { + Map> out = new LinkedHashMap>(); + + if (header == null || header.length() == 0) + return out; + + Matcher m = LINK_SPLITTER.matcher(header); + while (m.find()) { + String link = m.group().trim(); + String[] urlandparams = link.split(">", 2); + String url = urlandparams[0].substring(1); + Map parsedLink = new HashMap(); + + if (urlandparams.length > 1) { + String params = urlandparams[1]; + for (String param : splitParams(params)) { + String[] parts = param.split("=", 2); + if (parts.length > 1) { + parsedLink.put(parts[0].toLowerCase(), ClientUtils.unquoteString(parts[1])); + } else { + parsedLink.put(parts[0].toLowerCase(), null); + } + } + } + out.put(url, parsedLink); + } + + return out; + } + + private static List splitParams(String s) { + + List items = new ArrayList(); + if (s == null || s.length() == 0) + return items; + + Matcher m = PARAM_SPLITTER.matcher(s); + while (m.find()) { + items.add(m.group().trim()); + } + + return items; + } + +} diff --git a/src/main/java/com/basho/riak/client/http/util/Multipart.java b/src/main/java/com/basho/riak/client/http/util/Multipart.java new file mode 100644 index 000000000..80c0879cd --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/Multipart.java @@ -0,0 +1,255 @@ +/* + * This file is provided 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.basho.riak.client.http.util; + +import org.apache.commons.httpclient.util.EncodingUtil; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + +/** + * Represents a multipart entity as described here: + * + * http://tools.ietf.org/html/rfc2046#section-5.1 + */ +public class Multipart { + + private static byte[] HEADER_DELIM = "\r\n\r\n".getBytes(); + + private static int indexOf(byte[] text, byte[] pattern, int fromIndex) { + if (fromIndex >= text.length || fromIndex < 0) { + throw new IllegalArgumentException("index not within range"); + } + + if (pattern.length == 0) { + throw new IllegalArgumentException("pattern must not be empty"); + } + + byte first = pattern[0]; + int max = text.length - pattern.length; + + for (int i = fromIndex; i <= max; i++) { + if (text[i] != first) { + while (i <= max && text[i] != first) { + i++; + } + } + + if (i <= max) { + int j = i + 1; + int end = j + pattern.length - 1; + for (int k = 1; j < end && text[j] == pattern[k]; j++, k++); + if (j == end) { + return i; + } + } + } + return -1; + } + + /** + * Parses a multipart message or a multipart subpart of a multipart message. + * + * @return A list of the parts parsed into headers and body of this + * multipart message + */ + public static List parse(Map headers, byte[] body) { + if (headers == null || body == null || body.length == 0) + return null; + + + + if (!(body.length >= 2 && body[0] == '\r' && body[1] == '\n')) { + // In order to parse the multipart efficiently, we want to treat the + // first boundary identically to the others, so make sure that the + // first boundary is preceded by a '\r\n' like the others + byte[] newBody = new byte[body.length + 2]; + newBody[0] = '\r'; + newBody[1] = '\n'; + System.arraycopy(body, 0, newBody, 2, body.length); + body = newBody; + } + + String boundary = "\r\n--" + getBoundary(headers.get(Constants.HDR_CONTENT_TYPE)); + byte[] boundaryBytes = boundary.getBytes(); + int boundarySize = boundary.length(); + if ("\r\n--".equals(boundary)) + return null; + + // While this parsing could be more efficiently done in one pass with a + // hand written FSM, hopefully this method is more readable/intuitive. + List parts = new ArrayList(); + int pos = indexOf(body, boundaryBytes, 0); + if (pos != -1) { + while (pos < body.length) { + // first char of part + int start = pos + boundarySize; + // last char of part + 1 + int end = indexOf(body, boundaryBytes, start); + // end of header section + 1 + int headerEnd = indexOf(body, HEADER_DELIM, pos); + // start of body section + int bodyStart = headerEnd + HEADER_DELIM.length; + + // check for end boundary, which is (boundary + "--") + if (body.length >= (start + 2) && body[start] == '-' && body[start+1] == '-') { + break; + } + + if (end == -1) { + end = body.length; + } + + if (headerEnd == -1) { + headerEnd = body.length; + bodyStart = end; + } + + if (bodyStart > end) { + bodyStart = end; + } + + Map partHeaders = parseHeaders(EncodingUtil.getAsciiString(copyOfRange(body, start, headerEnd))); + parts.add(new Part(partHeaders, copyOfRange(body, bodyStart, end))); + + pos = end; + } + } + + return parts; + } + + /** + * A Java6 Arrays.copyOfRange style method locally. + * + * @param original the array to copy + * @param start the start of the copy range + * @param end the end of the copy range + * @return a new array populated with the bytes from original[start] to original[end]. + */ + private static byte[] copyOfRange(byte[] original, int start, int end) { + final byte[] copy = new byte[end-start]; + System.arraycopy(original, start, copy, 0, end-start); + return copy; + } + + /** + * Parse a block of header lines as defined here: + * + * http://tools.ietf.org/html/rfc822#section-3.2 + * + * @param s + * The header blob + * @return Map of header names to values + */ + public static Map parseHeaders(String s) { + // "unfold" header lines (http://tools.ietf.org/html/rfc822#section-3.1) + s.replaceAll("\r\n\\s+", " "); + + String[] headers = s.split("\r\n"); + Map parsedHeaders = new HashMap(); + for (String header : headers) { + // Split header line into name and value + String[] nv = header.split("\\s*:\\s*", 2); + if (nv.length > 1) { + parsedHeaders.put(nv[0].trim().toLowerCase(), nv[1].trim()); + } + } + return parsedHeaders; + } + + /** + * Given a content type value, get the "boundary" parameter + * + * @param contentType + * Content type value with boundary parameter. Should be of the + * form "type/subtype; boundary=foobar; param=value" + * @return Value of the boundary parameter + */ + public static String getBoundary(String contentType) { + String[] params = contentType.split("\\s*;\\s*"); + for (String param : params) { + String[] nv = param.split("\\s*=\\s*", 2); + if (nv.length > 1) { + if ("boundary".equals(nv[0].toLowerCase())) + return ClientUtils.unquoteString(nv[1]); + } + } + return ""; + } + + /** + * A single part of a multipart entity + */ + public static class Part { + private Map headers; + private byte[] body = null; + private InputStream stream; + + public Part(Map headers, byte[] body) { + this.headers = headers; + if(body != null) { + this.body = body.clone(); + } + } + + public Part(Map headers, InputStream body) { + this.headers = headers; + stream = body; + } + + /** + * Headers defined in the part + */ + public Map getHeaders() { + return headers; + } + + /** + * Body of this part + */ + public byte[] getBody() { + if (body == null && stream != null) { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + for (int readCount = 0; readCount != -1; readCount = stream.read(buffer)) { + os.write(buffer, 0, readCount); + } + body = os.toByteArray(); + } catch (IOException e) { /* nop */} + stream = null; + } + return body; + } + + public String getBodyAsString() { + byte[] body = getBody(); + if (body == null) + return null; + return new String(body); + } + + public InputStream getStream() { + if (stream == null && body != null) { + stream = new ByteArrayInputStream(body); + } + + return stream; + } + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java b/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java new file mode 100644 index 000000000..452b3944a --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java @@ -0,0 +1,92 @@ +package com.basho.riak.client.http.util; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A wrapper that reads a single element an underlying {@link InputStream} + * containing contains a delimited list + * + * @author jlee + */ +public class OneTokenInputStream extends InputStream { + + int maxBufferLen; + InputStream impl; + boolean eof = false; + int pos = 0; + int dataLen = 0; + int bufOffset = 0; + StringBuilder buf = null; + String delimiter; + + public OneTokenInputStream(InputStream in, String delimiter) { + impl = in; + maxBufferLen = Math.max(1024, delimiter.length() * 2); + this.delimiter = delimiter; + } + + @Override public int read() throws IOException { + while (!eof && pos >= dataLen) { + buffer(); + } + if (pos >= dataLen) + return -1; + + char c = buf.charAt(pos - bufOffset); + pos++; + return c; + } + + @Override public void close() throws IOException { + impl.close(); + impl = null; + eof = true; + } + + public boolean done() { + return eof; + } + + private void buffer() throws IOException { + if (eof) + return; + + if (buf == null) { + initBuffer(); + } + if (!eof) { + int c = impl.read(); + if (c == -1) { + dataLen = buf.length(); + eof = true; + } else { + buf.append((char) c); + if (buf.length() > maxBufferLen) { + bufOffset += buf.length() - delimiter.length(); + buf.delete(0, buf.length() - delimiter.length()); + } + if (buf.indexOf(delimiter) >= 0) { + eof = true; + } else { + dataLen++; + } + } + } + } + + private void initBuffer() throws IOException { + byte[] headStart = new byte[delimiter.length() - 1]; + int offset = 0; + while (offset < headStart.length) { + int bytesRead = impl.read(headStart, offset, headStart.length - offset); + if (bytesRead == -1) { + eof = true; + return; + } else { + offset += bytesRead; + } + } + buf = new StringBuilder(new String(headStart)); + } +} diff --git a/src/main/java/com/basho/riak/client/http/util/StreamedMultipart.java b/src/main/java/com/basho/riak/client/http/util/StreamedMultipart.java new file mode 100644 index 000000000..f26c00726 --- /dev/null +++ b/src/main/java/com/basho/riak/client/http/util/StreamedMultipart.java @@ -0,0 +1,173 @@ +package com.basho.riak.client.http.util; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; + +import com.basho.riak.client.http.util.Multipart.Part; + +public class StreamedMultipart implements Iterator { + + Map headers = null; + BranchableInputStream stream; + String boundary; + boolean foundNext = false; + BranchableInputStream currentPartStream = null; + + /** + * Parses a multipart message or a multipart subpart of a multipart message. + * Each parts of the message is parsed into a map of headers and the body as + * an InputStream. stream is not consumed until the return value is iterated + * over. It is consumed as each part is encountered. A part's body + * InputStream does not need to be consumed before proceed to the next part. + * If it is not consumed, it will be buffered in memory and accessible + * later. + * + * @param headers + * The headers from the original message, which contains the + * Content-Type header including the boundary string + * @param stream + * The input stream to read from + * @throws IOException + * There was a communication error reading the input stream while + * looking for the initial boundary + * @throws EOFException + * The initial boundary was not found + */ + public StreamedMultipart(Map headers, InputStream stream) throws IOException, EOFException { + if (headers == null || stream == null) + throw new IllegalArgumentException(); + + String initialBoundary = "--" + Multipart.getBoundary(headers.get(Constants.HDR_CONTENT_TYPE)); + String boundary = "\r\n" + initialBoundary; + + // Find the first boundary, ignoring everything preceding it + StringBuilder sb = new StringBuilder(); + while (true) { + int c = stream.read(); + if (c == -1) + throw new EOFException(); + sb.append((char) c); + if ((sb.length() == initialBoundary.length() && initialBoundary.equals(sb.toString())) || + (sb.indexOf(boundary, sb.length() - boundary.length()) >= 0)) { + finishReadingLine(stream); + break; + } + } + + this.headers = headers; + this.boundary = boundary; + this.stream = new BranchableInputStream(new OneTokenInputStream(stream, boundary + "--")); + } + + private void finishReadingLine(InputStream in) throws IOException { + while (true) { + int c = in.read(); + if (c == -1 || c == '\n') + break; + } + } + + /** + * Return the map of document headers that this object was constructed with. + */ + public Map getHeaders() { + return headers; + } + + /** + * See {@link Iterator#hasNext()}. + * + * @throws RuntimeException + * (IOException) if there is an error reading the next part from + * the input stream + */ + public boolean hasNext() { + if (foundNext) + return true; + + try { + foundNext = findNext(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return foundNext; + } + + /** + * See {@link Iterator#next()}. + * + * @throws RuntimeException + * (IOException) if there is an error reading the next part from + * the input stream + */ + public Part next() { + if (!hasNext()) + return null; + foundNext = false; + + String headerBlock = null; + try { + headerBlock = readHeaderBlock(currentPartStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + + Map headers = Multipart.parseHeaders(headerBlock); + return new Part(headers, currentPartStream.branch()); + } + + public void remove() { /* nop */} + + /** + * Move this.currentPartStream to the next part in the entity + * + * @return true if there is another part was found + * + * @throws IOException + */ + private boolean findNext() throws IOException { + if (currentPartStream != null) { + InputStream is = currentPartStream.branch(); + try { + while (is.read() != -1) { /* nop */} // advance stream to end of next boundary + finishReadingLine(stream); // and consume the rest of the boundary line including the newline + } catch (IOException e) { + throw new RuntimeException(e); + } + } + if (stream.peek() != -1) { + currentPartStream = new BranchableInputStream(new OneTokenInputStream(stream.branch(), boundary)); + return true; + } + return false; + } + + /** + * Read in the header block from a stream (i.e. everything before and + * including the first empty line) + * + * @param in + * Stream to read header block from + * + * @return String containing the header block + */ + private String readHeaderBlock(InputStream in) throws IOException { + StringBuilder headers = new StringBuilder(); + boolean currentLineEmpty = true; + while (true) { + int c = in.read(); + if (c == -1 || (currentLineEmpty && c == '\n')) { + break; + } else if (c == '\n') { + currentLineEmpty = true; + } else if (c != '\r' && c != '\n') { + currentLineEmpty = false; + } + headers.append((char) c); + } + return headers.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/mapreduce/ErlangFunction.java b/src/main/java/com/basho/riak/client/mapreduce/ErlangFunction.java index 3b3ba3889..d497f1132 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/ErlangFunction.java +++ b/src/main/java/com/basho/riak/client/mapreduce/ErlangFunction.java @@ -20,7 +20,15 @@ * Represents an Erlang function used in a map or reduce phase * of a map/reduce job * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.ErlangFunction + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.ErlangFunction */ +@Deprecated public class ErlangFunction implements MapReduceFunction { private String module; diff --git a/src/main/java/com/basho/riak/client/mapreduce/JavascriptFunction.java b/src/main/java/com/basho/riak/client/mapreduce/JavascriptFunction.java index 62740c477..fef9da3c8 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/JavascriptFunction.java +++ b/src/main/java/com/basho/riak/client/mapreduce/JavascriptFunction.java @@ -20,7 +20,16 @@ * Represents a Javascript function used in a map or reduce phase * of a map/reduce job * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.JavascriptFunction + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.JavascriptFunction + * */ +@Deprecated public class JavascriptFunction implements MapReduceFunction { private String source; diff --git a/src/main/java/com/basho/riak/client/mapreduce/LinkFunction.java b/src/main/java/com/basho/riak/client/mapreduce/LinkFunction.java index 1db54a7be..809b0835a 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/LinkFunction.java +++ b/src/main/java/com/basho/riak/client/mapreduce/LinkFunction.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONObject; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.LinkFunction + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.LinkFunction + */ +@Deprecated public class LinkFunction implements MapReduceFunction { private String bucket = null; diff --git a/src/main/java/com/basho/riak/client/mapreduce/MapReduceFunction.java b/src/main/java/com/basho/riak/client/mapreduce/MapReduceFunction.java index a1b7954bf..7e05bdcd9 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/MapReduceFunction.java +++ b/src/main/java/com/basho/riak/client/mapreduce/MapReduceFunction.java @@ -16,9 +16,17 @@ import org.json.JSONObject; /** - * Interface for describing functions used in - * map/reduce jobs + * Interface for describing functions used in map/reduce jobs + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.MapReduceFunction + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.MapReduceFunction */ +@Deprecated public interface MapReduceFunction { public static enum Types { diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/BetweenFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/BetweenFilter.java index 4530241a8..581a5830a 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/BetweenFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/BetweenFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.BetweenFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.BetweenFilter + */ +@Deprecated public class BetweenFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/EndsWithFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/EndsWithFilter.java index d64ac9f74..938ad9643 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/EndsWithFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/EndsWithFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.EndsWithFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.EndsWithFilter + */ +@Deprecated public class EndsWithFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/EqualToFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/EqualToFilter.java index 9faef7059..407583835 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/EqualToFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/EqualToFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.EqualToFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.EqualToFilter + */ +@Deprecated public class EqualToFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/FloatToStringFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/FloatToStringFilter.java index b3957b10e..268d8fdad 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/FloatToStringFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/FloatToStringFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.FloatToStringFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.FloatToStringFilter + */ +@Deprecated public class FloatToStringFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanFilter.java index 657bc374d..0543c04d1 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.GreaterThanFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.GreaterThanFilter + */ +@Deprecated public class GreaterThanFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanOrEqualFilter.java index 5b7dad220..3725ceb32 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanOrEqualFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/GreaterThanOrEqualFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.GreaterThanOrEqualFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.GreaterThanOrEqualFilter + */ +@Deprecated public class GreaterThanOrEqualFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/IntToStringFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/IntToStringFilter.java index ecc01d6f1..2eddb44d5 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/IntToStringFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/IntToStringFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.IntToStringFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.IntToStringFilter + */ +@Deprecated public class IntToStringFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanFilter.java index a78c3c35e..872b3a4a1 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LessThanFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LessThanFilter + */ +@Deprecated public class LessThanFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanOrEqualFilter.java index 308524cb9..a0aa1c4aa 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanOrEqualFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LessThanOrEqualFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LessThanOrEqualFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LessThanOrEqualFilter + */ +@Deprecated public class LessThanOrEqualFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalAndFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalAndFilter.java index 13f5a30b4..de61b7d03 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalAndFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalAndFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LogicalAndFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LogicalAndFilter + */ +@Deprecated public class LogicalAndFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalFilterGroup.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalFilterGroup.java index ed52fa190..ba9577c7f 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalFilterGroup.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalFilterGroup.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LogicalFilterGroup + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LogicalFilterGroup + */ +@Deprecated public class LogicalFilterGroup implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; private JSONArray filterArray = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalNotFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalNotFilter.java index 1a0738af7..c81c1673a 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalNotFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalNotFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LogicalNotFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LogicalNotFilter + */ +@Deprecated public class LogicalNotFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalOrFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalOrFilter.java index 2e3b50e05..94180cedb 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalOrFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/LogicalOrFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.LogicalOrFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.LogicalOrFilter + */ +@Deprecated public class LogicalOrFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.LOGICAL; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/MapReduceFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/MapReduceFilter.java index b2329a687..624f2a2f2 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/MapReduceFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/MapReduceFilter.java @@ -15,10 +15,19 @@ import org.json.JSONArray; -/* +/** * Interface for filter functions used for * key filtering + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.MapReduceFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.MapReduceFilter */ +@Deprecated public interface MapReduceFilter { public static enum Types { diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/MatchFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/MatchFilter.java index fbeb4aacd..98039e079 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/MatchFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/MatchFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.MatchFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.MatchFilter + */ +@Deprecated public class MatchFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/NotEqualToFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/NotEqualToFilter.java index d8be998ac..83fa53166 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/NotEqualToFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/NotEqualToFilter.java @@ -16,6 +16,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.NotEqualToFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.NotEqualToFilter + */ +@Deprecated public class NotEqualToFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java index fe6dcc19e..f4f8ae0d4 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/SetMemberFilter.java @@ -18,6 +18,16 @@ import org.json.JSONException; import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.SetMemberFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.SetMemberFilter + */ +@Deprecated public class SetMemberFilter implements MapReduceFilter { private static final String NAME = "set_member"; private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/SimilarToFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/SimilarToFilter.java index 98b8b9cfb..b79161195 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/SimilarToFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/SimilarToFilter.java @@ -15,6 +15,17 @@ import org.json.JSONArray; +/** + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.SimilarToFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.SimilarToFilter + */ +@Deprecated public class SimilarToFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/StartsWithFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/StartsWithFilter.java index a7f14d153..a58b33c1b 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/StartsWithFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/StartsWithFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.StartsWithFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.StartsWithFilter + */ +@Deprecated public class StartsWithFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/StringToFloatFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/StringToFloatFilter.java index bf0c4c602..2645b593b 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/StringToFloatFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/StringToFloatFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.StringToFloatFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.StringToFloatFilter + */ +@Deprecated public class StringToFloatFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/StringToIntFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/StringToIntFilter.java index 0104d0a66..008aeba06 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/StringToIntFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/StringToIntFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.StringToIntFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.StringToIntFilter + */ +@Deprecated public class StringToIntFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.FILTER; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/ToLowerFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/ToLowerFilter.java index eef0e0f4c..4002bc5fd 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/ToLowerFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/ToLowerFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.ToLowerFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.ToLowerFilter + */ +@Deprecated public class ToLowerFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/ToUpperFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/ToUpperFilter.java index df3ad224e..3b8884e5c 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/ToUpperFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/ToUpperFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.ToUpperFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.ToUpperFilter + */ +@Deprecated public class ToUpperFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/TokenizeFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/TokenizeFilter.java index 3f526df21..ccb6bd1a1 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/TokenizeFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/TokenizeFilter.java @@ -15,6 +15,16 @@ import org.json.JSONArray; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.TokenizeFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.TokenizeFilter + */ +@Deprecated public class TokenizeFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; private JSONArray args = new JSONArray(); diff --git a/src/main/java/com/basho/riak/client/mapreduce/filter/UrlDecodeFilter.java b/src/main/java/com/basho/riak/client/mapreduce/filter/UrlDecodeFilter.java index fbea13619..cfbbe2bce 100644 --- a/src/main/java/com/basho/riak/client/mapreduce/filter/UrlDecodeFilter.java +++ b/src/main/java/com/basho/riak/client/mapreduce/filter/UrlDecodeFilter.java @@ -15,6 +15,17 @@ import org.json.JSONArray; + +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.mapreduce.filter.UrlDecodeFilter + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.mapreduce.filter.UrlDecodeFilter + */ +@Deprecated public class UrlDecodeFilter implements MapReduceFilter { private MapReduceFilter.Types type = MapReduceFilter.Types.TRANSFORM; diff --git a/src/main/java/com/basho/riak/client/plain/ConvertToCheckedExceptions.java b/src/main/java/com/basho/riak/client/plain/ConvertToCheckedExceptions.java index f3defe503..e11b346a1 100644 --- a/src/main/java/com/basho/riak/client/plain/ConvertToCheckedExceptions.java +++ b/src/main/java/com/basho/riak/client/plain/ConvertToCheckedExceptions.java @@ -24,7 +24,16 @@ * RiakResponseRuntimeException to checked exceptions RiakIOException and * RiakRuntimeException. Be careful that everywhere calling a {@link RiakClient} * with this handler installed contains the appropriate throws declaration. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.plain.ConvertToCheckedExceptions + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.plain.ConvertToCheckedExceptions */ +@Deprecated public class ConvertToCheckedExceptions implements RiakExceptionHandler { /** diff --git a/src/main/java/com/basho/riak/client/plain/PlainClient.java b/src/main/java/com/basho/riak/client/plain/PlainClient.java index 5435e15e9..6b5321040 100644 --- a/src/main/java/com/basho/riak/client/plain/PlainClient.java +++ b/src/main/java/com/basho/riak/client/plain/PlainClient.java @@ -37,7 +37,16 @@ * An adapter from {@link RiakClient} to a slightly less HTTP, more * Java-centric, interface. Objects are returned without HTTP specific * information and exceptions are thrown on unsuccessful responses. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.plain.PlainClient + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.plain.PlainClient */ +@Deprecated public class PlainClient { private RiakClient impl; diff --git a/src/main/java/com/basho/riak/client/plain/RiakIOException.java b/src/main/java/com/basho/riak/client/plain/RiakIOException.java index abdf1e5ed..4b67947a8 100644 --- a/src/main/java/com/basho/riak/client/plain/RiakIOException.java +++ b/src/main/java/com/basho/riak/client/plain/RiakIOException.java @@ -17,7 +17,16 @@ /** * A checked wrapper for {@link RiakIORuntimeException}. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.plain.RiakIOException + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.plain.RiakIOException */ +@Deprecated public class RiakIOException extends Exception { private static final long serialVersionUID = 2179229841757644538L; diff --git a/src/main/java/com/basho/riak/client/plain/RiakResponseException.java b/src/main/java/com/basho/riak/client/plain/RiakResponseException.java index 53db6e2ce..a26ab0cfc 100644 --- a/src/main/java/com/basho/riak/client/plain/RiakResponseException.java +++ b/src/main/java/com/basho/riak/client/plain/RiakResponseException.java @@ -23,7 +23,16 @@ /** * A checked decorator for {@link RiakResponseRuntimeException} + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.plain.RiakResponseException + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.plain.RiakResponseException */ +@Deprecated public class RiakResponseException extends Exception implements HttpResponse { private static final long serialVersionUID = 5932513075276473483L; diff --git a/src/main/java/com/basho/riak/client/request/MapReduceBuilder.java b/src/main/java/com/basho/riak/client/request/MapReduceBuilder.java index 9fd9f193a..9aaa6ede1 100644 --- a/src/main/java/com/basho/riak/client/request/MapReduceBuilder.java +++ b/src/main/java/com/basho/riak/client/request/MapReduceBuilder.java @@ -39,7 +39,16 @@ /** * Builds a map/reduce job description and submits it Uses the same chained * method metaphor as StringBuilder or StringBuffer + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.request.MapReduceBuilder + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.request.MapReduceBuilder */ +@Deprecated public class MapReduceBuilder { private static enum Types { diff --git a/src/main/java/com/basho/riak/client/request/RequestMeta.java b/src/main/java/com/basho/riak/client/request/RequestMeta.java index 91d1e7ccc..fd4584384 100644 --- a/src/main/java/com/basho/riak/client/request/RequestMeta.java +++ b/src/main/java/com/basho/riak/client/request/RequestMeta.java @@ -25,7 +25,16 @@ /** * Extra headers and query parameters to send with a Riak operation. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.request.RequestMeta + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.request.RequestMeta */ +@Deprecated public class RequestMeta { private Map queryParams = new LinkedHashMap(); diff --git a/src/main/java/com/basho/riak/client/request/RiakWalkSpec.java b/src/main/java/com/basho/riak/client/request/RiakWalkSpec.java index a19109b61..eb324ed4e 100644 --- a/src/main/java/com/basho/riak/client/request/RiakWalkSpec.java +++ b/src/main/java/com/basho/riak/client/request/RiakWalkSpec.java @@ -19,10 +19,19 @@ /** * Taken from Jiak client in Riak source 12/1/09. - * + * * RiakWalkSpecStep is the internal representation of a RiakWalkSpec segment. It * should not be used directly. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.request.RiakWalkSpecStep + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.request.RiakWalkSpecStep */ +@Deprecated class RiakWalkSpecStep { public final String bucket; public final String tag; diff --git a/src/main/java/com/basho/riak/client/response/BucketResponse.java b/src/main/java/com/basho/riak/client/response/BucketResponse.java index 74f6bbcf7..5ca26353d 100644 --- a/src/main/java/com/basho/riak/client/response/BucketResponse.java +++ b/src/main/java/com/basho/riak/client/response/BucketResponse.java @@ -31,7 +31,16 @@ * Response from a GET request at a bucket's URL. Decorates an HttpResponse to * interpret listBucket response from Riak, which is a JSON object with the keys * "props" and "keys". + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.BucketResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.BucketResponse */ +@Deprecated public class BucketResponse extends HttpResponseDecorator implements HttpResponse { private RiakBucketInfo bucketInfo = null; diff --git a/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java b/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java index be19df1e1..c97516820 100644 --- a/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java +++ b/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java @@ -24,7 +24,16 @@ /** * Simple implementation of HttpResponse interface. Simply stores and returns * the various fields. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.DefaultHttpResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.DefaultHttpResponse */ +@Deprecated public class DefaultHttpResponse implements HttpResponse { private String bucket; diff --git a/src/main/java/com/basho/riak/client/response/FetchResponse.java b/src/main/java/com/basho/riak/client/response/FetchResponse.java index 09d74682a..1660675b2 100644 --- a/src/main/java/com/basho/riak/client/response/FetchResponse.java +++ b/src/main/java/com/basho/riak/client/response/FetchResponse.java @@ -30,7 +30,16 @@ * Response from a HEAD or GET request for an object. Decorates an HttpResponse * to interpret fetch and fetchMeta responses from Riak's HTTP interface which * returns object metadata in HTTP headers and value in the body. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.FetchResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.FetchResponse */ +@Deprecated public class FetchResponse extends HttpResponseDecorator implements WithBodyResponse { private RiakObject object = null; diff --git a/src/main/java/com/basho/riak/client/response/HttpResponse.java b/src/main/java/com/basho/riak/client/response/HttpResponse.java index 9bf359a43..e6ec6150f 100644 --- a/src/main/java/com/basho/riak/client/response/HttpResponse.java +++ b/src/main/java/com/basho/riak/client/response/HttpResponse.java @@ -20,7 +20,16 @@ /** * HTTP response information resulting from some HTTP operation + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.HttpResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.HttpResponse */ +@Deprecated public interface HttpResponse { /** diff --git a/src/main/java/com/basho/riak/client/response/HttpResponseDecorator.java b/src/main/java/com/basho/riak/client/response/HttpResponseDecorator.java index a89cafb6f..54d78ef38 100644 --- a/src/main/java/com/basho/riak/client/response/HttpResponseDecorator.java +++ b/src/main/java/com/basho/riak/client/response/HttpResponseDecorator.java @@ -21,7 +21,16 @@ /** * A default decorator implementation for HttpResponse + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.HttpResponseDecorator + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.HttpResponseDecorator */ +@Deprecated public class HttpResponseDecorator implements HttpResponse { protected HttpResponse impl = null; diff --git a/src/main/java/com/basho/riak/client/response/MapReduceResponse.java b/src/main/java/com/basho/riak/client/response/MapReduceResponse.java index 81147582c..9c20da05a 100644 --- a/src/main/java/com/basho/riak/client/response/MapReduceResponse.java +++ b/src/main/java/com/basho/riak/client/response/MapReduceResponse.java @@ -19,7 +19,16 @@ /** * Response from a map-reduce query (POST to /mapred). Decorates an HttpResponse * and parses returned JSON array returned from Riak. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.MapReduceResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.MapReduceResponse */ +@Deprecated public class MapReduceResponse extends HttpResponseDecorator implements HttpResponse { JSONArray result = null; diff --git a/src/main/java/com/basho/riak/client/response/RiakExceptionHandler.java b/src/main/java/com/basho/riak/client/response/RiakExceptionHandler.java index f29048255..ae296b065 100644 --- a/src/main/java/com/basho/riak/client/response/RiakExceptionHandler.java +++ b/src/main/java/com/basho/riak/client/response/RiakExceptionHandler.java @@ -21,7 +21,16 @@ * thrown. If exceptions can be handled centrally by the caller, using an * exception handler can result in cleaner code by avoiding repeated try/catch * blocks for every operation. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.RiakExceptionHandler + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.RiakExceptionHandler */ +@Deprecated public interface RiakExceptionHandler { /** Handle exceptions caused by communication errors with the sever */ diff --git a/src/main/java/com/basho/riak/client/response/RiakIORuntimeException.java b/src/main/java/com/basho/riak/client/response/RiakIORuntimeException.java index 14fe242bf..d872e57ed 100644 --- a/src/main/java/com/basho/riak/client/response/RiakIORuntimeException.java +++ b/src/main/java/com/basho/riak/client/response/RiakIORuntimeException.java @@ -17,7 +17,17 @@ /** * Thrown when an error occurs during communication with the Riak server. + * is returned in the exception. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.RiakIORuntimeException + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.RiakIORuntimeException */ +@Deprecated public class RiakIORuntimeException extends RuntimeException { private static final long serialVersionUID = -3451479917953961929L; diff --git a/src/main/java/com/basho/riak/client/response/RiakResponseRuntimeException.java b/src/main/java/com/basho/riak/client/response/RiakResponseRuntimeException.java index 59ed6bf2f..ffb3602ba 100644 --- a/src/main/java/com/basho/riak/client/response/RiakResponseRuntimeException.java +++ b/src/main/java/com/basho/riak/client/response/RiakResponseRuntimeException.java @@ -21,7 +21,16 @@ /** * Thrown when the Riak server returns a malformed response. The HTTP response * is returned in the exception. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.RiakResponseRuntimeException + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.RiakResponseRuntimeException */ +@Deprecated public class RiakResponseRuntimeException extends RuntimeException implements HttpResponse { private static final long serialVersionUID = 2853253336513247178L; diff --git a/src/main/java/com/basho/riak/client/response/StoreResponse.java b/src/main/java/com/basho/riak/client/response/StoreResponse.java index 8d50245aa..adde7c1e4 100644 --- a/src/main/java/com/basho/riak/client/response/StoreResponse.java +++ b/src/main/java/com/basho/riak/client/response/StoreResponse.java @@ -23,7 +23,16 @@ * Response from a PUT request for an object. Decorates an HttpResponse to * interpret store responses from Riak which returns updated object metadata in * HTTP headers. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.StoreResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.StoreResponse */ +@Deprecated public class StoreResponse extends HttpResponseDecorator implements WithBodyResponse { private final FetchResponse fetchResponse; diff --git a/src/main/java/com/basho/riak/client/response/StreamHandler.java b/src/main/java/com/basho/riak/client/response/StreamHandler.java index 7f67f6f5d..fd64b864a 100644 --- a/src/main/java/com/basho/riak/client/response/StreamHandler.java +++ b/src/main/java/com/basho/riak/client/response/StreamHandler.java @@ -21,7 +21,16 @@ /** * Used with RiakClient.stream() to process the HTTP responses for fetch * requests as a stream. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.StreamHandler + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.StreamHandler */ +@Deprecated public interface StreamHandler { /** diff --git a/src/main/java/com/basho/riak/client/response/StreamedKeysCollection.java b/src/main/java/com/basho/riak/client/response/StreamedKeysCollection.java index 846fc9a9f..9b63829d9 100644 --- a/src/main/java/com/basho/riak/client/response/StreamedKeysCollection.java +++ b/src/main/java/com/basho/riak/client/response/StreamedKeysCollection.java @@ -22,7 +22,16 @@ * Presents the stream of keys from a Riak bucket response with query parameter * keys=stream as a collection. Keys are read from the stream as needed. Note, * this class is NOT thread-safe! + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.StreamedKeysCollection + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.StreamedKeysCollection */ +@Deprecated public class StreamedKeysCollection extends CollectionWrapper { JSONTokener tokens; diff --git a/src/main/java/com/basho/riak/client/response/StreamedSiblingsCollection.java b/src/main/java/com/basho/riak/client/response/StreamedSiblingsCollection.java index 7f6c3b82d..3c88662ad 100644 --- a/src/main/java/com/basho/riak/client/response/StreamedSiblingsCollection.java +++ b/src/main/java/com/basho/riak/client/response/StreamedSiblingsCollection.java @@ -13,6 +13,16 @@ import com.basho.riak.client.util.Multipart; import com.basho.riak.client.util.StreamedMultipart; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.StreamedSiblingsCollections + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.StreamedSiblingsCollection + */ +@Deprecated public class StreamedSiblingsCollection extends CollectionWrapper { String bucket; diff --git a/src/main/java/com/basho/riak/client/response/WalkResponse.java b/src/main/java/com/basho/riak/client/response/WalkResponse.java index 351738ef4..16623e52f 100644 --- a/src/main/java/com/basho/riak/client/response/WalkResponse.java +++ b/src/main/java/com/basho/riak/client/response/WalkResponse.java @@ -27,7 +27,16 @@ * Response from a GET request for an object with link walking. Decorates an * HttpResponse to interpret walk responses from Riak which returns * multipart/mixed documents. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.WalkResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.WalkResponse */ +@Deprecated public class WalkResponse extends HttpResponseDecorator implements HttpResponse { private List> steps = new ArrayList>(); diff --git a/src/main/java/com/basho/riak/client/response/WithBodyResponse.java b/src/main/java/com/basho/riak/client/response/WithBodyResponse.java index fc20e1f4f..9a453ff49 100644 --- a/src/main/java/com/basho/riak/client/response/WithBodyResponse.java +++ b/src/main/java/com/basho/riak/client/response/WithBodyResponse.java @@ -22,8 +22,16 @@ * * @see {@link FetchResponse}, {@link StoreResponse} * @author russell - * + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.response.WithBodyResponse + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.response.WithBodyResponse */ +@Deprecated public interface WithBodyResponse extends HttpResponse { public boolean hasObject(); diff --git a/src/main/java/com/basho/riak/client/util/BranchableInputStream.java b/src/main/java/com/basho/riak/client/util/BranchableInputStream.java index c3df1c5c4..9cb78f83d 100644 --- a/src/main/java/com/basho/riak/client/util/BranchableInputStream.java +++ b/src/main/java/com/basho/riak/client/util/BranchableInputStream.java @@ -20,10 +20,19 @@ /** * An input stream that can be branched into other InputStreams, each * maintaining its own location, with the main read() method always returning - * bytes from the furthest advanced branch. + * bytes from the farthest advanced branch. * * @author jlee + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.BranchableInputStream + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.BranchableInputStream */ +@Deprecated public class BranchableInputStream extends InputStream { static final int DEFAULT_BASE_CHUNK_SIZE = 1024; diff --git a/src/main/java/com/basho/riak/client/util/ClientHelper.java b/src/main/java/com/basho/riak/client/util/ClientHelper.java index 9fb41a38f..bcec5130b 100644 --- a/src/main/java/com/basho/riak/client/util/ClientHelper.java +++ b/src/main/java/com/basho/riak/client/util/ClientHelper.java @@ -46,7 +46,16 @@ * This class performs the actual HTTP requests underlying the operations in * RiakClient and returns the resulting HTTP responses. It is up to RiakClient * to interpret the responses and translate them into the appropriate format. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.ClientHelper + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.ClientHelper */ +@Deprecated public class ClientHelper { private RiakConfig config; diff --git a/src/main/java/com/basho/riak/client/util/ClientUtils.java b/src/main/java/com/basho/riak/client/util/ClientUtils.java index 86da23a95..517c5b1e2 100644 --- a/src/main/java/com/basho/riak/client/util/ClientUtils.java +++ b/src/main/java/com/basho/riak/client/util/ClientUtils.java @@ -47,7 +47,16 @@ /** * Utility functions. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.ClientUtils + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.ClientUtils */ +@Deprecated public class ClientUtils { // Matches the scheme, host and port of a URL diff --git a/src/main/java/com/basho/riak/client/util/CollectionWrapper.java b/src/main/java/com/basho/riak/client/util/CollectionWrapper.java index ac8256c3f..d9f6d3b4c 100644 --- a/src/main/java/com/basho/riak/client/util/CollectionWrapper.java +++ b/src/main/java/com/basho/riak/client/util/CollectionWrapper.java @@ -5,6 +5,18 @@ import java.util.Iterator; import java.util.List; +/** + * @param + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.CollectionWrapper + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.CollectionWrapper + */ +@Deprecated public abstract class CollectionWrapper implements Collection { List cache = new ArrayList(); diff --git a/src/main/java/com/basho/riak/client/util/Constants.java b/src/main/java/com/basho/riak/client/util/Constants.java index 5547c5ccc..4582ff753 100644 --- a/src/main/java/com/basho/riak/client/util/Constants.java +++ b/src/main/java/com/basho/riak/client/util/Constants.java @@ -13,6 +13,16 @@ */ package com.basho.riak.client.util; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.Constants + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.Constants + */ +@Deprecated public interface Constants { // Default URL path prefixes Riak HTTP interface diff --git a/src/main/java/com/basho/riak/client/util/LinkHeader.java b/src/main/java/com/basho/riak/client/util/LinkHeader.java index b6c0a2ae0..ff3b7f671 100644 --- a/src/main/java/com/basho/riak/client/util/LinkHeader.java +++ b/src/main/java/com/basho/riak/client/util/LinkHeader.java @@ -32,7 +32,16 @@ * http://gist.github.com/210535 * * @author jlee + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.LinkHeader + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.LinkHeader */ +@Deprecated public class LinkHeader { private static String TOKEN = "(?:[^\\(\\)<>@,;:\\\\\"/\\[\\]\\?={} \\t]+?)"; diff --git a/src/main/java/com/basho/riak/client/util/Multipart.java b/src/main/java/com/basho/riak/client/util/Multipart.java index 029468364..2a7c52613 100644 --- a/src/main/java/com/basho/riak/client/util/Multipart.java +++ b/src/main/java/com/basho/riak/client/util/Multipart.java @@ -25,7 +25,16 @@ * Represents a multipart entity as described here: * * http://tools.ietf.org/html/rfc2046#section-5.1 + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.Multipart + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.Multipart */ +@Deprecated public class Multipart { private static byte[] HEADER_DELIM = "\r\n\r\n".getBytes(); diff --git a/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java b/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java index da2a0b39b..2b74f60ff 100644 --- a/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java +++ b/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java @@ -8,7 +8,16 @@ * containing contains a delimited list * * @author jlee + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.OneTokenInputStream + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.OneTokenInputStream */ +@Deprecated public class OneTokenInputStream extends InputStream { int maxBufferLen; diff --git a/src/main/java/com/basho/riak/client/util/StreamedMultipart.java b/src/main/java/com/basho/riak/client/util/StreamedMultipart.java index 39f2182a9..ba866d513 100644 --- a/src/main/java/com/basho/riak/client/util/StreamedMultipart.java +++ b/src/main/java/com/basho/riak/client/util/StreamedMultipart.java @@ -8,6 +8,16 @@ import com.basho.riak.client.util.Multipart.Part; +/** + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.util.StreamedMultipart + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ * @see com.basho.riak.client.http.util.StreamedMultipart + */ +@Deprecated public class StreamedMultipart implements Iterator { Map headers = null; diff --git a/src/main/java/com/basho/riak/pbc/RiakClient.java b/src/main/java/com/basho/riak/pbc/RiakClient.java index f7ba6b2f9..e79ae4dcd 100644 --- a/src/main/java/com/basho/riak/pbc/RiakClient.java +++ b/src/main/java/com/basho/riak/pbc/RiakClient.java @@ -32,7 +32,7 @@ import org.json.JSONObject; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.util.Constants; import com.basho.riak.pbc.RPB.RpbDelReq; import com.basho.riak.pbc.RPB.RpbGetClientIdResp; import com.basho.riak.pbc.RPB.RpbGetReq; diff --git a/src/test/java/com/basho/riak/client/Hosts.java b/src/test/java/com/basho/riak/client/http/Hosts.java similarity index 95% rename from src/test/java/com/basho/riak/client/Hosts.java rename to src/test/java/com/basho/riak/client/http/Hosts.java index 2ee540917..a6505e052 100644 --- a/src/test/java/com/basho/riak/client/Hosts.java +++ b/src/test/java/com/basho/riak/client/http/Hosts.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import java.util.regex.Pattern; diff --git a/src/test/java/com/basho/riak/client/TestRiakBucketInfo.java b/src/test/java/com/basho/riak/client/http/TestRiakBucketInfo.java similarity index 96% rename from src/test/java/com/basho/riak/client/TestRiakBucketInfo.java rename to src/test/java/com/basho/riak/client/http/TestRiakBucketInfo.java index 89bc92afd..681a8346d 100644 --- a/src/test/java/com/basho/riak/client/TestRiakBucketInfo.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakBucketInfo.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import static org.junit.Assert.*; @@ -22,7 +22,8 @@ import org.json.JSONObject; import org.junit.Test; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.util.Constants; public class TestRiakBucketInfo { diff --git a/src/test/java/com/basho/riak/client/TestRiakClient.java b/src/test/java/com/basho/riak/client/http/TestRiakClient.java similarity index 93% rename from src/test/java/com/basho/riak/client/TestRiakClient.java rename to src/test/java/com/basho/riak/client/http/TestRiakClient.java index 47e56a081..d960a7704 100644 --- a/src/test/java/com/basho/riak/client/TestRiakClient.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakClient.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import static org.junit.Assert.*; import static org.mockito.Matchers.*; @@ -30,15 +30,18 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.request.RiakWalkSpec; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.RiakResponseRuntimeException; -import com.basho.riak.client.response.StreamHandler; -import com.basho.riak.client.response.WalkResponse; -import com.basho.riak.client.util.ClientHelper; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StreamHandler; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.ClientHelper; +import com.basho.riak.client.http.util.Constants; public class TestRiakClient { diff --git a/src/test/java/com/basho/riak/client/TestRiakConfig.java b/src/test/java/com/basho/riak/client/http/TestRiakConfig.java similarity index 96% rename from src/test/java/com/basho/riak/client/TestRiakConfig.java rename to src/test/java/com/basho/riak/client/http/TestRiakConfig.java index 5516504d1..8adc2ac0c 100644 --- a/src/test/java/com/basho/riak/client/TestRiakConfig.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakConfig.java @@ -11,12 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import static org.junit.Assert.*; import org.junit.Test; +import com.basho.riak.client.http.RiakConfig; + public class TestRiakConfig { @Test public void chomps_ending_slash() { diff --git a/src/test/java/com/basho/riak/client/TestRiakLink.java b/src/test/java/com/basho/riak/client/http/TestRiakLink.java similarity index 95% rename from src/test/java/com/basho/riak/client/TestRiakLink.java rename to src/test/java/com/basho/riak/client/http/TestRiakLink.java index 498d70089..d5106ad14 100644 --- a/src/test/java/com/basho/riak/client/TestRiakLink.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakLink.java @@ -11,12 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import static org.junit.Assert.*; import org.junit.Test; +import com.basho.riak.client.http.RiakLink; + public class TestRiakLink { @Test public void constructor_args_persisted() { diff --git a/src/test/java/com/basho/riak/client/TestRiakObject.java b/src/test/java/com/basho/riak/client/http/TestRiakObject.java similarity index 98% rename from src/test/java/com/basho/riak/client/TestRiakObject.java rename to src/test/java/com/basho/riak/client/http/TestRiakObject.java index f042158bd..34b2f4086 100644 --- a/src/test/java/com/basho/riak/client/TestRiakObject.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakObject.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client; +package com.basho.riak.client.http; import static org.junit.Assert.*; import static org.mockito.Matchers.*; @@ -34,12 +34,15 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.StoreResponse; -import com.basho.riak.client.response.WalkResponse; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.Constants; public class TestRiakObject { diff --git a/src/test/java/com/basho/riak/client/itest/ITestBasic.java b/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java similarity index 89% rename from src/test/java/com/basho/riak/client/itest/ITestBasic.java rename to src/test/java/com/basho/riak/client/http/itest/ITestBasic.java index e6b53056c..19ce2e1b7 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBasic.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java @@ -11,34 +11,34 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; -import static com.basho.riak.client.Hosts.RIAK_URL; -import static com.basho.riak.client.itest.Utils.*; +import static com.basho.riak.client.http.Hosts.RIAK_URL; +import static com.basho.riak.client.http.itest.Utils.*; import static org.junit.Assert.*; import java.util.UUID; import org.junit.Test; -import com.basho.riak.client.RiakBucketInfo; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakLink; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.plain.PlainClient; -import com.basho.riak.client.plain.RiakIOException; -import com.basho.riak.client.plain.RiakResponseException; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.StoreResponse; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.plain.PlainClient; +import com.basho.riak.client.http.plain.RiakIOException; +import com.basho.riak.client.http.plain.RiakResponseException; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.util.Constants; /** * Basic exercises such as store, fetch, and modify objects for the Riak client. - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_URL }. - * @see com.basho.riak.client.Hosts#RIAK_URL + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. + * @see com.basho.riak.client.http.Hosts#RIAK_URL */ public class ITestBasic { diff --git a/src/test/java/com/basho/riak/client/itest/ITestDataLoad.java b/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java similarity index 90% rename from src/test/java/com/basho/riak/client/itest/ITestDataLoad.java rename to src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java index 55a8e6e6f..6ccdf5f94 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDataLoad.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java @@ -11,10 +11,10 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; -import static com.basho.riak.client.Hosts.RIAK_URL; +import static com.basho.riak.client.http.Hosts.RIAK_URL; import static org.junit.Assert.*; import java.util.Random; @@ -24,12 +24,12 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakObject; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; /** - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_URL }. - * @see com.basho.riak.client.Hosts#RIAK_URL + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. + * @see com.basho.riak.client.http.Hosts#RIAK_URL */ public class ITestDataLoad { diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/http/itest/ITestMapReduce.java similarity index 86% rename from src/test/java/com/basho/riak/client/itest/ITestMapReduce.java rename to src/test/java/com/basho/riak/client/http/itest/ITestMapReduce.java index e37273aa2..99f69468d 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestMapReduce.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; -import static com.basho.riak.client.Hosts.RIAK_URL; +import static com.basho.riak.client.http.Hosts.RIAK_URL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -28,21 +28,21 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakLink; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.mapreduce.ErlangFunction; -import com.basho.riak.client.mapreduce.JavascriptFunction; -import com.basho.riak.client.mapreduce.filter.LessThanFilter; -import com.basho.riak.client.mapreduce.filter.StringToIntFilter; -import com.basho.riak.client.mapreduce.filter.TokenizeFilter; -import com.basho.riak.client.request.MapReduceBuilder; -import com.basho.riak.client.response.MapReduceResponse; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.mapreduce.ErlangFunction; +import com.basho.riak.client.http.mapreduce.JavascriptFunction; +import com.basho.riak.client.http.mapreduce.filter.LessThanFilter; +import com.basho.riak.client.http.mapreduce.filter.StringToIntFilter; +import com.basho.riak.client.http.mapreduce.filter.TokenizeFilter; +import com.basho.riak.client.http.request.MapReduceBuilder; +import com.basho.riak.client.http.response.MapReduceResponse; /** * Exercises map/reduce features of the Riak client. - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_URL }. - * @see com.basho.riak.client.Hosts#RIAK_URL + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. + * @see com.basho.riak.client.http.Hosts#RIAK_URL */ public class ITestMapReduce { diff --git a/src/test/java/com/basho/riak/client/itest/ITestStreaming.java b/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java similarity index 88% rename from src/test/java/com/basho/riak/client/itest/ITestStreaming.java rename to src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java index 7fc63bfe8..c7e11d1ce 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestStreaming.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java @@ -11,10 +11,10 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; -import static com.basho.riak.client.Hosts.RIAK_URL; -import static com.basho.riak.client.itest.Utils.*; +import static com.basho.riak.client.http.Hosts.RIAK_URL; +import static com.basho.riak.client.http.itest.Utils.*; import static org.junit.Assert.*; import java.io.ByteArrayOutputStream; @@ -26,17 +26,17 @@ import org.junit.Test; -import com.basho.riak.client.RiakBucketInfo; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.util.ClientUtils; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; /** - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_URL }. - * @see com.basho.riak.client.Hosts#RIAK_URL + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. + * @see com.basho.riak.client.http.Hosts#RIAK_URL */ public class ITestStreaming { diff --git a/src/test/java/com/basho/riak/client/itest/ITestWalk.java b/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java similarity index 86% rename from src/test/java/com/basho/riak/client/itest/ITestWalk.java rename to src/test/java/com/basho/riak/client/http/itest/ITestWalk.java index 6be536576..5cf7d115d 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestWalk.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java @@ -11,10 +11,10 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; -import static com.basho.riak.client.Hosts.RIAK_URL; -import static com.basho.riak.client.itest.Utils.*; +import static com.basho.riak.client.http.Hosts.RIAK_URL; +import static com.basho.riak.client.http.itest.Utils.*; import static org.junit.Assert.*; import java.util.ArrayList; @@ -22,14 +22,14 @@ import org.junit.Test; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakLink; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.response.WalkResponse; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.response.WalkResponse; /** - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_URL }. - * @see com.basho.riak.client.Hosts#RIAK_URL + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. + * @see com.basho.riak.client.http.Hosts#RIAK_URL */ public class ITestWalk { diff --git a/src/test/java/com/basho/riak/client/itest/Utils.java b/src/test/java/com/basho/riak/client/http/itest/Utils.java similarity index 91% rename from src/test/java/com/basho/riak/client/itest/Utils.java rename to src/test/java/com/basho/riak/client/http/itest/Utils.java index 6df56b107..aed88b29b 100644 --- a/src/test/java/com/basho/riak/client/itest/Utils.java +++ b/src/test/java/com/basho/riak/client/http/itest/Utils.java @@ -11,14 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.itest; +package com.basho.riak.client.http.itest; import static org.junit.Assert.*; import org.apache.commons.httpclient.URIException; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.HttpResponse; public class Utils { diff --git a/src/test/java/com/basho/riak/client/mapreduce/TestMapReduceBuilder.java b/src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceBuilder.java similarity index 92% rename from src/test/java/com/basho/riak/client/mapreduce/TestMapReduceBuilder.java rename to src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceBuilder.java index 3d4c53aab..572e8e8ee 100644 --- a/src/test/java/com/basho/riak/client/mapreduce/TestMapReduceBuilder.java +++ b/src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceBuilder.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.mapreduce; +package com.basho.riak.client.http.mapreduce; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -28,32 +28,34 @@ import org.json.JSONObject; import org.junit.Test; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.mapreduce.filter.BetweenFilter; -import com.basho.riak.client.mapreduce.filter.EndsWithFilter; -import com.basho.riak.client.mapreduce.filter.EqualToFilter; -import com.basho.riak.client.mapreduce.filter.FloatToStringFilter; -import com.basho.riak.client.mapreduce.filter.GreaterThanFilter; -import com.basho.riak.client.mapreduce.filter.GreaterThanOrEqualFilter; -import com.basho.riak.client.mapreduce.filter.IntToStringFilter; -import com.basho.riak.client.mapreduce.filter.LessThanFilter; -import com.basho.riak.client.mapreduce.filter.LessThanOrEqualFilter; -import com.basho.riak.client.mapreduce.filter.LogicalAndFilter; -import com.basho.riak.client.mapreduce.filter.LogicalFilterGroup; -import com.basho.riak.client.mapreduce.filter.LogicalNotFilter; -import com.basho.riak.client.mapreduce.filter.LogicalOrFilter; -import com.basho.riak.client.mapreduce.filter.MatchFilter; -import com.basho.riak.client.mapreduce.filter.NotEqualToFilter; -import com.basho.riak.client.mapreduce.filter.SetMemberFilter; -import com.basho.riak.client.mapreduce.filter.SimilarToFilter; -import com.basho.riak.client.mapreduce.filter.StartsWithFilter; -import com.basho.riak.client.mapreduce.filter.StringToFloatFilter; -import com.basho.riak.client.mapreduce.filter.StringToIntFilter; -import com.basho.riak.client.mapreduce.filter.ToLowerFilter; -import com.basho.riak.client.mapreduce.filter.ToUpperFilter; -import com.basho.riak.client.mapreduce.filter.TokenizeFilter; -import com.basho.riak.client.mapreduce.filter.UrlDecodeFilter; -import com.basho.riak.client.request.MapReduceBuilder; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.mapreduce.ErlangFunction; +import com.basho.riak.client.http.mapreduce.JavascriptFunction; +import com.basho.riak.client.http.mapreduce.filter.BetweenFilter; +import com.basho.riak.client.http.mapreduce.filter.EndsWithFilter; +import com.basho.riak.client.http.mapreduce.filter.EqualToFilter; +import com.basho.riak.client.http.mapreduce.filter.FloatToStringFilter; +import com.basho.riak.client.http.mapreduce.filter.GreaterThanFilter; +import com.basho.riak.client.http.mapreduce.filter.GreaterThanOrEqualFilter; +import com.basho.riak.client.http.mapreduce.filter.IntToStringFilter; +import com.basho.riak.client.http.mapreduce.filter.LessThanFilter; +import com.basho.riak.client.http.mapreduce.filter.LessThanOrEqualFilter; +import com.basho.riak.client.http.mapreduce.filter.LogicalAndFilter; +import com.basho.riak.client.http.mapreduce.filter.LogicalFilterGroup; +import com.basho.riak.client.http.mapreduce.filter.LogicalNotFilter; +import com.basho.riak.client.http.mapreduce.filter.LogicalOrFilter; +import com.basho.riak.client.http.mapreduce.filter.MatchFilter; +import com.basho.riak.client.http.mapreduce.filter.NotEqualToFilter; +import com.basho.riak.client.http.mapreduce.filter.SetMemberFilter; +import com.basho.riak.client.http.mapreduce.filter.SimilarToFilter; +import com.basho.riak.client.http.mapreduce.filter.StartsWithFilter; +import com.basho.riak.client.http.mapreduce.filter.StringToFloatFilter; +import com.basho.riak.client.http.mapreduce.filter.StringToIntFilter; +import com.basho.riak.client.http.mapreduce.filter.ToLowerFilter; +import com.basho.riak.client.http.mapreduce.filter.ToUpperFilter; +import com.basho.riak.client.http.mapreduce.filter.TokenizeFilter; +import com.basho.riak.client.http.mapreduce.filter.UrlDecodeFilter; +import com.basho.riak.client.http.request.MapReduceBuilder; import com.basho.riak.test.util.JSONEquals; public class TestMapReduceBuilder { diff --git a/src/test/java/com/basho/riak/client/mapreduce/TestMapReduceFunctions.java b/src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceFunctions.java similarity index 92% rename from src/test/java/com/basho/riak/client/mapreduce/TestMapReduceFunctions.java rename to src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceFunctions.java index 455e46d08..82b5beeb7 100644 --- a/src/test/java/com/basho/riak/client/mapreduce/TestMapReduceFunctions.java +++ b/src/test/java/com/basho/riak/client/http/mapreduce/TestMapReduceFunctions.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.mapreduce; +package com.basho.riak.client.http.mapreduce; import static org.junit.Assert.assertEquals; @@ -19,6 +19,9 @@ import org.json.JSONObject; import org.junit.Test; +import com.basho.riak.client.http.mapreduce.ErlangFunction; +import com.basho.riak.client.http.mapreduce.JavascriptFunction; + public class TestMapReduceFunctions { @Test public void erlangFunction_generatesCorrectJson() throws JSONException { diff --git a/src/test/java/com/basho/riak/client/plain/TestConvertToCheckedExceptions.java b/src/test/java/com/basho/riak/client/http/plain/TestConvertToCheckedExceptions.java similarity index 75% rename from src/test/java/com/basho/riak/client/plain/TestConvertToCheckedExceptions.java rename to src/test/java/com/basho/riak/client/http/plain/TestConvertToCheckedExceptions.java index 71744eeb1..49b457c83 100644 --- a/src/test/java/com/basho/riak/client/plain/TestConvertToCheckedExceptions.java +++ b/src/test/java/com/basho/riak/client/http/plain/TestConvertToCheckedExceptions.java @@ -11,12 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.plain; +package com.basho.riak.client.http.plain; import org.junit.Test; -import com.basho.riak.client.response.RiakIORuntimeException; -import com.basho.riak.client.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.plain.ConvertToCheckedExceptions; +import com.basho.riak.client.http.plain.RiakIOException; +import com.basho.riak.client.http.plain.RiakResponseException; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; public class TestConvertToCheckedExceptions { diff --git a/src/test/java/com/basho/riak/client/plain/TestPlainClient.java b/src/test/java/com/basho/riak/client/http/plain/TestPlainClient.java similarity index 95% rename from src/test/java/com/basho/riak/client/plain/TestPlainClient.java rename to src/test/java/com/basho/riak/client/http/plain/TestPlainClient.java index 56bad1aea..6ff79d0cd 100644 --- a/src/test/java/com/basho/riak/client/plain/TestPlainClient.java +++ b/src/test/java/com/basho/riak/client/http/plain/TestPlainClient.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.plain; +package com.basho.riak.client.http.plain; import java.io.IOException; import java.util.ArrayList; @@ -28,16 +28,20 @@ import static org.mockito.Mockito.*; import static org.junit.Assert.*; -import com.basho.riak.client.RiakBucketInfo; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.StoreResponse; -import com.basho.riak.client.response.StreamHandler; -import com.basho.riak.client.response.WalkResponse; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.plain.ConvertToCheckedExceptions; +import com.basho.riak.client.http.plain.PlainClient; +import com.basho.riak.client.http.plain.RiakIOException; +import com.basho.riak.client.http.plain.RiakResponseException; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.StreamHandler; +import com.basho.riak.client.http.response.WalkResponse; public class TestPlainClient { diff --git a/src/test/java/com/basho/riak/client/request/TestRequestMeta.java b/src/test/java/com/basho/riak/client/http/request/TestRequestMeta.java similarity index 97% rename from src/test/java/com/basho/riak/client/request/TestRequestMeta.java rename to src/test/java/com/basho/riak/client/http/request/TestRequestMeta.java index bd5482dbb..220f5dd36 100644 --- a/src/test/java/com/basho/riak/client/request/TestRequestMeta.java +++ b/src/test/java/com/basho/riak/client/http/request/TestRequestMeta.java @@ -11,12 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.request; +package com.basho.riak.client.http.request; import static org.junit.Assert.*; import org.junit.Test; +import com.basho.riak.client.http.request.RequestMeta; + public class TestRequestMeta { @Test public void readParams_sets_r_query_parameter() { diff --git a/src/test/java/com/basho/riak/client/response/TestBucketResponse.java b/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java similarity index 97% rename from src/test/java/com/basho/riak/client/response/TestBucketResponse.java rename to src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java index 82b8b05e2..9fba524b5 100644 --- a/src/test/java/com/basho/riak/client/response/TestBucketResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -25,6 +25,9 @@ import org.json.JSONException; import org.junit.Test; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.HttpResponse; + public class TestBucketResponse { final String TEXT_BODY = diff --git a/src/test/java/com/basho/riak/client/response/TestDefaultHttpResponse.java b/src/test/java/com/basho/riak/client/http/response/TestDefaultHttpResponse.java similarity index 97% rename from src/test/java/com/basho/riak/client/response/TestDefaultHttpResponse.java rename to src/test/java/com/basho/riak/client/http/response/TestDefaultHttpResponse.java index 06d6cb79d..191f68a84 100644 --- a/src/test/java/com/basho/riak/client/response/TestDefaultHttpResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestDefaultHttpResponse.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.mockito.Mockito.*; import static org.junit.Assert.*; @@ -22,6 +22,8 @@ import org.apache.commons.httpclient.methods.HeadMethod; import org.junit.Test; +import com.basho.riak.client.http.response.DefaultHttpResponse; + public class TestDefaultHttpResponse { DefaultHttpResponse impl; diff --git a/src/test/java/com/basho/riak/client/response/TestFetchResponse.java b/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java similarity index 96% rename from src/test/java/com/basho/riak/client/response/TestFetchResponse.java rename to src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java index 31e419dd5..cc1dd07cc 100644 --- a/src/test/java/com/basho/riak/client/response/TestFetchResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -31,10 +31,13 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.util.ClientUtils; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.StreamedSiblingsCollection; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; public class TestFetchResponse { diff --git a/src/test/java/com/basho/riak/client/response/TestHttpResponseDecorator.java b/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java similarity index 94% rename from src/test/java/com/basho/riak/client/response/TestHttpResponseDecorator.java rename to src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java index 341acf58a..e04dc11f4 100644 --- a/src/test/java/com/basho/riak/client/response/TestHttpResponseDecorator.java +++ b/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -23,6 +23,9 @@ import org.json.JSONException; import org.junit.Test; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.HttpResponseDecorator; + public class TestHttpResponseDecorator { @Test public void delegates_http_response_methods_to_impl() throws JSONException { diff --git a/src/test/java/com/basho/riak/client/response/TestStoreResponse.java b/src/test/java/com/basho/riak/client/http/response/TestStoreResponse.java similarity index 93% rename from src/test/java/com/basho/riak/client/response/TestStoreResponse.java rename to src/test/java/com/basho/riak/client/http/response/TestStoreResponse.java index 2d8be5bcd..35df6de06 100644 --- a/src/test/java/com/basho/riak/client/response/TestStoreResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestStoreResponse.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -22,6 +22,9 @@ import org.json.JSONException; import org.junit.Test; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.StoreResponse; + public class TestStoreResponse { @Test public void doesnt_throw_on_null_impl() throws JSONException { diff --git a/src/test/java/com/basho/riak/client/response/TestStreamedKeysCollection.java b/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java similarity index 97% rename from src/test/java/com/basho/riak/client/response/TestStreamedKeysCollection.java rename to src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java index 226c3dc0e..a494a3769 100644 --- a/src/test/java/com/basho/riak/client/response/TestStreamedKeysCollection.java +++ b/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; @@ -23,6 +23,8 @@ import org.json.JSONTokener; import org.junit.Test; +import com.basho.riak.client.http.response.StreamedKeysCollection; + public class TestStreamedKeysCollection { StreamedKeysCollection impl; diff --git a/src/test/java/com/basho/riak/client/response/TestStreamedSiblingsCollection.java b/src/test/java/com/basho/riak/client/http/response/TestStreamedSiblingsCollection.java similarity index 91% rename from src/test/java/com/basho/riak/client/response/TestStreamedSiblingsCollection.java rename to src/test/java/com/basho/riak/client/http/response/TestStreamedSiblingsCollection.java index aebb2b82b..cddcd6b0d 100644 --- a/src/test/java/com/basho/riak/client/response/TestStreamedSiblingsCollection.java +++ b/src/test/java/com/basho/riak/client/http/response/TestStreamedSiblingsCollection.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -26,11 +26,13 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakLink; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.util.Multipart; -import com.basho.riak.client.util.StreamedMultipart; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.StreamedSiblingsCollection; +import com.basho.riak.client.http.util.Multipart; +import com.basho.riak.client.http.util.StreamedMultipart; public class TestStreamedSiblingsCollection { diff --git a/src/test/java/com/basho/riak/client/response/TestWalkResponse.java b/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java similarity index 94% rename from src/test/java/com/basho/riak/client/response/TestWalkResponse.java rename to src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java index aeb4ee60b..2fb311b11 100644 --- a/src/test/java/com/basho/riak/client/response/TestWalkResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.response; +package com.basho.riak.client.http.response; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -25,9 +25,10 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.WalkResponse; public class TestWalkResponse { diff --git a/src/test/java/com/basho/riak/client/util/TestBranchableInputStream.java b/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java similarity index 95% rename from src/test/java/com/basho/riak/client/util/TestBranchableInputStream.java rename to src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java index 472db940b..ed1075049 100644 --- a/src/test/java/com/basho/riak/client/util/TestBranchableInputStream.java +++ b/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; @@ -23,8 +23,10 @@ import org.junit.Test; -import com.basho.riak.client.util.BranchableInputStream.InputStreamBranch; -import com.basho.riak.client.util.BranchableInputStream.LinkedChunk; +import com.basho.riak.client.http.util.BranchableInputStream; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.BranchableInputStream.InputStreamBranch; +import com.basho.riak.client.http.util.BranchableInputStream.LinkedChunk; public class TestBranchableInputStream { diff --git a/src/test/java/com/basho/riak/client/util/TestClientHelper.java b/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java similarity index 95% rename from src/test/java/com/basho/riak/client/util/TestClientHelper.java rename to src/test/java/com/basho/riak/client/http/util/TestClientHelper.java index 188ea34e5..67f219dde 100644 --- a/src/test/java/com/basho/riak/client/util/TestClientHelper.java +++ b/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; import static org.mockito.Matchers.*; @@ -36,14 +36,17 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.basho.riak.client.RiakConfig; -import com.basho.riak.client.RiakObject; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.RiakExceptionHandler; -import com.basho.riak.client.response.RiakIORuntimeException; -import com.basho.riak.client.response.RiakResponseRuntimeException; -import com.basho.riak.client.response.StreamHandler; +import com.basho.riak.client.http.RiakConfig; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.RiakExceptionHandler; +import com.basho.riak.client.http.response.RiakIORuntimeException; +import com.basho.riak.client.http.response.RiakResponseRuntimeException; +import com.basho.riak.client.http.response.StreamHandler; +import com.basho.riak.client.http.util.ClientHelper; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.Constants; public class TestClientHelper { diff --git a/src/test/java/com/basho/riak/client/util/TestClientUtils.java b/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java similarity index 98% rename from src/test/java/com/basho/riak/client/util/TestClientUtils.java rename to src/test/java/com/basho/riak/client/http/util/TestClientUtils.java index b84fd8405..d64bc395b 100644 --- a/src/test/java/com/basho/riak/client/util/TestClientUtils.java +++ b/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -33,10 +33,11 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import com.basho.riak.client.RiakClient; -import com.basho.riak.client.RiakConfig; -import com.basho.riak.client.RiakLink; -import com.basho.riak.client.RiakObject; +import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakConfig; +import com.basho.riak.client.http.RiakLink; +import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.http.util.ClientUtils; public class TestClientUtils { diff --git a/src/test/java/com/basho/riak/client/util/TestCollectionWrapper.java b/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java similarity index 95% rename from src/test/java/com/basho/riak/client/util/TestCollectionWrapper.java rename to src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java index b540d2827..6447ddc29 100644 --- a/src/test/java/com/basho/riak/client/util/TestCollectionWrapper.java +++ b/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -24,6 +24,8 @@ import org.junit.Before; import org.junit.Test; +import com.basho.riak.client.http.util.CollectionWrapper; + public class TestCollectionWrapper { final static int MAX_ELS = 10; diff --git a/src/test/java/com/basho/riak/client/util/TestLinkHeader.java b/src/test/java/com/basho/riak/client/http/util/TestLinkHeader.java similarity index 98% rename from src/test/java/com/basho/riak/client/util/TestLinkHeader.java rename to src/test/java/com/basho/riak/client/http/util/TestLinkHeader.java index ec7e5dfed..f34e9c2c5 100644 --- a/src/test/java/com/basho/riak/client/util/TestLinkHeader.java +++ b/src/test/java/com/basho/riak/client/http/util/TestLinkHeader.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; @@ -19,6 +19,8 @@ import org.junit.Test; +import com.basho.riak.client.http.util.LinkHeader; + public class TestLinkHeader { @Test public void parses_null_and_empty_headers() { diff --git a/src/test/java/com/basho/riak/client/util/TestMultipart.java b/src/test/java/com/basho/riak/client/http/util/TestMultipart.java similarity index 98% rename from src/test/java/com/basho/riak/client/util/TestMultipart.java rename to src/test/java/com/basho/riak/client/http/util/TestMultipart.java index fd36dbf3d..13979a82a 100644 --- a/src/test/java/com/basho/riak/client/util/TestMultipart.java +++ b/src/test/java/com/basho/riak/client/http/util/TestMultipart.java @@ -11,10 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import org.junit.Test; +import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.http.util.Multipart; + import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/test/java/com/basho/riak/client/util/TestOneTokenInputStream.java b/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java similarity index 94% rename from src/test/java/com/basho/riak/client/util/TestOneTokenInputStream.java rename to src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java index 018cda3b4..c6ae8f10b 100644 --- a/src/test/java/com/basho/riak/client/util/TestOneTokenInputStream.java +++ b/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; @@ -21,6 +21,9 @@ import org.junit.Test; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.OneTokenInputStream; + public class TestOneTokenInputStream { OneTokenInputStream impl; diff --git a/src/test/java/com/basho/riak/client/util/TestStreamedMultipart.java b/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java similarity index 96% rename from src/test/java/com/basho/riak/client/util/TestStreamedMultipart.java rename to src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java index a13c20009..7e7e548ad 100644 --- a/src/test/java/com/basho/riak/client/util/TestStreamedMultipart.java +++ b/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.client.util; +package com.basho.riak.client.http.util; import static org.junit.Assert.*; @@ -25,7 +25,9 @@ import org.junit.Test; -import com.basho.riak.client.util.Multipart.Part; +import com.basho.riak.client.http.util.ClientUtils; +import com.basho.riak.client.http.util.StreamedMultipart; +import com.basho.riak.client.http.util.Multipart.Part; public class TestStreamedMultipart { diff --git a/src/test/java/com/basho/riak/pbc/itest/ITestBasic.java b/src/test/java/com/basho/riak/pbc/itest/ITestBasic.java index d2bdac1f7..ad89021ba 100644 --- a/src/test/java/com/basho/riak/pbc/itest/ITestBasic.java +++ b/src/test/java/com/basho/riak/pbc/itest/ITestBasic.java @@ -13,8 +13,8 @@ */ package com.basho.riak.pbc.itest; -import static com.basho.riak.client.Hosts.RIAK_HOST; -import static com.basho.riak.client.Hosts.RIAK_PORT; +import static com.basho.riak.client.http.Hosts.RIAK_HOST; +import static com.basho.riak.client.http.Hosts.RIAK_PORT; import static com.google.protobuf.ByteString.copyFromUtf8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -28,16 +28,16 @@ import org.junit.Test; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.util.Constants; import com.basho.riak.pbc.BucketProperties; import com.basho.riak.pbc.RiakClient; import com.basho.riak.pbc.RiakObject; import com.google.protobuf.ByteString; /** - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_HOST }. + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_HOST }. * @author russell - * @see com.basho.riak.client.Hosts#RIAK_HOST + * @see com.basho.riak.client.http.Hosts#RIAK_HOST */ public class ITestBasic { diff --git a/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java b/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java index 66f4fb0a8..5827dac77 100644 --- a/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java +++ b/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java @@ -13,8 +13,8 @@ */ package com.basho.riak.pbc.itest; -import static com.basho.riak.client.Hosts.RIAK_HOST; -import static com.basho.riak.client.Hosts.RIAK_PORT; +import static com.basho.riak.client.http.Hosts.RIAK_HOST; +import static com.basho.riak.client.http.Hosts.RIAK_PORT; import static com.google.protobuf.ByteString.copyFrom; import static com.google.protobuf.ByteString.copyFromUtf8; import static org.junit.Assert.assertEquals; @@ -37,8 +37,8 @@ import com.google.protobuf.ByteString; /** - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_HOST }. - * @see com.basho.riak.client.Hosts#RIAK_HOST + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_HOST }. + * @see com.basho.riak.client.http.Hosts#RIAK_HOST */ public class ITestDataLoad { diff --git a/src/test/java/com/basho/riak/pbc/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/pbc/itest/ITestMapReduce.java index 8fcd2afce..679fbb44d 100644 --- a/src/test/java/com/basho/riak/pbc/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/pbc/itest/ITestMapReduce.java @@ -13,8 +13,8 @@ */ package com.basho.riak.pbc.itest; -import static com.basho.riak.client.Hosts.RIAK_HOST; -import static com.basho.riak.client.Hosts.RIAK_PORT; +import static com.basho.riak.client.http.Hosts.RIAK_HOST; +import static com.basho.riak.client.http.Hosts.RIAK_PORT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -38,8 +38,8 @@ /** * Exercises map/reduce features of the Riak client. - * Assumes Riak is reachable at {@link com.basho.riak.client.Hosts#RIAK_HOST }. - * @see com.basho.riak.client.Hosts#RIAK_HOST + * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_HOST }. + * @see com.basho.riak.client.http.Hosts#RIAK_HOST */ public class ITestMapReduce { diff --git a/src/test/java/com/basho/riak/pbc/itest/Utils.java b/src/test/java/com/basho/riak/pbc/itest/Utils.java index b65828ad6..cdf8dc7e9 100644 --- a/src/test/java/com/basho/riak/pbc/itest/Utils.java +++ b/src/test/java/com/basho/riak/pbc/itest/Utils.java @@ -17,8 +17,8 @@ import org.apache.commons.httpclient.URIException; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.HttpResponse; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.HttpResponse; public class Utils { diff --git a/src/test/java/com/basho/riak/test/util/ExpectedValues.java b/src/test/java/com/basho/riak/test/util/ExpectedValues.java index ec155e98f..d9b1d7e97 100644 --- a/src/test/java/com/basho/riak/test/util/ExpectedValues.java +++ b/src/test/java/com/basho/riak/test/util/ExpectedValues.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.util.Constants; import com.basho.riak.pbc.RPB.RpbLink; import com.basho.riak.pbc.RPB.RpbPair; import com.google.protobuf.ByteString; From d3680115d094a4062f3814999a5f3509d83ec049 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 3 May 2011 15:17:24 +0100 Subject: [PATCH 020/764] Remove temporary, redundant interfaces --- .../com/basho/riak/client/HttpRiakClient.java | 381 ------------------ .../com/basho/riak/client/HttpRiakObject.java | 381 ------------------ 2 files changed, 762 deletions(-) delete mode 100644 src/main/java/com/basho/riak/client/HttpRiakClient.java delete mode 100644 src/main/java/com/basho/riak/client/HttpRiakObject.java diff --git a/src/main/java/com/basho/riak/client/HttpRiakClient.java b/src/main/java/com/basho/riak/client/HttpRiakClient.java deleted file mode 100644 index e1e03b33a..000000000 --- a/src/main/java/com/basho/riak/client/HttpRiakClient.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.httpclient.HttpClient; - -import com.basho.riak.client.request.MapReduceBuilder; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.request.RiakWalkSpec; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.MapReduceResponse; -import com.basho.riak.client.response.RiakExceptionHandler; -import com.basho.riak.client.response.RiakIORuntimeException; -import com.basho.riak.client.response.RiakResponseRuntimeException; -import com.basho.riak.client.response.StoreResponse; -import com.basho.riak.client.response.StreamHandler; -import com.basho.riak.client.response.WalkResponse; -import com.basho.riak.client.util.ClientUtils; - -/** - * @author russell - * - * @deprecated with the addition of a protocol buffers client in 0.14 all the - * existing REST client code should be in client.http.* this class - * has therefore been moved. Please use - * com.basho.riak.client.http.HttpRiakClient - * instead. - *

WARNING: This class will be REMOVED in the next version.

- * @see com.basho.riak.client.http.HttpRiakClient - */ -@Deprecated -public interface HttpRiakClient { - - RiakConfig getConfig(); - - /** - * Set the properties for a Riak bucket. - * - * @param bucket - * The bucket name. - * @param bucketInfo - * Contains the schema to use for the bucket. Refer to the Riak - * documentation for a list of the recognized properties and the - * format of their values. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link HttpResponse} containing HTTP response information. - * - * @throws IllegalArgumentException - * If the provided schema values cannot be serialized to send to - * Riak. - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - */ - HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta); - - HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo); - - /** - * Return the properties for a Riak bucket without listing the keys in it. - * - * @param bucket - * The target bucket. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link BucketResponse} containing HTTP response information and - * the parsed schema - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - BucketResponse getBucketSchema(String bucket, RequestMeta meta); - - BucketResponse getBucketSchema(String bucket); - - /** - * Return the properties and keys for a Riak bucket. - * - * @param bucket - * The bucket to list. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link BucketResponse} containing HTTP response information and - * the parsed schema and keys - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - BucketResponse listBucket(String bucket, RequestMeta meta); - - BucketResponse listBucket(String bucket); - - /** - * Same as {@link RiakClient#listBucket(String, RequestMeta)}, except - * streams the response, so the user must remember to call - * {@link BucketResponse#close()} on the return value. - */ - BucketResponse streamBucket(String bucket, RequestMeta meta); - - BucketResponse streamBucket(String bucket); - - /** - * Store a {@link RiakObject}. - * - * @param object - * The {@link RiakObject} to store. - * @param meta - * Extra metadata to attach to the request such as w and dw - * values for the request, HTTP headers, and other query - * parameters. See - * {@link RequestMeta#writeParams(Integer, Integer)}. - * - * @return A {@link StoreResponse} containing HTTP response information and - * any updated information returned by the server such as the - * vclock, last modified date. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - StoreResponse store(RiakObject object, RequestMeta meta); - - StoreResponse store(RiakObject object); - - /** - * Fetch metadata (e.g. vclock, last modified, vtag) for the - * {@link RiakObject} stored at bucket and key. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * {@link RequestMeta#readParams(int)}. - * - * @return {@link FetchResponse} containing HTTP response information and a - * {@link RiakObject} containing only metadata and no value. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - FetchResponse fetchMeta(String bucket, String key, RequestMeta meta); - - FetchResponse fetchMeta(String bucket, String key); - - /** - * Fetch the {@link RiakObject} (which can include sibling objects) stored - * at bucket and key. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * {@link RequestMeta#readParams(int)}. - * - * @return {@link FetchResponse} containing HTTP response information and a - * {@link RiakObject} or sibling objects. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - FetchResponse fetch(String bucket, String key, RequestMeta meta); - - FetchResponse fetch(String bucket, String key); - - /** - * Similar to fetch(), except the HTTP connection is left open for - * successful responses, and the Riak response is provided as a stream. - * The user must remember to call {@link FetchResponse#close()} on the - * return value. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * RequestMeta.readParams(). - * - * @return A streaming {@link FetchResponse} containing HTTP response - * information and the response stream. The HTTP connection must be - * closed manually by the user by calling - * {@link FetchResponse#close()}. - */ - FetchResponse stream(String bucket, String key, RequestMeta meta); - - FetchResponse stream(String bucket, String key); - - /** - * Fetch and process the object stored at bucket and - * key as a stream. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param handler - * A {@link StreamHandler} to process the Riak response. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * RequestMeta.readParams(). - * - * @return Result from calling handler.process() or true if handler is null. - * - * @throws IOException - * If an error occurs during communication with the Riak server. - * - * @see StreamHandler - */ - boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException; - - /** - * Delete the object at bucket and key. - * - * @param bucket - * The bucket containing the object. - * @param key - * The key of the object - * @param meta - * Extra metadata to attach to the request such as w and dw - * values for the request, HTTP headers, and other query - * parameters. See - * {@link RequestMeta#writeParams(Integer, Integer)}. - * - * @return {@link HttpResponse} containing HTTP response information. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - */ - HttpResponse delete(String bucket, String key, RequestMeta meta); - - HttpResponse delete(String bucket, String key); - - /** - * Perform a map/reduce link walking operation and return the objects for - * which the "accumulate" flag is true. - * - * @param bucket - * The bucket of the "starting object" - * @param key - * The key of the "starting object" - * @param walkSpec - * A URL-path (omit beginning /) of the form - * bucket,tag-spec,accumulateFlag The - * tag-spec "_" matches all tags. - * accumulateFlag is either the String "1" or "0". - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * or query parameters. - * - * @return {@link WalkResponse} containing HTTP response information and a - * List of Lists, where each sub-list - * corresponds to a walkSpec element that had - * accumulateFlag equal to 1. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - * - * @see RiakWalkSpec - */ - WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta); - - WalkResponse walk(String bucket, String key, String walkSpec); - - WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec); - - /** - * Execute a map reduce job on the Riak server. - * - * @param job - * JSON string representing the map reduce job to run, which can - * be created using {@link MapReduceBuilder} - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * or query parameters. - * - * @return {@link MapReduceResponse} containing HTTP response information - * and the result of the map reduce job - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server does not return a valid JSON array. - */ - MapReduceResponse mapReduce(String job, RequestMeta meta); - - MapReduceResponse mapReduce(String job); - - /** - * A convenience method for creating a MapReduceBuilder used for building a - * map reduce job to submission to this client - * - * @param bucket - * The bucket to perform the map reduce job over - * @return A {@link MapReduceBuilder} to build the map reduce job - */ - MapReduceBuilder mapReduceOverBucket(String bucket); - - /** - * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a set - * of objects instead of a bucket. - * - * @param objects - * A set of objects represented as a map of { bucket : [ list of - * keys in bucket ] } - */ - MapReduceBuilder mapReduceOverObjects(Map> objects); - - /** - * The installed exception handler or null if not installed - */ - RiakExceptionHandler getExceptionHandler(); - - /** - * If an exception handler is provided, then the Riak client will hand - * exceptions to the handler rather than throwing them. - * {@link ClientUtils#throwChecked(Throwable)} can be used to throw - * undeclared checked exceptions to effectively "convert" RiakClient's - * unchecked exceptions to checked exceptions. - */ - void setExceptionHandler(RiakExceptionHandler exceptionHandler); - - /** - * Return the {@link HttpClient} used to make requests, which can be - * configured. - */ - HttpClient getHttpClient(); - - /** - * A 4-byte unique ID for this client. The ID is base 64 encoded and sent to - * Riak to generating the object vclock on store operations. Refer to the - * Riak documentation and - * http://lists.basho.com/pipermail/riak-users_lists.basho.com/2009- - * November/000153.html for information about the client ID. - */ - byte[] getClientId(); - - void setClientId(String clientId); - -} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/HttpRiakObject.java b/src/main/java/com/basho/riak/client/HttpRiakObject.java deleted file mode 100644 index afe33a5ba..000000000 --- a/src/main/java/com/basho/riak/client/HttpRiakObject.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * This file is provided 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.basho.riak.client; - -import java.io.InputStream; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.commons.httpclient.HttpMethod; - -import com.basho.riak.client.RiakObject.LinkBuilder; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.request.RiakWalkSpec; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.StoreResponse; - -/** - * @author russell - * - * @deprecated with the addition of a protocol buffers client in 0.14 all the - * existing REST client code should be in client.http.* this class - * has therefore been moved. Please use - * com.basho.riak.client.http.HttpRiakObject - * instead. - *

WARNING: This class will be REMOVED in the next version.

- * @see com.basho.riak.client.http.HttpRiakObject - */ -@Deprecated -public interface HttpRiakObject { - - /** - * A {@link RiakObject} can be loosely attached to the {@link RiakClient} - * from which retrieve it was retrieved. Calling convenience methods like - * {@link RiakObject#store()} will store this object use that client. - */ - RiakClient getRiakClient(); - - RiakObject setRiakClient(RiakClient client); - - /** - * Copy the metadata and value from object. The bucket and key - * are not copied. - * - * @param object - * The source object to copy from - */ - void copyData(RiakObject object); - - /** - * Update the object's metadata. This usually happens when Riak returns - * updated metadata from a store operation. - * - * @param response - * Response from a store operation containing an updated vclock, - * last modified date, and vtag - */ - void updateMeta(StoreResponse response); - - /** - * Update the object's metadata from a fetch or fetchMeta operation - * - * @param response - * Response from a fetch or fetchMeta operation containing a - * vclock, last modified date, and vtag - */ - void updateMeta(FetchResponse response); - - /** - * The object's bucket - */ - String getBucket(); - - /** - * The object's key - */ - String getKey(); - - /** - * The object's value - */ - String getValue(); - - byte[] getValueAsBytes(); - - void setValue(String value); - - void setValue(byte[] value); - - /** - * Set the object's value as a stream. A value set here is independent of - * and has precedent over any value set using setValue(): - * {@link RiakObject#writeToHttpMethod(HttpMethod)} will always write the - * value from getValueStream() if it is not null. Calling getValue() will - * always return values set via setValue(), and calling getValueStream() - * will always return the stream set via setValueStream. - * - * @param in - * Input stream representing the object's value - * @param len - * Length of the InputStream or null if unknown. If null, the - * value will be buffered in memory to determine its size before - * sending to the server. - */ - void setValueStream(InputStream in, Long len); - - void setValueStream(InputStream in); - - InputStream getValueStream(); - - void setValueStreamLength(Long len); - - Long getValueStreamLength(); - - /** - * The object's links -- may be empty, but never be null. - * - * @see {@link RiakObject#addLink()}, {@link RiakObject#removeLink()}, {@link RiakObject#iterator()}, {@link RiakObject#hasLinks()} and , {@link RiakObject#numLinks()} - * - * @return the list of {@link RiakLink}s for this - * RiakObject - * @deprecated please use {@link RiakObject#iterableLinks())} to iterate over the - * collection of {@link RiakLink}s. Attempting to mutate the - * collection will result in UnsupportedOperationException in - * future versions. Use {@link RiakObject#addLink()} and {@link RiakObject#removeLink()} instead. - * Use {@link RiakObject#hasLinks()}, {@link RiakObject#numLinks()} and {@link RiakObject#hasLink(RiakLink)} - * to query state of links. - */ - @Deprecated List getLinks(); - - /** - * Makes a *deep* copy of links. - * - * Changes made to the original collection and its contents will not be reflected - * in this RiakObject's links. Use {@link RiakObject#addLink(RiakLink)}, - * {@link RiakObject#removeLink(RiakLink)} and {@link RiakObject#setLinks(List)} to alter the collection. - * @param links a List of {@link RiakLink} - */ - void setLinks(List links); - - /** - * Add link to this RiakObject's links. - * @param link a {@link RiakLink} to add. - * @return this RiakObject. - */ - RiakObject addLink(RiakLink link); - - /** - * Remove a {@link RiakLink} from this RiakObject. - * @param link the {@link RiakLink} to remove - * @return this RiakObject - */ - RiakObject removeLink(final RiakLink link); - - /** - * Does this RiakObject have any {@link RiakLink}s? - * @return true if there are links, false otherwise - */ - boolean hasLinks(); - - /** - * How many {@link RiakLink}s does this RiakObject have? - * @return the number of {@link RiakLink}s this object has. - */ - int numLinks(); - - /** - * Checks if the collection of RiakLinks contains the one passed in. - * @param riakLink a RiakLink - * @return true if the RiakObject's link collection contains riakLink. - */ - boolean hasLink(final RiakLink riakLink); - - /** - * User-specified metadata for the object in the form of key-value pairs -- - * may be empty, but never be null. New key-value pairs can be added using - * addUsermeta() - * - * @deprecated Future versions will return an unmodifiable view of the user meta. Please use - * {@link RiakObject#addUsermeta(String, String)}, - * {@link RiakObject#removeUsermetaItem(String)}, - * {@link RiakObject#setUsermeta(Map)}, - * {@link RiakObject#hasUsermetaItem(String)}, - * {@link RiakObject#hasUsermeta()} and - * {@link RiakObject#getUsermetaItem(String)} to mutate and query the User meta collection - */ - @Deprecated Map getUsermeta(); - - /** - * Creates a copy of userMetaData. Changes made to the original collection will not be - * reflected in the RiakObject's state. - * @param userMetaData - */ - void setUsermeta(final Map userMetaData); - - /** - * Adds the key, value to the collection of user meta for this object. - * @param key - * @param value - * @return this RiakObject. - */ - RiakObject addUsermetaItem(String key, String value); - - /** - * @return true if there are any user meta data set on this RiakObject. - */ - boolean hasUsermeta(); - - /** - * @return how many user meta data items this RiakObject has. - */ - int numUsermetaItems(); - - /** - * @param key - * @return - */ - boolean hasUsermetaItem(String key); - - /** - * Get an item of user meta data. - * @param key the user meta data item key - * @return The value for the given key or null. - */ - String getUsermetaItem(String key); - - /** - * @param key the key of the item to remove - */ - void removeUsermetaItem(String key); - - Iterable usermetaKeys(); - - /** - * The object's content type as a MIME type - */ - String getContentType(); - - void setContentType(String contentType); - - /** - * The object's opaque vclock assigned by Riak - */ - String getVclock(); - - /** - * The modification date of the object determined by Riak - */ - String getLastmod(); - - /** - * Convenience method to get the last modified header parsed into a Date - * object. Returns null if header is null, malformed, or cannot be parsed. - */ - Date getLastmodAsDate(); - - /** - * An entity tag for the object assigned by Riak - */ - String getVtag(); - - /** - * Convenience method for calling - * {@link RiakClient#store(RiakObject, RequestMeta)} followed by - * {@link RiakObject#updateMeta(StoreResponse)} - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to store it with. - */ - StoreResponse store(RequestMeta meta); - - StoreResponse store(); - - /** - * Store this object to a different Riak instance. - * - * @param riak - * Riak instance to store this object to - * @param meta - * Same as {@link RiakClient#store(RiakObject, RequestMeta)} - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to store it with. - */ - StoreResponse store(RiakClient riak, RequestMeta meta); - - /** - * Convenience method for calling {@link RiakClient#fetch(String, String)} - * followed by {@link RiakObject#copyData(RiakObject)} - * - * @param meta - * Same as {@link RiakClient#fetch(String, String, RequestMeta)} - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to refetch it from. - */ - FetchResponse fetch(RequestMeta meta); - - FetchResponse fetch(); - - /** - * Convenience method for calling - * {@link RiakClient#fetchMeta(String, String, RequestMeta)} followed by - * {@link RiakObject#updateMeta(FetchResponse)} - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to refetch meta from. - */ - FetchResponse fetchMeta(RequestMeta meta); - - FetchResponse fetchMeta(); - - /** - * Convenience method for calling - * {@link RiakClient#delete(String, String, RequestMeta)}. - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to delete from. - */ - HttpResponse delete(RequestMeta meta); - - HttpResponse delete(); - - /** - * Convenience methods for building a link walk specification starting from - * this object and calling - * {@link RiakClient#walk(String, String, RiakWalkSpec)} - * - * @param bucket - * The bucket to follow object links to - * @param tag - * The link tags to follow from this object - * @param keep - * Whether to keep the output from this link walking step. If not - * specified, then the output is only kept from the last step. - * @return A {@link LinkBuilder} object to continue building the walk query - * or to run it. - */ - LinkBuilder walk(String bucket, String tag, boolean keep); - - LinkBuilder walk(String bucket, String tag); - - LinkBuilder walk(String bucket, boolean keep); - - LinkBuilder walk(String bucket); - - LinkBuilder walk(); - - LinkBuilder walk(boolean keep); - - /** - * Serializes this object to an existing {@link HttpMethod} which can be - * sent as an HTTP request. Specifically, sends the object's link, - * user-defined metadata and vclock as HTTP headers and the value as the - * body. Used by {@link RiakClient} to create PUT requests. - */ - void writeToHttpMethod(HttpMethod httpMethod); - - /** - * A thread safe, snapshot Iterable view of the state of this RiakObject's {@link RiakLink}s at call time. - * Modifications are *NOT* supported. - * @return Iterable for this RiakObject's {@link RiakLink}s - */ - Iterable iterableLinks(); - -} \ No newline at end of file From 3cf501247d0815a7ed72603aad28edbe651ad2fe Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 3 May 2011 15:55:22 +0100 Subject: [PATCH 021/764] Remove references to deprecated legacy RiakClient code. Rename well named interfaces to ugly I* interfaces to facilitate merge into existing RiakClient project. --- .../com/basho/riak/client/raw/RawClient.java | 6 +- .../basho/riak/client/raw/RiakResponse.java | 14 +- .../riak/client/raw/http/ConversionUtil.java | 61 ++-- .../client/raw/http/HTTPClientAdapter.java | 29 +- .../basho/riak/client/raw/http/KeySource.java | 2 +- .../riak/client/raw/pbc/ConversionUtil.java | 24 +- .../riak/client/raw/pbc/PBClientAdapter.java | 16 +- .../riak/client/raw/query/MapReduceSpec.java | 2 +- .../com/basho/riak/newapi/DefaultClient.java | 102 ------ .../basho/riak/newapi/DefaultRiakLink.java | 129 ------- .../basho/riak/newapi/DefaultRiakObject.java | 332 ------------------ .../com/basho/riak/newapi/IRiakClient.java | 57 +++ .../com/basho/riak/newapi/IRiakObject.java | 114 ++++++ .../com/basho/riak/newapi/RiakClient.java | 124 +++++-- .../com/basho/riak/newapi/RiakFactory.java | 30 +- .../java/com/basho/riak/newapi/RiakLink.java | 106 +++++- .../com/basho/riak/newapi/RiakObject.java | 278 +++++++++++++-- .../com/basho/riak/newapi/bucket/Bucket.java | 6 +- .../riak/newapi/bucket/DefaultBucket.java | 26 +- .../basho/riak/newapi/bucket/RiakBucket.java | 24 +- .../newapi/builders/RiakObjectBuilder.java | 11 +- .../com/basho/riak/newapi/cap/Quorum.java | 5 + .../basho/riak/newapi/convert/Converter.java | 6 +- .../riak/newapi/convert/JSONConverter.java | 6 +- .../riak/newapi/operations/FetchObject.java | 4 +- .../riak/newapi/operations/StoreObject.java | 8 +- .../com/basho/riak/newapi/query/LinkWalk.java | 4 +- .../basho/riak/newapi/query/WalkResult.java | 4 +- .../basho/riak/client/itest/ITestBucket.java | 14 +- .../riak/client/itest/ITestClientBasic.java | 6 +- .../riak/client/itest/ITestDomainBucket.java | 6 +- .../client/itest/ITestDomainBucketHTTP.java | 4 +- .../client/itest/ITestDomainBucketPB.java | 4 +- .../riak/client/itest/ITestHTTPBucket.java | 4 +- .../riak/client/itest/ITestHTTPClient.java | 19 +- .../riak/client/itest/ITestLinkWalk.java | 20 +- .../riak/client/itest/ITestMapReduce.java | 15 +- .../riak/client/itest/ITestMapReduceHTTP.java | 4 +- .../riak/client/itest/ITestMapReducePB.java | 4 +- .../riak/client/itest/ITestPBBucket.java | 4 +- .../riak/client/itest/ITestPBClient.java | 4 +- .../riak/client/raw/http/TestKeySource.java | 4 +- 42 files changed, 827 insertions(+), 815 deletions(-) delete mode 100644 src/main/java/com/basho/riak/newapi/DefaultClient.java delete mode 100644 src/main/java/com/basho/riak/newapi/DefaultRiakLink.java delete mode 100644 src/main/java/com/basho/riak/newapi/DefaultRiakObject.java create mode 100644 src/main/java/com/basho/riak/newapi/IRiakClient.java create mode 100644 src/main/java/com/basho/riak/newapi/IRiakObject.java diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index 747f2d849..ebdf092c3 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -19,7 +19,7 @@ import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.query.MapReduceResult; import com.basho.riak.newapi.query.WalkResult; @@ -36,9 +36,9 @@ public interface RawClient { RiakResponse fetch(String bucket, String key, int readQuorum) throws IOException; - RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOException; + RiakResponse store(IRiakObject object, StoreMeta storeMeta) throws IOException; - void store(RiakObject object) throws IOException; + void store(IRiakObject object) throws IOException; void delete(String bucket, String key) throws IOException; diff --git a/src/main/java/com/basho/riak/client/raw/RiakResponse.java b/src/main/java/com/basho/riak/client/raw/RiakResponse.java index ae160158d..008f9d115 100644 --- a/src/main/java/com/basho/riak/client/raw/RiakResponse.java +++ b/src/main/java/com/basho/riak/client/raw/RiakResponse.java @@ -16,7 +16,7 @@ import java.util.Arrays; import java.util.Iterator; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.cap.BasicVClock; import com.basho.riak.newapi.cap.VClock; @@ -25,17 +25,17 @@ * * @author russell */ -public class RiakResponse implements Iterable { +public class RiakResponse implements Iterable { - private static final RiakObject[] NO_OBJECTS = new RiakObject[] {}; + private static final IRiakObject[] NO_OBJECTS = new IRiakObject[] {}; private final VClock vclock; - private final RiakObject[] riakObjects; + private final IRiakObject[] riakObjects; /** * @param vclock * @param riakObjects */ - public RiakResponse(byte[] vclock, RiakObject[] riakObjects) { + public RiakResponse(byte[] vclock, IRiakObject[] riakObjects) { this.vclock = new BasicVClock(vclock); if (riakObjects == null) { this.riakObjects = NO_OBJECTS; @@ -69,7 +69,7 @@ public VClock getVclock() { /** * @return the riakObjects */ - public RiakObject[] getRiakObjects() { + public IRiakObject[] getRiakObjects() { return riakObjects; } @@ -90,7 +90,7 @@ public int numberOfValues() { * * @see java.lang.Iterable#iterator() */ - public Iterator iterator() { + public Iterator iterator() { return Arrays.asList(riakObjects).iterator(); } diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index 904023032..4b65c165c 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -28,19 +28,18 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; -import com.basho.riak.client.RiakBucketInfo; -import com.basho.riak.client.RiakClient; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.request.RiakWalkSpec; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.MapReduceResponse; -import com.basho.riak.client.response.WalkResponse; -import com.basho.riak.client.util.Constants; -import com.basho.riak.newapi.DefaultRiakLink; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.request.RiakWalkSpec; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.MapReduceResponse; +import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.http.util.Constants; import com.basho.riak.newapi.RiakLink; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; import com.basho.riak.newapi.builders.RiakObjectBuilder; @@ -61,21 +60,21 @@ public class ConversionUtil { * @param bucket * @return */ - static RiakObject[] convert(Collection siblings) { - final Collection results = new ArrayList(); + static IRiakObject[] convert(Collection siblings) { + final Collection results = new ArrayList(); - for (com.basho.riak.client.RiakObject object : siblings) { + for (com.basho.riak.client.http.RiakObject object : siblings) { results.add(convert(object)); } - return results.toArray(new RiakObject[results.size()]); + return results.toArray(new IRiakObject[results.size()]); } /** * @param object * @return */ - static RiakObject convert(final com.basho.riak.client.RiakObject o) { + static IRiakObject convert(final com.basho.riak.client.http.RiakObject o) { RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); @@ -92,7 +91,7 @@ static RiakObject convert(final com.basho.riak.client.RiakObject o) { final Collection links = new ArrayList(); - for (com.basho.riak.client.RiakLink link : o.iterableLinks()) { + for (com.basho.riak.client.http.RiakLink link : o.iterableLinks()) { links.add(convert(link)); } @@ -114,8 +113,8 @@ static RiakObject convert(final com.basho.riak.client.RiakObject o) { * @param link * @return */ - static RiakLink convert(com.basho.riak.client.RiakLink link) { - return new DefaultRiakLink(link.getBucket(), link.getKey(), link.getTag()); + static RiakLink convert(com.basho.riak.client.http.RiakLink link) { + return new RiakLink(link.getBucket(), link.getKey(), link.getTag()); } /** @@ -146,8 +145,8 @@ static RequestMeta convert(StoreMeta storeMeta) { * @param object * @return */ - static com.basho.riak.client.RiakObject convert(RiakObject object, final RiakClient client) { - com.basho.riak.client.RiakObject riakObject = new com.basho.riak.client.RiakObject( + static com.basho.riak.client.http.RiakObject convert(IRiakObject object, final RiakClient client) { + com.basho.riak.client.http.RiakObject riakObject = new com.basho.riak.client.http.RiakObject( client, object.getBucket(), object.getKey(), @@ -176,7 +175,7 @@ static String formatDate(Date lastModified) { * @param object * @return */ - static Map getUserMetaData(RiakObject object) { + static Map getUserMetaData(IRiakObject object) { final Map userMetaData = new HashMap(); for (Entry entry : object.userMetaEntries()) { @@ -189,9 +188,9 @@ static Map getUserMetaData(RiakObject object) { * @param object * @return */ - static List getLinks(RiakObject object) { + static List getLinks(IRiakObject object) { - final List links = new ArrayList(); + final List links = new ArrayList(); for (RiakLink link : object) { links.add(convert(link)); @@ -204,8 +203,8 @@ static List getLinks(RiakObject object) { * @param link * @return */ - static com.basho.riak.client.RiakLink convert(RiakLink link) { - return new com.basho.riak.client.RiakLink(link.getBucket(), link.getKey(), link.getTag()); + static com.basho.riak.client.http.RiakLink convert(RiakLink link) { + return new com.basho.riak.client.http.RiakLink(link.getBucket(), link.getKey(), link.getTag()); } /** @@ -309,19 +308,19 @@ static String convert(LinkWalkSpec linkWalkSpec) { * @return a new api WalkResult */ static WalkResult convert(WalkResponse walkResponse) { - final Collection> convertedSteps = new LinkedList>(); + final Collection> convertedSteps = new LinkedList>(); - for(List step : walkResponse.getSteps()) { - final LinkedList objects = new LinkedList(); - for(com.basho.riak.client.RiakObject o : step) { + for(List step : walkResponse.getSteps()) { + final LinkedList objects = new LinkedList(); + for(com.basho.riak.client.http.RiakObject o : step) { objects.add(convert(o)); } convertedSteps.add(objects); } return new WalkResult() { - public Iterator> iterator() { - return new UnmodifiableIterator>( convertedSteps.iterator() ); + public Iterator> iterator() { + return new UnmodifiableIterator>( convertedSteps.iterator() ); } }; } diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index 7ea68824c..cb78f324b 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -18,21 +18,21 @@ import java.io.IOException; import java.util.Iterator; -import com.basho.riak.client.RiakClient; +import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; -import com.basho.riak.client.request.RequestMeta; -import com.basho.riak.client.response.BucketResponse; -import com.basho.riak.client.response.FetchResponse; -import com.basho.riak.client.response.HttpResponse; -import com.basho.riak.client.response.MapReduceResponse; -import com.basho.riak.client.response.StoreResponse; -import com.basho.riak.client.response.WithBodyResponse; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.client.http.request.RequestMeta; +import com.basho.riak.client.http.response.BucketResponse; +import com.basho.riak.client.http.response.FetchResponse; +import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.http.response.MapReduceResponse; +import com.basho.riak.client.http.response.StoreResponse; +import com.basho.riak.client.http.response.WithBodyResponse; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.cap.ClientId; import com.basho.riak.newapi.query.MapReduceResult; @@ -116,12 +116,12 @@ public RiakResponse fetch(String bucket, String key, int readQuorum) throws IOEx */ private RiakResponse handleBodyResponse(WithBodyResponse resp) { RiakResponse response = RiakResponse.empty(); - RiakObject[] values = new RiakObject[] {}; + IRiakObject[] values = new IRiakObject[] {}; if (resp.hasSiblings()) { values = convert(resp.getSiblings()); } else if (resp.hasObject()) { - values = new RiakObject[] { convert(resp.getObject()) }; + values = new IRiakObject[] { convert(resp.getObject()) }; } if (values.length > 0) { @@ -138,13 +138,13 @@ private RiakResponse handleBodyResponse(WithBodyResponse resp) { * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ - public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOException { + public RiakResponse store(IRiakObject object, StoreMeta storeMeta) throws IOException { if (object == null || object.getBucket() == null) { throw new IllegalArgumentException("cannot store a null RiakObject, or a RiakObject without a bucket"); } RiakResponse response = RiakResponse.empty(); - com.basho.riak.client.RiakObject riakObject = convert(object, client); + com.basho.riak.client.http.RiakObject riakObject = convert(object, client); RequestMeta requestMeta = convert(storeMeta); StoreResponse resp = client.store(riakObject, requestMeta); @@ -168,7 +168,7 @@ public RiakResponse store(RiakObject object, StoreMeta storeMeta) throws IOExcep * com.basho.riak.client.raw.RawClient#store(com.basho.riak.newapi.RiakObject * ) */ - public void store(RiakObject object) throws IOException { + public void store(IRiakObject object) throws IOException { store(object, new StoreMeta(null, null, false)); } @@ -235,7 +235,6 @@ public void updateBucket(String name, BucketProperties bucketProperties) throws if (!response.isSuccess()) { throw new IOException(response.getBodyAsString()); } - } /* diff --git a/src/main/java/com/basho/riak/client/raw/http/KeySource.java b/src/main/java/com/basho/riak/client/raw/http/KeySource.java index 42e7b107d..272fecc31 100644 --- a/src/main/java/com/basho/riak/client/raw/http/KeySource.java +++ b/src/main/java/com/basho/riak/client/raw/http/KeySource.java @@ -18,7 +18,7 @@ import java.util.Timer; import java.util.TimerTask; -import com.basho.riak.client.response.BucketResponse; +import com.basho.riak.client.http.response.BucketResponse; /** * Wraps the stream of keys from BucketResponse.getBucketInfo.getKeys in an diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index 783a9585e..cf4005a5e 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -32,7 +32,7 @@ import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; import com.basho.riak.newapi.builders.RiakObjectBuilder; @@ -60,7 +60,7 @@ static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects) { RiakResponse response = RiakResponse.empty(); if (pbcObjects != null && pbcObjects.length > 0) { - RiakObject[] converted = new RiakObject[pbcObjects.length]; + IRiakObject[] converted = new IRiakObject[pbcObjects.length]; for (int i = 0; i < pbcObjects.length; i++) { converted[i] = convert(pbcObjects[i]); } @@ -74,7 +74,7 @@ static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects) { * @param o * @return */ - static RiakObject convert(com.basho.riak.pbc.RiakObject o) { + static IRiakObject convert(com.basho.riak.pbc.RiakObject o) { RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); builder.withValue(nullSafeToStringUtf8(o.getValue())); @@ -117,7 +117,7 @@ static ByteString nullSafeToByteString(String value) { * a {@link StoreMeta} for the store operation. * @return a {@link RequestMeta} populated from the storeMeta's values. */ - static RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { + static RequestMeta convert(StoreMeta storeMeta, IRiakObject riakObject) { RequestMeta requestMeta = new RequestMeta(); if (storeMeta.hasW()) { requestMeta.w(storeMeta.getW()); @@ -136,14 +136,14 @@ static RequestMeta convert(StoreMeta storeMeta, RiakObject riakObject) { } /** - * Convert a {@link RiakObject} to a pbc + * Convert a {@link IRiakObject} to a pbc * {@link com.basho.riak.pbc.RiakObject} * * @param riakObject * the RiakObject to convert * @return a {@link com.basho.riak.pbc.RiakObject} populated from riakObject */ - static com.basho.riak.pbc.RiakObject convert(RiakObject riakObject) { + static com.basho.riak.pbc.RiakObject convert(IRiakObject riakObject) { final VClock vc = riakObject.getVClock(); ByteString bucketName = nullSafeToByteString(riakObject.getBucket()); ByteString key = nullSafeToByteString(riakObject.getKey()); @@ -303,16 +303,16 @@ static boolean linkAccumulateToLinkPhaseKeep(Accumulate accumulate, boolean isFi * @throws IOException */ @SuppressWarnings({ "rawtypes" }) static WalkResult convert(MapReduceResult secondPhaseResult) throws IOException { - final SortedMap> steps = new TreeMap>(); + final SortedMap> steps = new TreeMap>(); try { Collection results = secondPhaseResult.getResult(Map.class); for (Map o : results) { final int step = Integer.parseInt((String) o.get("step")); - Collection stepAccumulator = steps.get(step); + Collection stepAccumulator = steps.get(step); if (stepAccumulator == null) { - stepAccumulator = new ArrayList(); + stepAccumulator = new ArrayList(); steps.put(step, stepAccumulator); } @@ -325,8 +325,8 @@ static boolean linkAccumulateToLinkPhaseKeep(Accumulate accumulate, boolean isFi } // create a result instance return new WalkResult() { - public Iterator> iterator() { - return new UnmodifiableIterator>(steps.values().iterator()); + public Iterator> iterator() { + return new UnmodifiableIterator>(steps.values().iterator()); } }; } @@ -338,7 +338,7 @@ public Iterator> iterator() { * a valid Map from JSON. * @return A RiakObject populated from the map. */ - @SuppressWarnings({ "rawtypes", "unchecked" }) private static RiakObject mapToRiakObject(Map data) { + @SuppressWarnings({ "rawtypes", "unchecked" }) private static IRiakObject mapToRiakObject(Map data) { RiakObjectBuilder b = RiakObjectBuilder.newBuilder((String) data.get("bucket"), (String) data.get("key")); b.withVClock(((String) data.get("vclock")).getBytes()); diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index d7141d7e6..02b773c30 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -29,9 +29,9 @@ import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; -import com.basho.riak.client.util.Constants; +import com.basho.riak.client.http.util.Constants; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.convert.ConversionException; import com.basho.riak.newapi.query.BucketKeyMapReduce; @@ -65,6 +65,14 @@ public PBClientAdapter(String host, int port) throws IOException { this.client = new RiakClient(host, port); } + /** + * Wrap a pre-created/configured pb client as a RawClient + * @param delegate the {@link RiakClient} to adapt. + */ + public PBClientAdapter(com.basho.riak.pbc.RiakClient delegate) { + this.client = delegate; + } + /* * (non-Javadoc) * @@ -111,7 +119,7 @@ public RiakResponse fetch(String bucket, String key, int readQuorum) throws IOEx * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject * , com.basho.riak.client.raw.StoreMeta) */ - public RiakResponse store(RiakObject riakObject, StoreMeta storeMeta) throws IOException { + public RiakResponse store(IRiakObject riakObject, StoreMeta storeMeta) throws IOException { if (riakObject == null || riakObject.getKey() == null || riakObject.getBucket() == null) { throw new IllegalArgumentException( "object cannot be null, object's key cannot be null, object's bucket cannot be null"); @@ -127,7 +135,7 @@ public RiakResponse store(RiakObject riakObject, StoreMeta storeMeta) throws IOE * com.basho.riak.client.raw.RawClient#store(com.basho.riak.client.RiakObject * ) */ - public void store(RiakObject object) throws IOException { + public void store(IRiakObject object) throws IOException { store(object, new StoreMeta(null, null, false)); } diff --git a/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java b/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java index 3e7bd1d62..00ca5a6bc 100644 --- a/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java +++ b/src/main/java/com/basho/riak/client/raw/query/MapReduceSpec.java @@ -14,7 +14,7 @@ package com.basho.riak.client.raw.query; /** - * A Map Reduce Query run it via {@link RiakClient#mapReduce(MapReduceSpec)} + * A Map Reduce Query run it via {@link IRiakClient#mapReduce(MapReduceSpec)} * * @author russell * diff --git a/src/main/java/com/basho/riak/newapi/DefaultClient.java b/src/main/java/com/basho/riak/newapi/DefaultClient.java deleted file mode 100644 index 6d3e6f299..000000000 --- a/src/main/java/com/basho/riak/newapi/DefaultClient.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.basho.riak.newapi; - -import java.io.IOException; - -import com.basho.riak.client.raw.Command; -import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.FetchBucket; -import com.basho.riak.newapi.bucket.WriteBucket; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.query.BucketKeyMapReduce; -import com.basho.riak.newapi.query.BucketMapReduce; -import com.basho.riak.newapi.query.LinkWalk; - -/** - * @author russell - * - */ -public final class DefaultClient implements RiakClient { - - private final RawClient client; - - /** - * @param client - */ - DefaultClient(RawClient client) { - this.client = client; - } - - // BUCKET OPS - - public WriteBucket updateBucket(Bucket b) { - WriteBucket op = new WriteBucket(client, b); - return op; - } - - public FetchBucket fetchBucket(String bucketName) { - FetchBucket op = new FetchBucket(client, bucketName); - return op; - } - - public WriteBucket createBucket(String bucketName) { - WriteBucket op = new WriteBucket(client, bucketName); - return op; - } - - // CLIENT ID - - public RiakClient setClientId(final byte[] clientId) throws RiakException { - if (clientId == null || clientId.length != 4) { - throw new IllegalArgumentException("Client Id must be 4 bytes long"); - } - final byte[] cloned = clientId.clone(); - new DefaultRetrier().attempt(new Command() { - public Void execute() throws IOException { - client.setClientId(cloned); - return null; - } - }, 3); - - return this; - } - - public byte[] generateAndSetClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { - return client.generateAndSetClientId(); - } - }, 3); - - return clientId; - } - - public byte[] getClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { - return client.getClientId(); - } - }, 3); - - return clientId; - } - - // QUERY - - public BucketKeyMapReduce mapReduce() { - return new BucketKeyMapReduce(client); - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.newapi.RiakClient#mapReduce(java.lang.String) - */ - public BucketMapReduce mapReduce(String bucket) { - return new BucketMapReduce(client, bucket); - } - - public LinkWalk walk(RiakObject startObject) { - return new LinkWalk(client, startObject); - } -} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java b/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java deleted file mode 100644 index 96989dfdd..000000000 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakLink.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is provided 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.basho.riak.newapi; - -/** - * Immutable RiakLink impl. - * - * @author russell - * - */ -public class DefaultRiakLink implements RiakLink { - - private final String bucket; - private final String key; - private final String tag; - - /** - * @param tag - * @param bucket - * @param key - */ - public DefaultRiakLink(String bucket, String key, String tag) { - this.tag = tag; - this.bucket = bucket; - this.key = key; - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.newapi.RiakLink#getBucket() - */ - public String getBucket() { - return bucket; - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.newapi.RiakLink#getKey() - */ - public String getKey() { - return key; - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.newapi.RiakLink#getTag() - */ - public String getTag() { - return tag; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((bucket == null) ? 0 : bucket.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((tag == null) ? 0 : tag.hashCode()); - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof DefaultRiakLink)) { - return false; - } - DefaultRiakLink other = (DefaultRiakLink) obj; - if (bucket == null) { - if (other.bucket != null) { - return false; - } - } else if (!bucket.equals(other.bucket)) { - return false; - } - if (key == null) { - if (other.key != null) { - return false; - } - } else if (!key.equals(other.key)) { - return false; - } - if (tag == null) { - if (other.tag != null) { - return false; - } - } else if (!tag.equals(other.tag)) { - return false; - } - return true; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override public String toString() { - return String.format("DefaultRiakLink [tag=%s, bucket=%s, key=%s]", tag, bucket, key); - } - -} diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java deleted file mode 100644 index cfafd5df0..000000000 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * This file is provided 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.basho.riak.newapi; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.RiakKey; - -/** - * @author russell - * - */ -public class DefaultRiakObject implements RiakObject { - - public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; - - private final String bucket; - @RiakKey private final String key; - private final VClock vclock; - private final String vtag; - private final long lastModified; - - private final Object linksLock = new Object(); - private final Collection links; - private final Object userMetaLock = new Object(); - private final Map userMeta; - - private volatile String contentType; - private volatile String value; - - /** - * Use the builder. - * - * @param bucket - * @param key - * @param vclock - * @param conflict - * @param vtag - * @param lastModified - * @param contentType - * @param value - * @param siblings - * @param links - * @param userMeta - */ - public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, - String contentType, String value, final Collection links, final Map userMeta) { - - if (bucket == null) { - throw new IllegalArgumentException("Bucket cannot be null"); - } - - if (key == null) { - throw new IllegalArgumentException("Key cannot be null"); - } - - this.bucket = bucket; - this.key = key; - this.vclock = vclock; - this.vtag = vtag; - this.lastModified = lastModified == null ? 0 : lastModified.getTime(); - safeSetContentType(contentType); - this.value = value; - this.links = copy(links); - this.userMeta = copy(userMeta); - } - - private Map copy(Map userMeta) { - Map copy; - - if (userMeta == null) { - copy = new HashMap(); - } else { - copy = new HashMap(userMeta); - } - - return copy; - } - - private Collection copy(Collection links) { - Collection copy; - if (links == null) { - copy = new ArrayList(); - } else { - copy = new ArrayList(links); - } - return copy; - } - - private void safeSetContentType(String contentType) { - if (contentType == null) { - this.contentType = DEFAULT_CONTENT_TYPE; - } else { - this.contentType = contentType; - } - } - - private Collection deepCopy(final Collection siblings) { - final ArrayList copy = new ArrayList(); - - if (siblings != null && siblings.size() == 0) { - for (RiakObject o : siblings) { - copy.add(RiakObjectBuilder.from(o).build()); - } - } - - return copy; - } - - public Iterator iterator() { - return links.iterator(); - } - - public String getBucket() { - return bucket; - } - - public VClock getVClock() { - return vclock; - } - - public String getKey() { - return key; - } - - public String getVtag() { - return vtag; - } - - public Date getLastModified() { - Date lastModified = null; - - if (this.lastModified != 0) { - lastModified = new Date(this.lastModified); - } - - return lastModified; - } - - public String getContentType() { - return contentType; - } - - public Map getMeta() { - return new HashMap(userMeta); - } - - public String getValue() { - return value; - } - - // mutate - - public RiakObject setValue(String value) { - this.value = value; - return this; - } - - public RiakObject setContentType(String contentType) { - this.contentType = contentType; - return this; - } - - /** - * Add link to this RiakObject's links. - * - * @param link - * a {@link RiakLink} to add. - * @return this RiakObject. - */ - public RiakObject addLink(RiakLink link) { - if (link != null) { - synchronized (linksLock) { - links.add(link); - } - } - return this; - } - - /** - * Remove a {@link RiakLink} from this RiakObject. - * - * @param link - * the {@link RiakLink} to remove - * @return this RiakObject - */ - public RiakObject removeLink(final RiakLink link) { - synchronized (linksLock) { - this.links.remove(link); - } - return this; - } - - /** - * Does this RiakObject has any {@link RiakLink}s? - * - * @return true if there are links, false otherwise - */ - public boolean hasLinks() { - synchronized (linksLock) { - return !links.isEmpty(); - } - } - - /** - * How many {@link RiakLink}s does this RiakObject have? - * - * @return the number of {@link RiakLink}s this object has. - */ - public int numLinks() { - synchronized (linksLock) { - return links.size(); - } - } - - public Collection getLinks() { - synchronized (linksLock) { - return new ArrayList(links); - } - } - - /** - * Checks if the collection of RiakLinks contains the one passed in. - * - * @param riakLink - * a RiakLink - * @return true if the RiakObject's link collection contains riakLink. - */ - public boolean hasLink(final RiakLink riakLink) { - synchronized (linksLock) { - return links.contains(riakLink); - } - } - - /** - * Adds the key, value to the collection of user meta for this object. - * - * @param key - * @param value - * @return this RiakObject. - */ - public RiakObject addUsermeta(String key, String value) { - synchronized (userMetaLock) { - userMeta.put(key, value); - } - return this; - } - - /** - * @return true if there are any user meta data set on this RiakObject. - */ - public boolean hasUsermeta() { - synchronized (userMetaLock) { - return !userMeta.isEmpty(); - } - } - - /** - * @param key - * @return - */ - public boolean hasUsermeta(String key) { - synchronized (userMetaLock) { - return userMeta.containsKey(key); - } - } - - /** - * Get an item of user meta data. - * - * @param key - * the user meta data item key - * @return The value for the given key or null. - */ - public String getUsermeta(String key) { - synchronized (userMetaLock) { - return userMeta.get(key); - } - - } - - /** - * @param key - * the key of the item to remove - */ - public RiakObject removeUsermeta(String key) { - synchronized (userMetaLock) { - userMeta.remove(key); - } - return this; - } - - /** - * return an unmodifiable view of the user meta entries. Attempts to modify - * will throw UnsupportedOperationException. - */ - public Iterable> userMetaEntries() { - return Collections.unmodifiableCollection(userMeta.entrySet()); - } - - /* - * (non-Javadoc) - * - * @see com.basho.riak.newapi.RiakObject#getVClockAsString() - */ - public String getVClockAsString() { - if (vclock != null) { - return vclock.asString(); - } - return null; - } - -} diff --git a/src/main/java/com/basho/riak/newapi/IRiakClient.java b/src/main/java/com/basho/riak/newapi/IRiakClient.java new file mode 100644 index 000000000..137da659f --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/IRiakClient.java @@ -0,0 +1,57 @@ +/* + * This file is provided 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.basho.riak.newapi; + +import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.bucket.FetchBucket; +import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.query.BucketKeyMapReduce; +import com.basho.riak.newapi.query.BucketMapReduce; +import com.basho.riak.newapi.query.LinkWalk; + +/** + * @author russell + * + */ +public interface IRiakClient { + + IRiakClient setClientId(byte[] clientId) throws RiakException; + + byte[] generateAndSetClientId() throws RiakException; + + byte[] getClientId() throws RiakException; + + FetchBucket fetchBucket(String bucketName); + + WriteBucket updateBucket(Bucket b); + + WriteBucket createBucket(String string); + + // query - links + LinkWalk walk(final IRiakObject startObject); + + // query - m/r + + /** + * Map reduce over a set of bucket, key inputs + */ + BucketKeyMapReduce mapReduce(); + + /** + * Map reduce over a bucket + * @param bucket + * @return + */ + BucketMapReduce mapReduce(String bucket); +} diff --git a/src/main/java/com/basho/riak/newapi/IRiakObject.java b/src/main/java/com/basho/riak/newapi/IRiakObject.java new file mode 100644 index 000000000..3823883d8 --- /dev/null +++ b/src/main/java/com/basho/riak/newapi/IRiakObject.java @@ -0,0 +1,114 @@ +/* + * This file is provided 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.basho.riak.newapi; + +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.Map.Entry; + +import com.basho.riak.newapi.cap.VClock; + +/** + * Represents the data and meta data stored in Riak for bucket/key. + * + * NOTE: The name will be changing soon. The initial Java client release + * laid claim to the best name real estate. + * This class will be named RiakObject in subsequent releases. + * + * @see RiakObject in the legacy project + * @author russell + * + */ +public interface IRiakObject extends Iterable { + + String getBucket(); + + String getValue(); + + VClock getVClock(); + + String getKey(); + + String getVtag(); + + Date getLastModified(); + + String getContentType(); + + // links + Collection getLinks(); + + boolean hasLinks(); + + int numLinks(); + + boolean hasLink(final RiakLink riakLink); + + // user meta + Map getMeta(); + + boolean hasUsermeta(); + + boolean hasUsermeta(String key); + + String getUsermeta(String key); + + Iterable> userMetaEntries(); + + // Mutate + + IRiakObject setValue(String value); + + IRiakObject setContentType(String contentType); + + /** + * Add link to this RiakObject's links. + * + * @param link + * a {@link RiakLink} to add. + * @return this RiakObject. + */ + IRiakObject addLink(RiakLink link); + + /** + * Remove a {@link RiakLink} from this RiakObject. + * + * @param link + * the {@link RiakLink} to remove + * @return this RiakObject + */ + IRiakObject removeLink(final RiakLink link); + + /** + * Adds the key, value to the collection of user meta for this object. + * + * @param key + * @param value + * @return this RiakObject. + */ + IRiakObject addUsermeta(String key, String value); + + /** + * @param key + * the key of the item to remove + */ + IRiakObject removeUsermeta(String key); + + /** + * @return A String of the VClock + */ + String getVClockAsString(); + +} diff --git a/src/main/java/com/basho/riak/newapi/RiakClient.java b/src/main/java/com/basho/riak/newapi/RiakClient.java index 5e21ced0e..e816f2f75 100644 --- a/src/main/java/com/basho/riak/newapi/RiakClient.java +++ b/src/main/java/com/basho/riak/newapi/RiakClient.java @@ -1,57 +1,111 @@ -/* - * This file is provided 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.basho.riak.newapi; +import java.io.IOException; + +import com.basho.riak.client.raw.Command; +import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.FetchBucket; import com.basho.riak.newapi.bucket.WriteBucket; +import com.basho.riak.newapi.cap.DefaultRetrier; import com.basho.riak.newapi.query.BucketKeyMapReduce; import com.basho.riak.newapi.query.BucketMapReduce; import com.basho.riak.newapi.query.LinkWalk; /** + * A default implementation of IRiakClient. + * + * The class also includes the deprecated http.RiakClient methods to + * ease the transition between versions. + * + * RiakClient provides convenient, transport agnostic ways to perform perform + * bucket and query operations on Riak. + * + * In the next release this class will be renamed and all deprecated methods removed. * @author russell * */ -public interface RiakClient { +public final class RiakClient implements IRiakClient { - RiakClient setClientId(byte[] clientId) throws RiakException; + private final RawClient client; - byte[] generateAndSetClientId() throws RiakException; + /** + * @param client + */ + RiakClient(RawClient client) { + this.client = client; + } - byte[] getClientId() throws RiakException; + // BUCKET OPS - FetchBucket fetchBucket(String bucketName); + public WriteBucket updateBucket(Bucket b) { + WriteBucket op = new WriteBucket(client, b); + return op; + } - WriteBucket updateBucket(Bucket b); + public FetchBucket fetchBucket(String bucketName) { + FetchBucket op = new FetchBucket(client, bucketName); + return op; + } - WriteBucket createBucket(String string); + public WriteBucket createBucket(String bucketName) { + WriteBucket op = new WriteBucket(client, bucketName); + return op; + } - // query - links - LinkWalk walk(final RiakObject startObject); + // CLIENT ID - // query - m/r - - /** - * Map reduce over a set of bucket, key inputs - */ - BucketKeyMapReduce mapReduce(); - - /** - * Map reduce over a bucket - * @param bucket - * @return + public IRiakClient setClientId(final byte[] clientId) throws RiakException { + if (clientId == null || clientId.length != 4) { + throw new IllegalArgumentException("Client Id must be 4 bytes long"); + } + final byte[] cloned = clientId.clone(); + new DefaultRetrier().attempt(new Command() { + public Void execute() throws IOException { + client.setClientId(cloned); + return null; + } + }, 3); + + return this; + } + + public byte[] generateAndSetClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.generateAndSetClientId(); + } + }, 3); + + return clientId; + } + + public byte[] getClientId() throws RiakException { + final byte[] clientId = new DefaultRetrier().attempt(new Command() { + public byte[] execute() throws IOException { + return client.getClientId(); + } + }, 3); + + return clientId; + } + + // QUERY + + public BucketKeyMapReduce mapReduce() { + return new BucketKeyMapReduce(client); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakClient#mapReduce(java.lang.String) */ - BucketMapReduce mapReduce(String bucket); -} + public BucketMapReduce mapReduce(String bucket) { + return new BucketMapReduce(client, bucket); + } + + public LinkWalk walk(IRiakObject startObject) { + return new LinkWalk(client, startObject); + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java index 681790702..7c4c50a12 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -20,8 +20,10 @@ import com.basho.riak.client.raw.pbc.PBClientAdapter; /** - * @author russell - * + * A very basic factory for getting an IRiakClient implementation wrapping + * the {@link RawClient} of your choice. + * + * @author russell */ public class RiakFactory { @@ -32,31 +34,41 @@ public class RiakFactory { * @return a default configuration PBC client * @throws RiakException */ - public static RiakClient pbcClient() throws RiakException { + public static IRiakClient pbcClient() throws RiakException { try { final RawClient client = new PBClientAdapter("127.0.0.1", 8087); - return new DefaultClient(client); + return new RiakClient(client); } catch (IOException e) { throw new RiakException(e); } } + /** + * Wraps the given pb client in IRiakFactory clothes. + * @param delegate + * @return a wrapped pb client + */ + public static IRiakClient pbcClient(com.basho.riak.pbc.RiakClient delegate) { + final RawClient client = new PBClientAdapter(delegate); + return new RiakClient(client); + } + /** * @return a default configuration HTTP client */ - public static RiakClient httpClient() throws RiakException { + public static IRiakClient httpClient() throws RiakException { final RawClient client = new HTTPClientAdapter(DEFAULT_RIAK_URL); - return new DefaultClient(client); + return new RiakClient(client); } /** - * @return a wrapped RiakClient + * @return a wrapped http RiakClient */ - public static RiakClient httpClient(com.basho.riak.client.RiakClient delegate) throws RiakException { + public static IRiakClient httpClient(com.basho.riak.client.http.RiakClient delegate) throws RiakException { final RawClient client = new HTTPClientAdapter(delegate); - return new DefaultClient(client); + return new RiakClient(client); } } diff --git a/src/main/java/com/basho/riak/newapi/RiakLink.java b/src/main/java/com/basho/riak/newapi/RiakLink.java index 50d8d0116..46128f971 100644 --- a/src/main/java/com/basho/riak/newapi/RiakLink.java +++ b/src/main/java/com/basho/riak/newapi/RiakLink.java @@ -14,15 +14,113 @@ package com.basho.riak.newapi; /** + * Immutable RiakLink + * * @author russell * */ -public interface RiakLink { +public class RiakLink { - String getTag(); + private final String bucket; + private final String key; + private final String tag; - String getBucket(); + /** + * Create a RiakLink from the specified parameters. + * + * @param bucket the name of the bucket + * @param key the key name + * @param tag the link tag + */ + public RiakLink(String bucket, String key, String tag) { + this.bucket = bucket; + this.key = key; + this.tag = tag; + } - String getKey(); + /** + * Create a RiakLink that is a copy of another RiakLink. + * @param riakLink the RiakLink to copy + */ + public RiakLink(final RiakLink riakLink) { + this.bucket = riakLink.getBucket(); + this.key = riakLink.getKey(); + this.tag = riakLink.getTag(); + } + + public String getBucket() { + return bucket; + } + + public String getKey() { + return key; + } + + public String getTag() { + return tag; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bucket == null) ? 0 : bucket.hashCode()); + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((tag == null) ? 0 : tag.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof RiakLink)) { + return false; + } + RiakLink other = (RiakLink) obj; + if (bucket == null) { + if (other.bucket != null) { + return false; + } + } else if (!bucket.equals(other.bucket)) { + return false; + } + if (key == null) { + if (other.key != null) { + return false; + } + } else if (!key.equals(other.key)) { + return false; + } + if (tag == null) { + if (other.tag != null) { + return false; + } + } else if (!tag.equals(other.tag)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override public String toString() { + return String.format("DefaultRiakLink [tag=%s, bucket=%s, key=%s]", tag, bucket, key); + } } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/RiakObject.java index 82a2b389e..2da587313 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/RiakObject.java @@ -13,58 +13,165 @@ */ package com.basho.riak.newapi; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; +import com.basho.riak.client.http.HttpRiakObject; import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.newapi.convert.RiakKey; /** - * @author russell + * An implementation of {@link IRiakObject} that also contains the deprecated + * http.RiakObject methods to facilitate transition between versions. + * + * A RiakObject models the meta data and data stored at a bucket/key location in + * Riak. * + * @author russell */ -public interface RiakObject extends Iterable { +public class RiakObject implements IRiakObject { + + public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + + private final String bucket; + @RiakKey private final String key; + private final VClock vclock; + private final String vtag; + private final long lastModified; + + private final Object linksLock = new Object(); + private final Collection links; + private final Object userMetaLock = new Object(); + private final Map userMeta; + + private volatile String contentType; + private volatile String value; + + /** + * Use the builder. + * + * @param bucket + * @param key + * @param vclock + * @param conflict + * @param vtag + * @param lastModified + * @param contentType + * @param value + * @param siblings + * @param links + * @param userMeta + */ + public RiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, + String contentType, String value, final Collection links, final Map userMeta) { + + if (bucket == null) { + throw new IllegalArgumentException("Bucket cannot be null"); + } + + if (key == null) { + throw new IllegalArgumentException("Key cannot be null"); + } - String getBucket(); + this.bucket = bucket; + this.key = key; + this.vclock = vclock; + this.vtag = vtag; + this.lastModified = lastModified == null ? 0 : lastModified.getTime(); + safeSetContentType(contentType); + this.value = value; + this.links = copy(links); + this.userMeta = copy(userMeta); + } - String getValue(); + private Map copy(Map userMeta) { + Map copy; - VClock getVClock(); + if (userMeta == null) { + copy = new HashMap(); + } else { + copy = new HashMap(userMeta); + } - String getKey(); + return copy; + } - String getVtag(); + private Collection copy(Collection links) { + Collection copy; + if (links == null) { + copy = new ArrayList(); + } else { + copy = new ArrayList(links); + } + return copy; + } - Date getLastModified(); + private void safeSetContentType(String contentType) { + if (contentType == null) { + this.contentType = DEFAULT_CONTENT_TYPE; + } else { + this.contentType = contentType; + } + } - String getContentType(); + public Iterator iterator() { + return links.iterator(); + } - // links - Collection getLinks(); + public String getBucket() { + return bucket; + } - boolean hasLinks(); + public VClock getVClock() { + return vclock; + } - int numLinks(); + public String getKey() { + return key; + } - boolean hasLink(final RiakLink riakLink); + public String getVtag() { + return vtag; + } - // user meta - Map getMeta(); + public Date getLastModified() { + Date lastModified = null; - boolean hasUsermeta(); + if (this.lastModified != 0) { + lastModified = new Date(this.lastModified); + } - boolean hasUsermeta(String key); + return lastModified; + } - String getUsermeta(String key); + public String getContentType() { + return contentType; + } - Iterable> userMetaEntries(); + public Map getMeta() { + return new HashMap(userMeta); + } - // Mutate + public String getValue() { + return value; + } - RiakObject setValue(String value); + // mutate - RiakObject setContentType(String contentType); + public IRiakObject setValue(String value) { + this.value = value; + return this; + } + + public IRiakObject setContentType(String contentType) { + this.contentType = contentType; + return this; + } /** * Add link to this RiakObject's links. @@ -73,7 +180,14 @@ public interface RiakObject extends Iterable { * a {@link RiakLink} to add. * @return this RiakObject. */ - RiakObject addLink(RiakLink link); + public IRiakObject addLink(RiakLink link) { + if (link != null) { + synchronized (linksLock) { + links.add(link); + } + } + return this; + } /** * Remove a {@link RiakLink} from this RiakObject. @@ -82,7 +196,53 @@ public interface RiakObject extends Iterable { * the {@link RiakLink} to remove * @return this RiakObject */ - RiakObject removeLink(final RiakLink link); + public IRiakObject removeLink(final RiakLink link) { + synchronized (linksLock) { + this.links.remove(link); + } + return this; + } + + /** + * Does this RiakObject have any {@link RiakLink}s? + * + * @return true if there are links, false otherwise + */ + public boolean hasLinks() { + synchronized (linksLock) { + return !links.isEmpty(); + } + } + + /** + * How many {@link RiakLink}s does this RiakObject have? + * + * @return the number of {@link RiakLink}s this object has. + */ + public int numLinks() { + synchronized (linksLock) { + return links.size(); + } + } + + public Collection getLinks() { + synchronized (linksLock) { + return new ArrayList(links); + } + } + + /** + * Checks if the collection of RiakLinks contains the one passed in. + * + * @param riakLink + * a RiakLink + * @return true if the RiakObject's link collection contains riakLink. + */ + public boolean hasLink(final RiakLink riakLink) { + synchronized (linksLock) { + return links.contains(riakLink); + } + } /** * Adds the key, value to the collection of user meta for this object. @@ -91,17 +251,75 @@ public interface RiakObject extends Iterable { * @param value * @return this RiakObject. */ - RiakObject addUsermeta(String key, String value); + public IRiakObject addUsermeta(String key, String value) { + synchronized (userMetaLock) { + userMeta.put(key, value); + } + return this; + } + + /** + * @return true if there are any user meta data set on this RiakObject. + */ + public boolean hasUsermeta() { + synchronized (userMetaLock) { + return !userMeta.isEmpty(); + } + } + + /** + * @param key + * @return + */ + public boolean hasUsermeta(String key) { + synchronized (userMetaLock) { + return userMeta.containsKey(key); + } + } + + /** + * Get an item of user meta data. + * + * @param key + * the user meta data item key + * @return The value for the given key or null. + */ + public String getUsermeta(String key) { + synchronized (userMetaLock) { + return userMeta.get(key); + } + + } /** * @param key * the key of the item to remove */ - RiakObject removeUsermeta(String key); + public IRiakObject removeUsermeta(String key) { + synchronized (userMetaLock) { + userMeta.remove(key); + } + return this; + } /** - * @return A String of the VClock + * return an unmodifiable view of the user meta entries. Attempts to modify + * will throw UnsupportedOperationException. + */ + public Iterable> userMetaEntries() { + return Collections.unmodifiableCollection(userMeta.entrySet()); + } + + /* + * (non-Javadoc) + * + * @see com.basho.riak.newapi.RiakObject#getVClockAsString() */ - String getVClockAsString(); + public String getVClockAsString() { + if (vclock != null) { + return vclock.asString(); + } + return null; + } } diff --git a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java index 81d0a6f50..c6e4d7e65 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/Bucket.java @@ -14,7 +14,7 @@ package com.basho.riak.newapi.bucket; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.operations.DeleteObject; import com.basho.riak.newapi.operations.FetchObject; import com.basho.riak.newapi.operations.StoreObject; @@ -27,13 +27,13 @@ public interface Bucket extends BucketProperties { String getName(); - StoreObject store(String key, String value); + StoreObject store(String key, String value); StoreObject store(T o); StoreObject store(String key, T o); - FetchObject fetch(String key); + FetchObject fetch(String key); FetchObject fetch(String key, Class type); diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 7a377f478..260128242 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -20,7 +20,7 @@ import com.basho.riak.client.raw.RawClient; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.ClobberMutation; import com.basho.riak.newapi.cap.DefaultResolver; @@ -231,24 +231,24 @@ public Iterable keys() throws RiakException { * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, * java.lang.String) */ - public StoreObject store(final String key, final String value) { + public StoreObject store(final String key, final String value) { final Bucket b = this; - return new StoreObject(client, name, key).withMutator(new Mutation() { - public RiakObject apply(RiakObject original) { + return new StoreObject(client, name, key).withMutator(new Mutation() { + public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(b.getName(), key).withValue(value).build(); } else { return original.setValue(value); } } - }).withResolver(new DefaultResolver()).withConverter(new Converter() { + }).withResolver(new DefaultResolver()).withConverter(new Converter() { - public RiakObject toDomain(RiakObject riakObject) { + public IRiakObject toDomain(IRiakObject riakObject) { return riakObject; } - public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { + public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { return domainObject; } }); @@ -318,16 +318,16 @@ public FetchObject fetch(final String key, final Class type) { * * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) */ - public FetchObject fetch(String key) { - return new FetchObject(client, name, key) - .withResolver(new DefaultResolver()) - .withConverter(new Converter() { + public FetchObject fetch(String key) { + return new FetchObject(client, name, key) + .withResolver(new DefaultResolver()) + .withConverter(new Converter() { - public RiakObject toDomain(RiakObject riakObject) { + public IRiakObject toDomain(IRiakObject riakObject) { return riakObject; } - public RiakObject fromDomain(RiakObject domainObject, + public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { return RiakObjectBuilder.from(domainObject).withVClock(vclock).build(); diff --git a/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java b/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java index fc1749b00..ae0e33f25 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java @@ -14,7 +14,7 @@ package com.basho.riak.newapi.bucket; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.builders.DomainBucketBuilder; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; @@ -28,19 +28,19 @@ */ public class RiakBucket { - private final DomainBucket delegate; + private final DomainBucket delegate; private final Bucket bucket; public static RiakBucket newRiakBucket(final Bucket b) { // create a DomainBucket as a delegate - DomainBucketBuilder builder = DomainBucket.builder(b, RiakObject.class); - builder.withConverter(new Converter() { + DomainBucketBuilder builder = DomainBucket.builder(b, IRiakObject.class); + builder.withConverter(new Converter() { // no conversion required - public RiakObject toDomain(RiakObject riakObject) throws ConversionException { + public IRiakObject toDomain(IRiakObject riakObject) throws ConversionException { return riakObject; } - public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws ConversionException { + public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { return domainObject; } }); @@ -48,7 +48,7 @@ public RiakObject fromDomain(RiakObject domainObject, VClock vclock) throws Conv return new RiakBucket(builder.build(), b); } - private RiakBucket(final DomainBucket delegate, final Bucket bucket) { + private RiakBucket(final DomainBucket delegate, final Bucket bucket) { this.delegate = delegate; this.bucket = bucket; } @@ -59,7 +59,7 @@ private RiakBucket(final DomainBucket delegate, final Bucket bucket) * @throws RiakException * @see com.basho.riak.newapi.bucket.DomainBucket#store(java.lang.Object) */ - public RiakObject store(RiakObject o) throws RiakException { + public IRiakObject store(IRiakObject o) throws RiakException { return delegate.store(o); } @@ -70,7 +70,7 @@ public RiakObject store(RiakObject o) throws RiakException { * @return * @throws RiakException */ - public RiakObject store(String key, String value) throws RiakException { + public IRiakObject store(String key, String value) throws RiakException { return delegate.store(RiakObjectBuilder.newBuilder(bucket.getName(), key).withValue(value).build()); } /** @@ -79,7 +79,7 @@ public RiakObject store(String key, String value) throws RiakException { * @throws RiakException * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.String) */ - public RiakObject fetch(String key) throws RiakException { + public IRiakObject fetch(String key) throws RiakException { return delegate.fetch(key); } @@ -89,7 +89,7 @@ public RiakObject fetch(String key) throws RiakException { * @throws RiakException * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.Object) */ - public RiakObject fetch(RiakObject o) throws RiakException { + public IRiakObject fetch(IRiakObject o) throws RiakException { return delegate.fetch(o); } @@ -98,7 +98,7 @@ public RiakObject fetch(RiakObject o) throws RiakException { * @throws RiakException * @see com.basho.riak.newapi.bucket.DomainBucket#delete(java.lang.Object) */ - public void delete(RiakObject o) throws RiakException { + public void delete(IRiakObject o) throws RiakException { delegate.delete(o); } diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java index 6593d5b1f..90bbf497a 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -19,10 +19,9 @@ import java.util.HashMap; import java.util.Map; -import com.basho.riak.newapi.DefaultRiakLink; -import com.basho.riak.newapi.DefaultRiakObject; import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.cap.BasicVClock; import com.basho.riak.newapi.cap.VClock; @@ -50,7 +49,7 @@ public static RiakObjectBuilder newBuilder(String bucket, String key) { return new RiakObjectBuilder(bucket, key); } - public static RiakObjectBuilder from(RiakObject o) { + public static RiakObjectBuilder from(IRiakObject o) { RiakObjectBuilder rob = new RiakObjectBuilder(o.getBucket(), o.getKey()); rob.vclock = o.getVClock(); rob.contentType = o.getContentType(); @@ -61,8 +60,8 @@ public static RiakObjectBuilder from(RiakObject o) { return rob; } - public RiakObject build() { - return new DefaultRiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); + public IRiakObject build() { + return new RiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); } public RiakObjectBuilder withValue(String value) { @@ -94,7 +93,7 @@ public RiakObjectBuilder withLinks(Collection links) { public RiakObjectBuilder addLink(String bucket, String key, String tag) { synchronized (links) { - links.add(new DefaultRiakLink(bucket, key, tag)); + links.add(new RiakLink(bucket, key, tag)); } return this; } diff --git a/src/main/java/com/basho/riak/newapi/cap/Quorum.java b/src/main/java/com/basho/riak/newapi/cap/Quorum.java index af7064ca4..a7b13679d 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Quorum.java +++ b/src/main/java/com/basho/riak/newapi/cap/Quorum.java @@ -13,6 +13,11 @@ */ package com.basho.riak.newapi.cap; +/** + * TODO needs further definition and accessor methods. + * + * @author russell + */ public final class Quorum { private Integer i; private Quora quorum; diff --git a/src/main/java/com/basho/riak/newapi/convert/Converter.java b/src/main/java/com/basho/riak/newapi/convert/Converter.java index f5b7ba28d..a73c09aa8 100644 --- a/src/main/java/com/basho/riak/newapi/convert/Converter.java +++ b/src/main/java/com/basho/riak/newapi/convert/Converter.java @@ -13,7 +13,7 @@ */ package com.basho.riak.newapi.convert; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.cap.VClock; /** @@ -28,7 +28,7 @@ public interface Converter { * @param domainObject * @return a RiakObject populated from domainObject */ - RiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException; + IRiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException; /** * Convert from a riakObject to a domain specific instance @@ -37,6 +37,6 @@ public interface Converter { * the RiakObject to convert * @return an instance of type T */ - T toDomain(RiakObject riakObject) throws ConversionException; + T toDomain(IRiakObject riakObject) throws ConversionException; } diff --git a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java index ccbbd9f12..a595fd9e7 100644 --- a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java +++ b/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java @@ -21,7 +21,7 @@ import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.ObjectMapper; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.builders.RiakObjectBuilder; import com.basho.riak.newapi.cap.VClock; @@ -60,7 +60,7 @@ public JSONConverter(Class clazz, String b, String defaultKey) { * @see com.basho.riak.newapi.convert.Converter#fromDomain(java.lang.Object, * VClock) */ - public RiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException { + public IRiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException { try { String key = getKey(domainObject, this.defaultKey); @@ -87,7 +87,7 @@ public RiakObject fromDomain(T domainObject, VClock vclock) throws ConversionExc * com.basho.riak.newapi.convert.Converter#toDomain(com.basho.riak.newapi * .RiakObject) */ - public T toDomain(RiakObject riakObject) throws ConversionException { + public T toDomain(IRiakObject riakObject) throws ConversionException { if (riakObject == null) { return null; } diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java index 38905c784..43505a20e 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/FetchObject.java @@ -20,7 +20,7 @@ import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.DefaultRetrier; @@ -74,7 +74,7 @@ public RiakResponse execute() throws IOException { final RiakResponse ros = new DefaultRetrier().attempt(command, retries); final Collection siblings = new ArrayList(ros.numberOfValues()); - for (RiakObject o : ros) { + for (IRiakObject o : ros) { siblings.add(converter.toDomain(o)); } diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java index 3a4823cae..6cc9d9360 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/newapi/operations/StoreObject.java @@ -22,7 +22,7 @@ import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.RiakRetryFailedException; import com.basho.riak.newapi.cap.ConflictResolver; import com.basho.riak.newapi.cap.DefaultRetrier; @@ -82,13 +82,13 @@ public RiakResponse execute() throws IOException { final RiakResponse ros = new DefaultRetrier().attempt(command, retries); final Collection siblings = new ArrayList(ros.numberOfValues()); - for (RiakObject o : ros) { + for (IRiakObject o : ros) { siblings.add(converter.toDomain(o)); } final T resolved = resolver.resolve(siblings); final T mutated = mutation.apply(resolved); - final RiakObject o = converter.fromDomain(mutated, ros.getVclock()); + final IRiakObject o = converter.fromDomain(mutated, ros.getVclock()); final RiakResponse stored = new DefaultRetrier().attempt(new Command() { public RiakResponse execute() throws IOException { @@ -98,7 +98,7 @@ public RiakResponse execute() throws IOException { final Collection storedSiblings = new ArrayList(stored.numberOfValues()); - for (RiakObject s : stored) { + for (IRiakObject s : stored) { storedSiblings.add(converter.toDomain(s)); } diff --git a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java index b58b4f41f..36f7e4e47 100644 --- a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java +++ b/src/main/java/com/basho/riak/newapi/query/LinkWalk.java @@ -19,7 +19,7 @@ import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.operations.RiakOperation; import com.basho.riak.newapi.query.LinkWalkStep.Accumulate; @@ -38,7 +38,7 @@ public class LinkWalk implements RiakOperation { /** * @param startObject */ - public LinkWalk(final RawClient client, final RiakObject startObject) { + public LinkWalk(final RawClient client, final IRiakObject startObject) { this.client = client; this.startBucket = startObject.getBucket(); this.startKey = startObject.getKey(); diff --git a/src/main/java/com/basho/riak/newapi/query/WalkResult.java b/src/main/java/com/basho/riak/newapi/query/WalkResult.java index d466841bc..dac02d230 100644 --- a/src/main/java/com/basho/riak/newapi/query/WalkResult.java +++ b/src/main/java/com/basho/riak/newapi/query/WalkResult.java @@ -15,12 +15,12 @@ import java.util.Collection; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; /** * * @author russell * */ -public interface WalkResult extends Iterable> { +public interface WalkResult extends Iterable> { } diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index c02fa241b..7fe9d452b 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -35,9 +35,9 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.cap.UnresolvedConflictException; import com.basho.riak.newapi.convert.NoKeySpecifedException; @@ -50,22 +50,22 @@ */ public abstract class ITestBucket { - protected RiakClient client; + protected IRiakClient client; @Before public void setUp() throws RiakException { client = getClient(); } - protected abstract RiakClient getClient() throws RiakException; + protected abstract IRiakClient getClient() throws RiakException; @Test public void basicStore() throws Exception { final String bucketName = UUID.randomUUID().toString(); Bucket b = client.fetchBucket(bucketName).execute(); - RiakObject o = b.store("k", "v").execute(); + IRiakObject o = b.store("k", "v").execute(); assertNull(o); - RiakObject fetched = b.fetch("k").execute(); + IRiakObject fetched = b.fetch("k").execute(); assertEquals("v", fetched.getValue()); // now update that riak object @@ -94,7 +94,7 @@ public abstract class ITestBucket { final ExecutorService es = Executors.newFixedThreadPool(numThreads); for (int i = 0; i < numThreads; i++) { - final RiakClient c = getClient(); + final IRiakClient c = getClient(); c.generateAndSetClientId(); final Bucket bucket = c.fetchBucket(bucketName).execute(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java index c0183eea2..086c7160a 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java @@ -24,7 +24,7 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.bucket.Bucket; @@ -34,7 +34,7 @@ */ public abstract class ITestClientBasic { - protected RiakClient client; + protected IRiakClient client; @Before public void setUp() throws RiakException { this.client = getClient(); @@ -43,7 +43,7 @@ public abstract class ITestClientBasic { /** * @return */ - protected abstract RiakClient getClient() throws RiakException; + protected abstract IRiakClient getClient() throws RiakException; @Test public void fetchBucket() throws RiakException { final String bucketName = UUID.randomUUID().toString(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java index 04c56ec84..d67be08d8 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java @@ -28,7 +28,7 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.DomainBucket; @@ -44,13 +44,13 @@ */ public abstract class ITestDomainBucket { - protected RiakClient client; + protected IRiakClient client; @Before public void setUp() throws RiakException { this.client = getClient(); } - public abstract RiakClient getClient() throws RiakException; + public abstract IRiakClient getClient() throws RiakException; @Test public void useDomainBucket() throws Exception { final String bucketName = UUID.randomUUID().toString() + "_carts"; diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java index a41310a17..7f0eb3c65 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestDomainBucketHTTP extends ITestDomainBucket { * * @see com.basho.riak.client.itest.ITestDomainBucket#getClient() */ - @Override public RiakClient getClient() throws RiakException { + @Override public IRiakClient getClient() throws RiakException { // com.basho.riak.client.RiakClient riakClient = new // com.basho.riak.client.RiakClient("http://127.0.0.1:8098/riak"); // riakClient.getHttpClient().getHostConfiguration().setProxy("127.0.0.1", diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java index 04bc3f589..260989552 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestDomainBucketPB extends ITestDomainBucket { * * @see com.basho.riak.client.itest.ITestDomainBucket#getClient() */ - @Override public RiakClient getClient() throws RiakException { + @Override public IRiakClient getClient() throws RiakException { return RiakFactory.pbcClient(); } diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java index aa0e5b95a..6d69e777b 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestHTTPBucket extends ITestBucket { * * @see com.basho.riak.client.itest.ITestBucket#getClient() */ - @Override protected RiakClient getClient() throws RiakException { + @Override protected IRiakClient getClient() throws RiakException { return RiakFactory.httpClient(); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java index c2eb72c2a..3fd234df0 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java @@ -19,10 +19,11 @@ import org.junit.Test; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.newapi.cap.Quora; import com.basho.riak.newapi.query.functions.NamedErlangFunction; /** @@ -36,7 +37,7 @@ public class ITestHTTPClient extends ITestClientBasic { * * @see com.basho.riak.client.itest.ITestClient#getClient() */ - @Override protected RiakClient getClient() throws RiakException { + @Override protected IRiakClient getClient() throws RiakException { return RiakFactory.httpClient(); } @@ -79,10 +80,22 @@ public class ITestHTTPClient extends ITestClientBasic { final String bucketName = UUID.randomUUID().toString(); - Bucket b = client.createBucket(bucketName).chashKeyFunction(newChashkeyFun).linkWalkFunction(newLinkwalkFun).execute(); + Bucket b = client.createBucket(bucketName) + .chashKeyFunction(newChashkeyFun) + .linkWalkFunction(newLinkwalkFun) + .r(Quora.ALL) + .w(2) + .dw(Quora.QUORUM) + .rw(1) + .execute(); assertEquals(newChashkeyFun, b.getChashKeyFunction()); assertEquals(newLinkwalkFun, b.getLinkWalkFunction()); + // TODO add extra properties to underlying transports, and expose them + // assertEquals(Quora.ALL, b.getR()); + // assertEquals(2, b.getW()); + // assertEquals(Quora.QUORUM, b.getDW()); + // assertEquals(1, b.getRW()); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java index a540c57ee..b49ab67f2 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java +++ b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java @@ -24,10 +24,10 @@ import org.junit.Test; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.RiakBucket; import com.basho.riak.newapi.builders.RiakObjectBuilder; @@ -40,7 +40,7 @@ public class ITestLinkWalk { @Test public void test_walk() throws RiakException { - final RiakClient client = RiakFactory.pbcClient(); + final IRiakClient client = RiakFactory.pbcClient(); final String fooVal = "fooer"; final String barVal = "barrer"; @@ -58,26 +58,26 @@ public class ITestLinkWalk { final Bucket b = client.createBucket(bucketName).execute(); final RiakBucket bucket = RiakBucket.newRiakBucket(b); - RiakObject o1 = RiakObjectBuilder.newBuilder(bucketName, first[0]).withValue(first[1]).addLink(bucketName, + IRiakObject o1 = RiakObjectBuilder.newBuilder(bucketName, first[0]).withValue(first[1]).addLink(bucketName, second[0], fooTag).addLink(bucketName, third[0], barTag).build(); - RiakObject o2 = RiakObjectBuilder.newBuilder(bucketName, second[0]).withValue(second[1]).addLink(bucketName, + IRiakObject o2 = RiakObjectBuilder.newBuilder(bucketName, second[0]).withValue(second[1]).addLink(bucketName, fourth[0], fooTag).build(); - RiakObject o3 = RiakObjectBuilder.newBuilder(bucketName, third[0]).withValue(third[1]).addLink(bucketName, + IRiakObject o3 = RiakObjectBuilder.newBuilder(bucketName, third[0]).withValue(third[1]).addLink(bucketName, fourth[0], fooTag).build(); - RiakObject o4 = RiakObjectBuilder.newBuilder(bucketName, fourth[0]).withValue(fourth[1]).addLink(bucketName, + IRiakObject o4 = RiakObjectBuilder.newBuilder(bucketName, fourth[0]).withValue(fourth[1]).addLink(bucketName, fith[0], barTag). addUsermeta("metaKey", "123").build(); - RiakObject o5 = RiakObjectBuilder.newBuilder(bucketName, fith[0]).withValue(fith[1]).build(); + IRiakObject o5 = RiakObjectBuilder.newBuilder(bucketName, fith[0]).withValue(fith[1]).build(); bucket.store(o1); bucket.store(o2); @@ -91,9 +91,9 @@ public class ITestLinkWalk { int stepsCnt = 0; List keys = new ArrayList(); - for (Collection s : result) { + for (Collection s : result) { - for (RiakObject object : s) { + for (IRiakObject object : s) { keys.add(object.getKey()); assertEquals(fooVal, object.getValue()); } diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java index e38557a14..807b41de0 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -30,11 +30,10 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.basho.riak.newapi.DefaultRiakLink; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.RiakLink; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.bucket.Bucket; import com.basho.riak.newapi.bucket.DomainBucket; import com.basho.riak.newapi.bucket.RiakBucket; @@ -52,7 +51,7 @@ * */ public abstract class ITestMapReduce { - protected RiakClient client; + protected IRiakClient client; @Before public void setUp() throws RiakException { client = getClient(); @@ -62,13 +61,13 @@ public abstract class ITestMapReduce { * @return * @throws RiakException */ - protected abstract RiakClient getClient() throws RiakException; + protected abstract IRiakClient getClient() throws RiakException; public static final String BUCKET_NAME = "mr_test_java"; public static final int TEST_ITEMS = 200; @BeforeClass public static void setup() throws RiakException { - final RiakClient client = RiakFactory.pbcClient(); + final IRiakClient client = RiakFactory.pbcClient(); final Bucket bucket = client.createBucket(BUCKET_NAME).execute(); final RiakBucket b = RiakBucket.newRiakBucket(bucket); @@ -76,7 +75,7 @@ public abstract class ITestMapReduce { RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(BUCKET_NAME, "java_" + Integer.toString(i)); builder.withContentType("text/plain").withValue(Integer.toString(i)); if (i < TEST_ITEMS - 1) { - RiakLink link = new DefaultRiakLink(BUCKET_NAME, "java_" + Integer.toString(i + 1), "test"); + RiakLink link = new RiakLink(BUCKET_NAME, "java_" + Integer.toString(i + 1), "test"); List links = new ArrayList(1); links.add(link); builder.withLinks(links); @@ -87,7 +86,7 @@ public abstract class ITestMapReduce { } @AfterClass public static void teardown() throws RiakException { - final RiakClient client = RiakFactory.pbcClient(); + final IRiakClient client = RiakFactory.pbcClient(); final Bucket b = client.fetchBucket(BUCKET_NAME).execute(); for (int i = 0; i < TEST_ITEMS; i++) { diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java index 7d95a7991..46f590bb3 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestMapReduceHTTP extends ITestMapReduce { * * @see com.basho.riak.client.itest.ITestMapReduce#getClient() */ - protected RiakClient getClient() throws RiakException { + protected IRiakClient getClient() throws RiakException { return RiakFactory.httpClient(); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java index 8edacb110..4e20f9e63 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestMapReducePB extends ITestMapReduce { * * @see com.basho.riak.client.itest.ITestMapReduce#getClient() */ - protected RiakClient getClient() throws RiakException { + protected IRiakClient getClient() throws RiakException { return RiakFactory.pbcClient(); } } diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java index bbbcdde11..2009d57b5 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestPBBucket extends ITestBucket { * * @see com.basho.riak.client.itest.ITestBucket#getClient() */ - @Override protected RiakClient getClient() throws RiakException { + @Override protected IRiakClient getClient() throws RiakException { return RiakFactory.pbcClient(); } diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java index ea7ec49a1..ccf7d6f93 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.RiakClient; +import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; @@ -28,7 +28,7 @@ public class ITestPBClient extends ITestClientBasic { * * @see com.basho.riak.client.itest.ITestClient#getClient() */ - @Override protected RiakClient getClient() throws RiakException { + @Override protected IRiakClient getClient() throws RiakException { return RiakFactory.pbcClient(); } diff --git a/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java index dc49832b3..cf8261246 100644 --- a/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java +++ b/src/test/java/com/basho/riak/client/raw/http/TestKeySource.java @@ -23,8 +23,8 @@ import org.junit.Test; -import com.basho.riak.client.RiakBucketInfo; -import com.basho.riak.client.response.BucketResponse; +import com.basho.riak.client.http.RiakBucketInfo; +import com.basho.riak.client.http.response.BucketResponse; /** * @author russell From 6772599457935a6f7c78c87904dac8f459ef6238 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 4 May 2011 09:53:42 +0100 Subject: [PATCH 022/764] Rename classes for merge of legacy client API --- .../riak/{newapi => client}/RiakLink.java | 2 +- .../riak/client/raw/http/ConversionUtil.java | 2 +- .../riak/client/raw/pbc/ConversionUtil.java | 2 +- ...RiakClient.java => DefaultRiakClient.java} | 4 +-- ...RiakObject.java => DefaultRiakObject.java} | 31 ++++++++++++------- .../com/basho/riak/newapi/IRiakObject.java | 11 ++++--- .../com/basho/riak/newapi/RiakFactory.java | 8 ++--- .../riak/newapi/bucket/DefaultBucket.java | 3 +- .../newapi/builders/RiakObjectBuilder.java | 6 ++-- .../riak/client/itest/ITestMapReduce.java | 2 +- 10 files changed, 40 insertions(+), 31 deletions(-) rename src/main/java/com/basho/riak/{newapi => client}/RiakLink.java (99%) rename src/main/java/com/basho/riak/newapi/{RiakClient.java => DefaultRiakClient.java} (96%) rename src/main/java/com/basho/riak/newapi/{RiakObject.java => DefaultRiakObject.java} (92%) diff --git a/src/main/java/com/basho/riak/newapi/RiakLink.java b/src/main/java/com/basho/riak/client/RiakLink.java similarity index 99% rename from src/main/java/com/basho/riak/newapi/RiakLink.java rename to src/main/java/com/basho/riak/client/RiakLink.java index 46128f971..3f4633232 100644 --- a/src/main/java/com/basho/riak/newapi/RiakLink.java +++ b/src/main/java/com/basho/riak/client/RiakLink.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; /** * Immutable RiakLink diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index 4b65c165c..befa61a48 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -28,6 +28,7 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; +import com.basho.riak.client.RiakLink; import com.basho.riak.client.http.RiakBucketInfo; import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.raw.StoreMeta; @@ -38,7 +39,6 @@ import com.basho.riak.client.http.response.MapReduceResponse; import com.basho.riak.client.http.response.WalkResponse; import com.basho.riak.client.http.util.Constants; -import com.basho.riak.newapi.RiakLink; import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.bucket.BucketProperties; import com.basho.riak.newapi.bucket.DefaultBucketProperties; diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index cf4005a5e..16c35e2b0 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -156,7 +156,7 @@ static com.basho.riak.pbc.RiakObject convert(IRiakObject riakObject) { com.basho.riak.pbc.RiakObject result = new com.basho.riak.pbc.RiakObject(vclock, bucketName, key, content); - for (com.basho.riak.newapi.RiakLink link : riakObject) { + for (com.basho.riak.client.RiakLink link : riakObject) { result.addLink(link.getTag(), link.getBucket(), link.getKey()); } diff --git a/src/main/java/com/basho/riak/newapi/RiakClient.java b/src/main/java/com/basho/riak/newapi/DefaultRiakClient.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/RiakClient.java rename to src/main/java/com/basho/riak/newapi/DefaultRiakClient.java index e816f2f75..412e89d8f 100644 --- a/src/main/java/com/basho/riak/newapi/RiakClient.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakClient.java @@ -25,14 +25,14 @@ * @author russell * */ -public final class RiakClient implements IRiakClient { +public final class DefaultRiakClient implements IRiakClient { private final RawClient client; /** * @param client */ - RiakClient(RawClient client) { + DefaultRiakClient(RawClient client) { this.client = client; } diff --git a/src/main/java/com/basho/riak/newapi/RiakObject.java b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/RiakObject.java rename to src/main/java/com/basho/riak/newapi/DefaultRiakObject.java index 2da587313..e87789f3f 100644 --- a/src/main/java/com/basho/riak/newapi/RiakObject.java +++ b/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java @@ -19,11 +19,13 @@ import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; -import com.basho.riak.client.http.HttpRiakObject; +import com.basho.riak.client.RiakLink; import com.basho.riak.newapi.cap.VClock; import com.basho.riak.newapi.convert.RiakKey; +import com.basho.riak.newapi.util.UnmodifiableIterator; /** * An implementation of {@link IRiakObject} that also contains the deprecated @@ -34,7 +36,7 @@ * * @author russell */ -public class RiakObject implements IRiakObject { +public class DefaultRiakObject implements IRiakObject { public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; @@ -67,7 +69,7 @@ public class RiakObject implements IRiakObject { * @param links * @param userMeta */ - public RiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, + public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, String contentType, String value, final Collection links, final Map userMeta) { if (bucket == null) { @@ -119,10 +121,6 @@ private void safeSetContentType(String contentType) { } } - public Iterator iterator() { - return links.iterator(); - } - public String getBucket() { return bucket; } @@ -163,16 +161,22 @@ public String getValue() { // mutate - public IRiakObject setValue(String value) { + public void setValue(String value) { this.value = value; - return this; } - public IRiakObject setContentType(String contentType) { + public void setContentType(String contentType) { this.contentType = contentType; - return this; } + /** + * an UnmodifiableIterator view on the RiakLinks + */ + public Iterator iterator() { + return new UnmodifiableIterator(getLinks().iterator()); + } + + /** * Add link to this RiakObject's links. * @@ -225,7 +229,10 @@ public int numLinks() { } } - public Collection getLinks() { + /** + * Return a copy of the links. + */ + public List getLinks() { synchronized (linksLock) { return new ArrayList(links); } diff --git a/src/main/java/com/basho/riak/newapi/IRiakObject.java b/src/main/java/com/basho/riak/newapi/IRiakObject.java index 3823883d8..bb6b3dcdb 100644 --- a/src/main/java/com/basho/riak/newapi/IRiakObject.java +++ b/src/main/java/com/basho/riak/newapi/IRiakObject.java @@ -13,11 +13,12 @@ */ package com.basho.riak.newapi; -import java.util.Collection; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Map.Entry; +import com.basho.riak.client.RiakLink; import com.basho.riak.newapi.cap.VClock; /** @@ -27,7 +28,7 @@ * laid claim to the best name real estate. * This class will be named RiakObject in subsequent releases. * - * @see RiakObject in the legacy project + * @see DefaultRiakObject in the legacy project * @author russell * */ @@ -48,7 +49,7 @@ public interface IRiakObject extends Iterable { String getContentType(); // links - Collection getLinks(); + List getLinks(); boolean hasLinks(); @@ -69,9 +70,9 @@ public interface IRiakObject extends Iterable { // Mutate - IRiakObject setValue(String value); + void setValue(String value); - IRiakObject setContentType(String contentType); + void setContentType(String contentType); /** * Add link to this RiakObject's links. diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/newapi/RiakFactory.java index 7c4c50a12..3d9fe5076 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/newapi/RiakFactory.java @@ -39,7 +39,7 @@ public static IRiakClient pbcClient() throws RiakException { try { final RawClient client = new PBClientAdapter("127.0.0.1", 8087); - return new RiakClient(client); + return new DefaultRiakClient(client); } catch (IOException e) { throw new RiakException(e); } @@ -52,7 +52,7 @@ public static IRiakClient pbcClient() throws RiakException { */ public static IRiakClient pbcClient(com.basho.riak.pbc.RiakClient delegate) { final RawClient client = new PBClientAdapter(delegate); - return new RiakClient(client); + return new DefaultRiakClient(client); } /** @@ -60,7 +60,7 @@ public static IRiakClient pbcClient(com.basho.riak.pbc.RiakClient delegate) { */ public static IRiakClient httpClient() throws RiakException { final RawClient client = new HTTPClientAdapter(DEFAULT_RIAK_URL); - return new RiakClient(client); + return new DefaultRiakClient(client); } /** @@ -68,7 +68,7 @@ public static IRiakClient httpClient() throws RiakException { */ public static IRiakClient httpClient(com.basho.riak.client.http.RiakClient delegate) throws RiakException { final RawClient client = new HTTPClientAdapter(delegate); - return new RiakClient(client); + return new DefaultRiakClient(client); } } diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java index 260128242..e883b1d99 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java @@ -239,7 +239,8 @@ public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(b.getName(), key).withValue(value).build(); } else { - return original.setValue(value); + original.setValue(value); + return original; } } }).withResolver(new DefaultResolver()).withConverter(new Converter() { diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java index 90bbf497a..55a500398 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java @@ -19,8 +19,8 @@ import java.util.HashMap; import java.util.Map; -import com.basho.riak.newapi.RiakLink; -import com.basho.riak.newapi.RiakObject; +import com.basho.riak.client.RiakLink; +import com.basho.riak.newapi.DefaultRiakObject; import com.basho.riak.newapi.IRiakObject; import com.basho.riak.newapi.cap.BasicVClock; import com.basho.riak.newapi.cap.VClock; @@ -61,7 +61,7 @@ public static RiakObjectBuilder from(IRiakObject o) { } public IRiakObject build() { - return new RiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); + return new DefaultRiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); } public RiakObjectBuilder withValue(String value) { diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java index 807b41de0..95163be5c 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -30,7 +30,7 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.basho.riak.newapi.RiakLink; +import com.basho.riak.client.RiakLink; import com.basho.riak.newapi.IRiakClient; import com.basho.riak.newapi.RiakException; import com.basho.riak.newapi.RiakFactory; From ab21df38df1d0c7e7b2bde1ab6663430ca147c13 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 4 May 2011 10:55:12 +0100 Subject: [PATCH 023/764] Move all new api code into correct client package for merge --- .../{newapi => client}/DefaultRiakClient.java | 16 ++++---- .../{newapi => client}/DefaultRiakObject.java | 9 ++--- .../riak/{newapi => client}/IRiakClient.java | 16 ++++---- .../riak/{newapi => client}/IRiakObject.java | 5 +-- .../{newapi => client}/RiakException.java | 2 +- .../riak/{newapi => client}/RiakFactory.java | 2 +- .../RiakRetryFailedException.java | 2 +- .../{newapi => client}/bucket/Bucket.java | 12 +++--- .../bucket/BucketProperties.java | 8 ++-- .../bucket/DefaultBucket.java | 38 +++++++++---------- .../bucket/DefaultBucketProperties.java | 10 ++--- .../bucket/DomainBucket.java | 16 ++++---- .../bucket/FetchBucket.java | 8 ++-- .../{newapi => client}/bucket/RiakBucket.java | 26 ++++++------- .../bucket/WriteBucket.java | 16 ++++---- .../builders/DomainBucketBuilder.java | 22 +++++------ .../builders/RiakObjectBuilder.java | 10 ++--- .../{newapi => client}/cap/BasicVClock.java | 2 +- .../riak/{newapi => client}/cap/ClientId.java | 2 +- .../cap/ClobberMutation.java | 2 +- .../cap/ConflictResolver.java | 2 +- .../cap/DefaultResolver.java | 2 +- .../cap/DefaultRetrier.java | 4 +- .../riak/{newapi => client}/cap/Mutation.java | 2 +- .../cap/MutationProducer.java | 2 +- .../riak/{newapi => client}/cap/Quora.java | 2 +- .../riak/{newapi => client}/cap/Quorum.java | 2 +- .../riak/{newapi => client}/cap/Retrier.java | 4 +- .../cap/UnresolvedConflictException.java | 4 +- .../riak/{newapi => client}/cap/VClock.java | 2 +- .../convert/ConversionException.java | 4 +- .../{newapi => client}/convert/Converter.java | 6 +-- .../convert/JSONConverter.java | 10 ++--- .../{newapi => client}/convert/KeyUtil.java | 2 +- .../convert/NoKeySpecifedException.java | 2 +- .../{newapi => client}/convert/RiakKey.java | 2 +- .../operations/DeleteObject.java | 6 +-- .../operations/FetchObject.java | 16 ++++---- .../operations/RiakOperation.java | 4 +- .../operations/StoreObject.java | 20 +++++----- .../query/BucketKeyMapReduce.java | 2 +- .../query/BucketMapReduce.java | 4 +- .../{newapi => client}/query/LinkPhase.java | 2 +- .../{newapi => client}/query/LinkWalk.java | 10 ++--- .../query/LinkWalkStep.java | 2 +- .../{newapi => client}/query/MapPhase.java | 4 +- .../{newapi => client}/query/MapReduce.java | 10 ++--- .../query/MapReducePhase.java | 2 +- .../query/MapReduceResult.java | 4 +- .../{newapi => client}/query/ReducePhase.java | 4 +- .../{newapi => client}/query/WalkResult.java | 4 +- .../query/filter/AbstractKeyFilter.java | 2 +- .../query/filter/AbstractLogicalFilter.java | 2 +- .../query/filter/BetweenFilter.java | 2 +- .../query/filter/EndsWithFilter.java | 2 +- .../query/filter/EqualToFilter.java | 2 +- .../query/filter/FloatToStringFilter.java | 2 +- .../query/filter/GreaterThanFilter.java | 2 +- .../filter/GreaterThanOrEqualFilter.java | 2 +- .../query/filter/IntToStringFilter.java | 2 +- .../query/filter/KeyFilter.java | 2 +- .../query/filter/KeyTransformFilter.java | 2 +- .../query/filter/LessThanFilter.java | 2 +- .../query/filter/LessThanOrEqualFilter.java | 2 +- .../query/filter/LogicalAndFilter.java | 2 +- .../query/filter/LogicalFilter.java | 2 +- .../query/filter/LogicalFilterGroup.java | 2 +- .../query/filter/LogicalNotFilter.java | 2 +- .../query/filter/LogicalOrFilter.java | 2 +- .../query/filter/MatchFilter.java | 2 +- .../query/filter/NotEqualToFilter.java | 2 +- .../query/filter/SetMemberFilter.java | 2 +- .../query/filter/SimilarToFilter.java | 2 +- .../query/filter/StartsWithFilter.java | 2 +- .../query/filter/StringToFloatFilter.java | 2 +- .../query/filter/StringToIntFilter.java | 2 +- .../query/filter/ToLowerFilter.java | 2 +- .../query/filter/ToUpperFilter.java | 2 +- .../query/filter/TokenizeFilter.java | 2 +- .../query/filter/UrlDecodeFilter.java | 2 +- .../query/functions/AnonymousFunction.java | 2 +- .../query/functions/Function.java | 2 +- .../query/functions/JSBucketKeyFunction.java | 2 +- .../query/functions/JSSourceFunction.java | 2 +- .../query/functions/NamedErlangFunction.java | 2 +- .../query/functions/NamedFunction.java | 2 +- .../query/functions/NamedJSFunction.java | 2 +- .../query/serialize/FunctionToJson.java | 12 +++--- .../query/serialize/FunctionWriter.java | 2 +- .../serialize/JSBucketKeyFunctionWriter.java | 4 +- .../serialize/JSSourceFunctionWriter.java | 4 +- .../serialize/NamedErlangFunctionWriter.java | 4 +- .../serialize/NamedJSFunctionWriter.java | 4 +- .../com/basho/riak/client/raw/RawClient.java | 8 ++-- .../basho/riak/client/raw/RiakResponse.java | 6 +-- .../riak/client/raw/http/ConversionUtil.java | 20 +++++----- .../client/raw/http/HTTPClientAdapter.java | 10 ++--- .../riak/client/raw/pbc/ConversionUtil.java | 20 +++++----- .../riak/client/raw/pbc/PBClientAdapter.java | 20 +++++----- .../riak/client/raw/query/LinkWalkSpec.java | 4 +- .../raw/query/MapReduceTimeoutException.java | 2 +- .../util/UnmodifiableIterator.java | 2 +- .../cap/ClobberMutationTest.java | 6 ++- .../convert/ConversionUtilTest.java | 5 ++- .../basho/riak/client/itest/ITestBucket.java | 12 +++--- .../riak/client/itest/ITestClientBasic.java | 6 +-- .../riak/client/itest/ITestDomainBucket.java | 8 ++-- .../client/itest/ITestDomainBucketHTTP.java | 6 +-- .../client/itest/ITestDomainBucketPB.java | 6 +-- .../riak/client/itest/ITestHTTPBucket.java | 6 +-- .../riak/client/itest/ITestHTTPClient.java | 12 +++--- .../riak/client/itest/ITestLinkWalk.java | 16 ++++---- .../riak/client/itest/ITestMapReduce.java | 26 ++++++------- .../riak/client/itest/ITestMapReduceHTTP.java | 6 +-- .../riak/client/itest/ITestMapReducePB.java | 6 +-- .../riak/client/itest/ITestPBBucket.java | 6 +-- .../riak/client/itest/ITestPBClient.java | 6 +-- .../query/filter/LogicalAndFilterTest.java | 11 +++++- .../query/serialize/FunctionToJsonTest.java | 18 ++++++--- .../commerce/GoogleStockDataItem.java | 2 +- .../megacorp/commerce/MergeCartResolver.java | 4 +- .../com/megacorp/commerce/ShoppingCart.java | 2 +- .../MyCheckedBusinessException.java | 2 +- 123 files changed, 376 insertions(+), 360 deletions(-) rename src/main/java/com/basho/riak/{newapi => client}/DefaultRiakClient.java (88%) rename src/main/java/com/basho/riak/{newapi => client}/DefaultRiakObject.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/IRiakClient.java (79%) rename src/main/java/com/basho/riak/{newapi => client}/IRiakObject.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/RiakException.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/RiakFactory.java (98%) rename src/main/java/com/basho/riak/{newapi => client}/RiakRetryFailedException.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/Bucket.java (79%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/BucketProperties.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/DefaultBucket.java (90%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/DefaultBucketProperties.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/DomainBucket.java (89%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/FetchBucket.java (88%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/RiakBucket.java (80%) rename src/main/java/com/basho/riak/{newapi => client}/bucket/WriteBucket.java (91%) rename src/main/java/com/basho/riak/{newapi => client}/builders/DomainBucketBuilder.java (88%) rename src/main/java/com/basho/riak/{newapi => client}/builders/RiakObjectBuilder.java (94%) rename src/main/java/com/basho/riak/{newapi => client}/cap/BasicVClock.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/cap/ClientId.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/cap/ClobberMutation.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/cap/ConflictResolver.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/cap/DefaultResolver.java (94%) rename src/main/java/com/basho/riak/{newapi => client}/cap/DefaultRetrier.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/cap/Mutation.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/cap/MutationProducer.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/cap/Quora.java (94%) rename src/main/java/com/basho/riak/{newapi => client}/cap/Quorum.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/cap/Retrier.java (89%) rename src/main/java/com/basho/riak/{newapi => client}/cap/UnresolvedConflictException.java (94%) rename src/main/java/com/basho/riak/{newapi => client}/cap/VClock.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/convert/ConversionException.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/convert/Converter.java (90%) rename src/main/java/com/basho/riak/{newapi => client}/convert/JSONConverter.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/convert/KeyUtil.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/convert/NoKeySpecifedException.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/convert/RiakKey.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/operations/DeleteObject.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/operations/FetchObject.java (86%) rename src/main/java/com/basho/riak/{newapi => client}/operations/RiakOperation.java (88%) rename src/main/java/com/basho/riak/{newapi => client}/operations/StoreObject.java (89%) rename src/main/java/com/basho/riak/{newapi => client}/query/BucketKeyMapReduce.java (98%) rename src/main/java/com/basho/riak/{newapi => client}/query/BucketMapReduce.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/query/LinkPhase.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/query/LinkWalk.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/LinkWalkStep.java (98%) rename src/main/java/com/basho/riak/{newapi => client}/query/MapPhase.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/MapReduce.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/MapReducePhase.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/MapReduceResult.java (91%) rename src/main/java/com/basho/riak/{newapi => client}/query/ReducePhase.java (94%) rename src/main/java/com/basho/riak/{newapi => client}/query/WalkResult.java (90%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/AbstractKeyFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/AbstractLogicalFilter.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/BetweenFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/EndsWithFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/EqualToFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/FloatToStringFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/GreaterThanFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/GreaterThanOrEqualFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/IntToStringFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/KeyFilter.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/KeyTransformFilter.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LessThanFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LessThanOrEqualFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LogicalAndFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LogicalFilter.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LogicalFilterGroup.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LogicalNotFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/LogicalOrFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/MatchFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/NotEqualToFilter.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/SetMemberFilter.java (97%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/SimilarToFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/StartsWithFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/StringToFloatFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/StringToIntFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/ToLowerFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/ToUpperFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/TokenizeFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/filter/UrlDecodeFilter.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/AnonymousFunction.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/Function.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/JSBucketKeyFunction.java (96%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/JSSourceFunction.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/NamedErlangFunction.java (98%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/NamedFunction.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/functions/NamedJSFunction.java (95%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/FunctionToJson.java (81%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/FunctionWriter.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/JSBucketKeyFunctionWriter.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/JSSourceFunctionWriter.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/NamedErlangFunctionWriter.java (93%) rename src/main/java/com/basho/riak/{newapi => client}/query/serialize/NamedJSFunctionWriter.java (92%) rename src/main/java/com/basho/riak/{newapi => client}/util/UnmodifiableIterator.java (97%) rename src/test/java/com/basho/riak/{newapi => client}/cap/ClobberMutationTest.java (89%) rename src/test/java/com/basho/riak/{newapi => client}/convert/ConversionUtilTest.java (93%) rename src/test/java/com/basho/riak/{newapi => client}/query/filter/LogicalAndFilterTest.java (75%) rename src/test/java/com/basho/riak/{newapi => client}/query/serialize/FunctionToJsonTest.java (78%) diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakClient.java b/src/main/java/com/basho/riak/client/DefaultRiakClient.java similarity index 88% rename from src/main/java/com/basho/riak/newapi/DefaultRiakClient.java rename to src/main/java/com/basho/riak/client/DefaultRiakClient.java index 412e89d8f..4eb106b35 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakClient.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakClient.java @@ -1,16 +1,16 @@ -package com.basho.riak.newapi; +package com.basho.riak.client; import java.io.IOException; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.FetchBucket; +import com.basho.riak.client.bucket.WriteBucket; +import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.query.BucketKeyMapReduce; +import com.basho.riak.client.query.BucketMapReduce; +import com.basho.riak.client.query.LinkWalk; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.FetchBucket; -import com.basho.riak.newapi.bucket.WriteBucket; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.query.BucketKeyMapReduce; -import com.basho.riak.newapi.query.BucketMapReduce; -import com.basho.riak.newapi.query.LinkWalk; /** * A default implementation of IRiakClient. diff --git a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java b/src/main/java/com/basho/riak/client/DefaultRiakObject.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/DefaultRiakObject.java rename to src/main/java/com/basho/riak/client/DefaultRiakObject.java index e87789f3f..1ef1c6833 100644 --- a/src/main/java/com/basho/riak/newapi/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakObject.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; import java.util.ArrayList; import java.util.Collection; @@ -22,10 +22,9 @@ import java.util.List; import java.util.Map; -import com.basho.riak.client.RiakLink; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.RiakKey; -import com.basho.riak.newapi.util.UnmodifiableIterator; +import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.convert.RiakKey; +import com.basho.riak.client.util.UnmodifiableIterator; /** * An implementation of {@link IRiakObject} that also contains the deprecated diff --git a/src/main/java/com/basho/riak/newapi/IRiakClient.java b/src/main/java/com/basho/riak/client/IRiakClient.java similarity index 79% rename from src/main/java/com/basho/riak/newapi/IRiakClient.java rename to src/main/java/com/basho/riak/client/IRiakClient.java index 137da659f..3ce01694a 100644 --- a/src/main/java/com/basho/riak/newapi/IRiakClient.java +++ b/src/main/java/com/basho/riak/client/IRiakClient.java @@ -11,14 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; - -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.FetchBucket; -import com.basho.riak.newapi.bucket.WriteBucket; -import com.basho.riak.newapi.query.BucketKeyMapReduce; -import com.basho.riak.newapi.query.BucketMapReduce; -import com.basho.riak.newapi.query.LinkWalk; +package com.basho.riak.client; + +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.FetchBucket; +import com.basho.riak.client.bucket.WriteBucket; +import com.basho.riak.client.query.BucketKeyMapReduce; +import com.basho.riak.client.query.BucketMapReduce; +import com.basho.riak.client.query.LinkWalk; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/IRiakObject.java b/src/main/java/com/basho/riak/client/IRiakObject.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/IRiakObject.java rename to src/main/java/com/basho/riak/client/IRiakObject.java index bb6b3dcdb..8bea1788e 100644 --- a/src/main/java/com/basho/riak/newapi/IRiakObject.java +++ b/src/main/java/com/basho/riak/client/IRiakObject.java @@ -11,15 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import com.basho.riak.client.RiakLink; -import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.client.cap.VClock; /** * Represents the data and meta data stored in Riak for bucket/key. diff --git a/src/main/java/com/basho/riak/newapi/RiakException.java b/src/main/java/com/basho/riak/client/RiakException.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/RiakException.java rename to src/main/java/com/basho/riak/client/RiakException.java index 9784fc302..185f2fbb5 100644 --- a/src/main/java/com/basho/riak/newapi/RiakException.java +++ b/src/main/java/com/basho/riak/client/RiakException.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/RiakFactory.java b/src/main/java/com/basho/riak/client/RiakFactory.java similarity index 98% rename from src/main/java/com/basho/riak/newapi/RiakFactory.java rename to src/main/java/com/basho/riak/client/RiakFactory.java index 3d9fe5076..59dea5543 100644 --- a/src/main/java/com/basho/riak/newapi/RiakFactory.java +++ b/src/main/java/com/basho/riak/client/RiakFactory.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; import java.io.IOException; diff --git a/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java b/src/main/java/com/basho/riak/client/RiakRetryFailedException.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java rename to src/main/java/com/basho/riak/client/RiakRetryFailedException.java index 7ae0770e9..867fe5bb9 100644 --- a/src/main/java/com/basho/riak/newapi/RiakRetryFailedException.java +++ b/src/main/java/com/basho/riak/client/RiakRetryFailedException.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi; +package com.basho.riak.client; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java b/src/main/java/com/basho/riak/client/bucket/Bucket.java similarity index 79% rename from src/main/java/com/basho/riak/newapi/bucket/Bucket.java rename to src/main/java/com/basho/riak/client/bucket/Bucket.java index c6e4d7e65..2bca1ca83 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/client/bucket/Bucket.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.operations.DeleteObject; -import com.basho.riak.newapi.operations.FetchObject; -import com.basho.riak.newapi.operations.StoreObject; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.operations.DeleteObject; +import com.basho.riak.client.operations.FetchObject; +import com.basho.riak.client.operations.StoreObject; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java b/src/main/java/com/basho/riak/client/bucket/BucketProperties.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java rename to src/main/java/com/basho/riak/client/bucket/BucketProperties.java index 29a1a1848..8ae2b4d44 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/BucketProperties.java +++ b/src/main/java/com/basho/riak/client/bucket/BucketProperties.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; import java.util.Collection; -import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedFunction; +import com.basho.riak.client.cap.Quorum; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java similarity index 90% rename from src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java rename to src/main/java/com/basho/riak/client/bucket/DefaultBucket.java index e883b1d99..db732b6f2 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java @@ -11,31 +11,31 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; -import static com.basho.riak.newapi.convert.KeyUtil.getKey; +import static com.basho.riak.client.convert.KeyUtil.getKey; import java.io.IOException; import java.util.Collection; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.cap.ClobberMutation; +import com.basho.riak.client.cap.DefaultResolver; +import com.basho.riak.client.cap.Mutation; +import com.basho.riak.client.cap.Quorum; +import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.convert.Converter; +import com.basho.riak.client.convert.JSONConverter; +import com.basho.riak.client.convert.NoKeySpecifedException; +import com.basho.riak.client.operations.DeleteObject; +import com.basho.riak.client.operations.FetchObject; +import com.basho.riak.client.operations.StoreObject; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedFunction; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.ClobberMutation; -import com.basho.riak.newapi.cap.DefaultResolver; -import com.basho.riak.newapi.cap.Mutation; -import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.convert.Converter; -import com.basho.riak.newapi.convert.JSONConverter; -import com.basho.riak.newapi.convert.NoKeySpecifedException; -import com.basho.riak.newapi.operations.DeleteObject; -import com.basho.riak.newapi.operations.FetchObject; -import com.basho.riak.newapi.operations.StoreObject; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java rename to src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java index 83cad6f60..e8be0b56d 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DefaultBucketProperties.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java @@ -11,15 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; import java.util.ArrayList; import java.util.Collection; -import com.basho.riak.newapi.cap.Quora; -import com.basho.riak.newapi.cap.Quorum; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedFunction; +import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.cap.Quorum; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedFunction; /** * Since not all interfaces to Riak are equal in terms of what they provide not diff --git a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java similarity index 89% rename from src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java rename to src/main/java/com/basho/riak/client/bucket/DomainBucket.java index b86ce5f61..1a3629ab4 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java @@ -11,15 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.builders.DomainBucketBuilder; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.Mutation; -import com.basho.riak.newapi.cap.MutationProducer; -import com.basho.riak.newapi.convert.Converter; -import com.basho.riak.newapi.convert.KeyUtil; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.builders.DomainBucketBuilder; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.Mutation; +import com.basho.riak.client.cap.MutationProducer; +import com.basho.riak.client.convert.Converter; +import com.basho.riak.client.convert.KeyUtil; /** * A domain bucket is a wrapper around a bucket that is strongly typed uses a diff --git a/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java similarity index 88% rename from src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java rename to src/main/java/com/basho/riak/client/bucket/FetchBucket.java index 7aac5abbd..a09beec95 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/FetchBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java @@ -11,15 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; import java.io.IOException; +import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.operations.RiakOperation; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java similarity index 80% rename from src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java rename to src/main/java/com/basho/riak/client/bucket/RiakBucket.java index ae0e33f25..67e1d2931 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/RiakBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java @@ -11,15 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.builders.DomainBucketBuilder; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.convert.Converter; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.builders.DomainBucketBuilder; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.convert.Converter; /** * A DomainBucket for convenience. @@ -57,7 +57,7 @@ private RiakBucket(final DomainBucket delegate, final Bucket bucket * @param o * @return * @throws RiakException - * @see com.basho.riak.newapi.bucket.DomainBucket#store(java.lang.Object) + * @see com.basho.riak.client.bucket.DomainBucket#store(java.lang.Object) */ public IRiakObject store(IRiakObject o) throws RiakException { return delegate.store(o); @@ -77,7 +77,7 @@ public IRiakObject store(String key, String value) throws RiakException { * @param key * @return * @throws RiakException - * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.String) + * @see com.basho.riak.client.bucket.DomainBucket#fetch(java.lang.String) */ public IRiakObject fetch(String key) throws RiakException { return delegate.fetch(key); @@ -87,7 +87,7 @@ public IRiakObject fetch(String key) throws RiakException { * @param o * @return * @throws RiakException - * @see com.basho.riak.newapi.bucket.DomainBucket#fetch(java.lang.Object) + * @see com.basho.riak.client.bucket.DomainBucket#fetch(java.lang.Object) */ public IRiakObject fetch(IRiakObject o) throws RiakException { return delegate.fetch(o); @@ -96,7 +96,7 @@ public IRiakObject fetch(IRiakObject o) throws RiakException { /** * @param o * @throws RiakException - * @see com.basho.riak.newapi.bucket.DomainBucket#delete(java.lang.Object) + * @see com.basho.riak.client.bucket.DomainBucket#delete(java.lang.Object) */ public void delete(IRiakObject o) throws RiakException { delegate.delete(o); @@ -105,7 +105,7 @@ public void delete(IRiakObject o) throws RiakException { /** * @param key * @throws RiakException - * @see com.basho.riak.newapi.bucket.DomainBucket#delete(java.lang.String) + * @see com.basho.riak.client.bucket.DomainBucket#delete(java.lang.String) */ public void delete(String key) throws RiakException { delegate.delete(key); diff --git a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java similarity index 91% rename from src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java rename to src/main/java/com/basho/riak/client/bucket/WriteBucket.java index 49d0fc40a..857dba13a 100644 --- a/src/main/java/com/basho/riak/newapi/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java @@ -11,20 +11,20 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.bucket; +package com.basho.riak.client.bucket; import java.io.IOException; import java.util.Collection; +import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.bucket.DefaultBucketProperties.Builder; +import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.operations.RiakOperation; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedFunction; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.bucket.DefaultBucketProperties.Builder; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.cap.Quora; -import com.basho.riak.newapi.operations.RiakOperation; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java similarity index 88% rename from src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java rename to src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java index 1bf78d3ee..d1f5ad5c5 100644 --- a/src/main/java/com/basho/riak/newapi/builders/DomainBucketBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java @@ -11,17 +11,17 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.builders; - -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.DomainBucket; -import com.basho.riak.newapi.cap.ClobberMutation; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.DefaultResolver; -import com.basho.riak.newapi.cap.Mutation; -import com.basho.riak.newapi.cap.MutationProducer; -import com.basho.riak.newapi.convert.Converter; -import com.basho.riak.newapi.convert.JSONConverter; +package com.basho.riak.client.builders; + +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.DomainBucket; +import com.basho.riak.client.cap.ClobberMutation; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.DefaultResolver; +import com.basho.riak.client.cap.Mutation; +import com.basho.riak.client.cap.MutationProducer; +import com.basho.riak.client.convert.Converter; +import com.basho.riak.client.convert.JSONConverter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java similarity index 94% rename from src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java rename to src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java index 55a500398..3bbc919c3 100644 --- a/src/main/java/com/basho/riak/newapi/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.builders; +package com.basho.riak.client.builders; import java.util.ArrayList; import java.util.Collection; @@ -19,11 +19,11 @@ import java.util.HashMap; import java.util.Map; +import com.basho.riak.client.DefaultRiakObject; +import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakLink; -import com.basho.riak.newapi.DefaultRiakObject; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.cap.BasicVClock; -import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.client.cap.BasicVClock; +import com.basho.riak.client.cap.VClock; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java b/src/main/java/com/basho/riak/client/cap/BasicVClock.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/cap/BasicVClock.java rename to src/main/java/com/basho/riak/client/cap/BasicVClock.java index 2f6e34b3e..2a70dedee 100644 --- a/src/main/java/com/basho/riak/newapi/cap/BasicVClock.java +++ b/src/main/java/com/basho/riak/client/cap/BasicVClock.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/ClientId.java b/src/main/java/com/basho/riak/client/cap/ClientId.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/cap/ClientId.java rename to src/main/java/com/basho/riak/client/cap/ClientId.java index ccdbe84eb..e223ea218 100644 --- a/src/main/java/com/basho/riak/newapi/cap/ClientId.java +++ b/src/main/java/com/basho/riak/client/cap/ClientId.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import java.security.SecureRandom; diff --git a/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java b/src/main/java/com/basho/riak/client/cap/ClobberMutation.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java rename to src/main/java/com/basho/riak/client/cap/ClobberMutation.java index 4a53946c4..23854d5c8 100644 --- a/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java +++ b/src/main/java/com/basho/riak/client/cap/ClobberMutation.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * A dumb mutation that overwrites the original value with a new one. diff --git a/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java b/src/main/java/com/basho/riak/client/cap/ConflictResolver.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java rename to src/main/java/com/basho/riak/client/cap/ConflictResolver.java index 8e70235a3..8f2566afb 100644 --- a/src/main/java/com/basho/riak/newapi/cap/ConflictResolver.java +++ b/src/main/java/com/basho/riak/client/cap/ConflictResolver.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import java.util.Collection; diff --git a/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java b/src/main/java/com/basho/riak/client/cap/DefaultResolver.java similarity index 94% rename from src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java rename to src/main/java/com/basho/riak/client/cap/DefaultResolver.java index e18a682e2..7ddb25258 100644 --- a/src/main/java/com/basho/riak/newapi/cap/DefaultResolver.java +++ b/src/main/java/com/basho/riak/client/cap/DefaultResolver.java @@ -1,4 +1,4 @@ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import java.util.Collection; diff --git a/src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java rename to src/main/java/com/basho/riak/client/cap/DefaultRetrier.java index 9c2e9db03..7a4ef6327 100644 --- a/src/main/java/com/basho/riak/newapi/cap/DefaultRetrier.java +++ b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java @@ -11,12 +11,12 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import java.io.IOException; +import com.basho.riak.client.RiakRetryFailedException; import com.basho.riak.client.raw.Command; -import com.basho.riak.newapi.RiakRetryFailedException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/Mutation.java b/src/main/java/com/basho/riak/client/cap/Mutation.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/cap/Mutation.java rename to src/main/java/com/basho/riak/client/cap/Mutation.java index dc1d86396..80a0af320 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Mutation.java +++ b/src/main/java/com/basho/riak/client/cap/Mutation.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * Interface for a mutation. diff --git a/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java b/src/main/java/com/basho/riak/client/cap/MutationProducer.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/cap/MutationProducer.java rename to src/main/java/com/basho/riak/client/cap/MutationProducer.java index 6c1f10059..20aec1cf4 100644 --- a/src/main/java/com/basho/riak/newapi/cap/MutationProducer.java +++ b/src/main/java/com/basho/riak/client/cap/MutationProducer.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * Maybe you want to produce a mutation at will? Say if you are using a domain diff --git a/src/main/java/com/basho/riak/newapi/cap/Quora.java b/src/main/java/com/basho/riak/client/cap/Quora.java similarity index 94% rename from src/main/java/com/basho/riak/newapi/cap/Quora.java rename to src/main/java/com/basho/riak/client/cap/Quora.java index 6560df8eb..e58611db7 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Quora.java +++ b/src/main/java/com/basho/riak/client/cap/Quora.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/Quorum.java b/src/main/java/com/basho/riak/client/cap/Quorum.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/cap/Quorum.java rename to src/main/java/com/basho/riak/client/cap/Quorum.java index a7b13679d..add1e3680 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Quorum.java +++ b/src/main/java/com/basho/riak/client/cap/Quorum.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * TODO needs further definition and accessor methods. diff --git a/src/main/java/com/basho/riak/newapi/cap/Retrier.java b/src/main/java/com/basho/riak/client/cap/Retrier.java similarity index 89% rename from src/main/java/com/basho/riak/newapi/cap/Retrier.java rename to src/main/java/com/basho/riak/client/cap/Retrier.java index 554b55189..313585797 100644 --- a/src/main/java/com/basho/riak/newapi/cap/Retrier.java +++ b/src/main/java/com/basho/riak/client/cap/Retrier.java @@ -11,10 +11,10 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; +import com.basho.riak.client.RiakRetryFailedException; import com.basho.riak.client.raw.Command; -import com.basho.riak.newapi.RiakRetryFailedException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java b/src/main/java/com/basho/riak/client/cap/UnresolvedConflictException.java similarity index 94% rename from src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java rename to src/main/java/com/basho/riak/client/cap/UnresolvedConflictException.java index b358f5436..08f2354f3 100644 --- a/src/main/java/com/basho/riak/newapi/cap/UnresolvedConflictException.java +++ b/src/main/java/com/basho/riak/client/cap/UnresolvedConflictException.java @@ -11,11 +11,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import java.util.Collection; -import com.basho.riak.newapi.RiakException; +import com.basho.riak.client.RiakException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/cap/VClock.java b/src/main/java/com/basho/riak/client/cap/VClock.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/cap/VClock.java rename to src/main/java/com/basho/riak/client/cap/VClock.java index fcc7722b5..958d529d3 100644 --- a/src/main/java/com/basho/riak/newapi/cap/VClock.java +++ b/src/main/java/com/basho/riak/client/cap/VClock.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/convert/ConversionException.java b/src/main/java/com/basho/riak/client/convert/ConversionException.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/convert/ConversionException.java rename to src/main/java/com/basho/riak/client/convert/ConversionException.java index 7643333ae..3117079fb 100644 --- a/src/main/java/com/basho/riak/newapi/convert/ConversionException.java +++ b/src/main/java/com/basho/riak/client/convert/ConversionException.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; -import com.basho.riak.newapi.RiakException; +import com.basho.riak.client.RiakException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/convert/Converter.java b/src/main/java/com/basho/riak/client/convert/Converter.java similarity index 90% rename from src/main/java/com/basho/riak/newapi/convert/Converter.java rename to src/main/java/com/basho/riak/client/convert/Converter.java index a73c09aa8..3489c4126 100644 --- a/src/main/java/com/basho/riak/newapi/convert/Converter.java +++ b/src/main/java/com/basho/riak/client/convert/Converter.java @@ -11,10 +11,10 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.cap.VClock; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java b/src/main/java/com/basho/riak/client/convert/JSONConverter.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/convert/JSONConverter.java rename to src/main/java/com/basho/riak/client/convert/JSONConverter.java index a595fd9e7..266c60f4d 100644 --- a/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java +++ b/src/main/java/com/basho/riak/client/convert/JSONConverter.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; -import static com.basho.riak.newapi.convert.KeyUtil.getKey; +import static com.basho.riak.client.convert.KeyUtil.getKey; import java.io.IOException; import java.io.StringWriter; @@ -21,9 +21,9 @@ import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.ObjectMapper; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.cap.VClock; /** * Converts a RiakObject's value to an instance of T. T must have a field diff --git a/src/main/java/com/basho/riak/newapi/convert/KeyUtil.java b/src/main/java/com/basho/riak/client/convert/KeyUtil.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/convert/KeyUtil.java rename to src/main/java/com/basho/riak/client/convert/KeyUtil.java index c72aff9fa..0bf8c6468 100644 --- a/src/main/java/com/basho/riak/newapi/convert/KeyUtil.java +++ b/src/main/java/com/basho/riak/client/convert/KeyUtil.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; import java.lang.reflect.Field; diff --git a/src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java b/src/main/java/com/basho/riak/client/convert/NoKeySpecifedException.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java rename to src/main/java/com/basho/riak/client/convert/NoKeySpecifedException.java index 51510e5c6..2ce6b0a87 100644 --- a/src/main/java/com/basho/riak/newapi/convert/NoKeySpecifedException.java +++ b/src/main/java/com/basho/riak/client/convert/NoKeySpecifedException.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/convert/RiakKey.java b/src/main/java/com/basho/riak/client/convert/RiakKey.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/convert/RiakKey.java rename to src/main/java/com/basho/riak/client/convert/RiakKey.java index fbffeaea9..7e9ac776b 100644 --- a/src/main/java/com/basho/riak/newapi/convert/RiakKey.java +++ b/src/main/java/com/basho/riak/client/convert/RiakKey.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java b/src/main/java/com/basho/riak/client/operations/DeleteObject.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/operations/DeleteObject.java rename to src/main/java/com/basho/riak/client/operations/DeleteObject.java index 9970f4757..d864d3830 100644 --- a/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/client/operations/DeleteObject.java @@ -11,14 +11,14 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.operations; +package com.basho.riak.client.operations; import java.io.IOException; +import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.cap.DefaultRetrier; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java b/src/main/java/com/basho/riak/client/operations/FetchObject.java similarity index 86% rename from src/main/java/com/basho/riak/newapi/operations/FetchObject.java rename to src/main/java/com/basho/riak/client/operations/FetchObject.java index 43505a20e..43f749349 100644 --- a/src/main/java/com/basho/riak/newapi/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/client/operations/FetchObject.java @@ -11,22 +11,22 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.operations; +package com.basho.riak.client.operations; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.UnresolvedConflictException; +import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.convert.Converter; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.cap.UnresolvedConflictException; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.convert.Converter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java b/src/main/java/com/basho/riak/client/operations/RiakOperation.java similarity index 88% rename from src/main/java/com/basho/riak/newapi/operations/RiakOperation.java rename to src/main/java/com/basho/riak/client/operations/RiakOperation.java index 7cb1c36aa..575bf4592 100644 --- a/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java +++ b/src/main/java/com/basho/riak/client/operations/RiakOperation.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.operations; +package com.basho.riak.client.operations; -import com.basho.riak.newapi.RiakException; +import com.basho.riak.client.RiakException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java b/src/main/java/com/basho/riak/client/operations/StoreObject.java similarity index 89% rename from src/main/java/com/basho/riak/newapi/operations/StoreObject.java rename to src/main/java/com/basho/riak/client/operations/StoreObject.java index 6cc9d9360..11aeb6766 100644 --- a/src/main/java/com/basho/riak/newapi/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/client/operations/StoreObject.java @@ -11,25 +11,25 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.operations; +package com.basho.riak.client.operations; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.Mutation; +import com.basho.riak.client.cap.UnresolvedConflictException; +import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.convert.Converter; import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.RiakRetryFailedException; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.DefaultRetrier; -import com.basho.riak.newapi.cap.Mutation; -import com.basho.riak.newapi.cap.UnresolvedConflictException; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.convert.Converter; /** * Stores a given object into riak. Fetches first. diff --git a/src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java b/src/main/java/com/basho/riak/client/query/BucketKeyMapReduce.java similarity index 98% rename from src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java rename to src/main/java/com/basho/riak/client/query/BucketKeyMapReduce.java index e415e3735..6bb9f3fc4 100644 --- a/src/main/java/com/basho/riak/newapi/query/BucketKeyMapReduce.java +++ b/src/main/java/com/basho/riak/client/query/BucketKeyMapReduce.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.io.IOException; import java.util.Collection; diff --git a/src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java b/src/main/java/com/basho/riak/client/query/BucketMapReduce.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java rename to src/main/java/com/basho/riak/client/query/BucketMapReduce.java index 2e8dadcfb..a1e6b36b9 100644 --- a/src/main/java/com/basho/riak/newapi/query/BucketMapReduce.java +++ b/src/main/java/com/basho/riak/client/query/BucketMapReduce.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.io.IOException; import java.util.Arrays; @@ -22,8 +22,8 @@ import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.annotate.JsonProperty; +import com.basho.riak.client.query.filter.KeyFilter; import com.basho.riak.client.raw.RawClient; -import com.basho.riak.newapi.query.filter.KeyFilter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/LinkPhase.java b/src/main/java/com/basho/riak/client/query/LinkPhase.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/query/LinkPhase.java rename to src/main/java/com/basho/riak/client/query/LinkPhase.java index 7ec40c6b3..67a081380 100644 --- a/src/main/java/com/basho/riak/newapi/query/LinkPhase.java +++ b/src/main/java/com/basho/riak/client/query/LinkPhase.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java b/src/main/java/com/basho/riak/client/query/LinkWalk.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/LinkWalk.java rename to src/main/java/com/basho/riak/client/query/LinkWalk.java index 36f7e4e47..513009ecd 100644 --- a/src/main/java/com/basho/riak/newapi/query/LinkWalk.java +++ b/src/main/java/com/basho/riak/client/query/LinkWalk.java @@ -11,17 +11,17 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.io.IOException; import java.util.LinkedList; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.operations.RiakOperation; +import com.basho.riak.client.query.LinkWalkStep.Accumulate; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.query.LinkWalkSpec; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.operations.RiakOperation; -import com.basho.riak.newapi.query.LinkWalkStep.Accumulate; /** * diff --git a/src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java b/src/main/java/com/basho/riak/client/query/LinkWalkStep.java similarity index 98% rename from src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java rename to src/main/java/com/basho/riak/client/query/LinkWalkStep.java index 76f873d3d..260fe03c7 100644 --- a/src/main/java/com/basho/riak/newapi/query/LinkWalkStep.java +++ b/src/main/java/com/basho/riak/client/query/LinkWalkStep.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/MapPhase.java b/src/main/java/com/basho/riak/client/query/MapPhase.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/MapPhase.java rename to src/main/java/com/basho/riak/client/query/MapPhase.java index 7df5b5de5..7a1fe8725 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapPhase.java +++ b/src/main/java/com/basho/riak/client/query/MapPhase.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; -import com.basho.riak.newapi.query.functions.Function; +import com.basho.riak.client.query.functions.Function; /** * A Map Phase of a Map/Reduce job spec. diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduce.java b/src/main/java/com/basho/riak/client/query/MapReduce.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/MapReduce.java rename to src/main/java/com/basho/riak/client/query/MapReduce.java index 9b3e05cce..e1faef602 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduce.java +++ b/src/main/java/com/basho/riak/client/query/MapReduce.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -23,12 +23,12 @@ import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.operations.RiakOperation; +import com.basho.riak.client.query.functions.Function; +import com.basho.riak.client.query.serialize.FunctionToJson; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.query.MapReduceSpec; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.operations.RiakOperation; -import com.basho.riak.newapi.query.functions.Function; -import com.basho.riak.newapi.query.serialize.FunctionToJson; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/MapReducePhase.java b/src/main/java/com/basho/riak/client/query/MapReducePhase.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/MapReducePhase.java rename to src/main/java/com/basho/riak/client/query/MapReducePhase.java index 6dc460f21..a74404e9b 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReducePhase.java +++ b/src/main/java/com/basho/riak/client/query/MapReducePhase.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java b/src/main/java/com/basho/riak/client/query/MapReduceResult.java similarity index 91% rename from src/main/java/com/basho/riak/newapi/query/MapReduceResult.java rename to src/main/java/com/basho/riak/client/query/MapReduceResult.java index 0b2778542..7f354b658 100644 --- a/src/main/java/com/basho/riak/newapi/query/MapReduceResult.java +++ b/src/main/java/com/basho/riak/client/query/MapReduceResult.java @@ -11,11 +11,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.util.Collection; -import com.basho.riak.newapi.convert.ConversionException; +import com.basho.riak.client.convert.ConversionException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/ReducePhase.java b/src/main/java/com/basho/riak/client/query/ReducePhase.java similarity index 94% rename from src/main/java/com/basho/riak/newapi/query/ReducePhase.java rename to src/main/java/com/basho/riak/client/query/ReducePhase.java index 72cd95a1c..dcb68bfb4 100644 --- a/src/main/java/com/basho/riak/newapi/query/ReducePhase.java +++ b/src/main/java/com/basho/riak/client/query/ReducePhase.java @@ -11,9 +11,9 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; -import com.basho.riak.newapi.query.functions.Function; +import com.basho.riak.client.query.functions.Function; /** * A reduce phase of a MapReduce job spec. Just a tag class. diff --git a/src/main/java/com/basho/riak/newapi/query/WalkResult.java b/src/main/java/com/basho/riak/client/query/WalkResult.java similarity index 90% rename from src/main/java/com/basho/riak/newapi/query/WalkResult.java rename to src/main/java/com/basho/riak/client/query/WalkResult.java index dac02d230..e47303280 100644 --- a/src/main/java/com/basho/riak/newapi/query/WalkResult.java +++ b/src/main/java/com/basho/riak/client/query/WalkResult.java @@ -11,11 +11,11 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query; +package com.basho.riak.client.query; import java.util.Collection; -import com.basho.riak.newapi.IRiakObject; +import com.basho.riak.client.IRiakObject; /** * diff --git a/src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java b/src/main/java/com/basho/riak/client/query/filter/AbstractKeyFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java rename to src/main/java/com/basho/riak/client/query/filter/AbstractKeyFilter.java index ef6ec7e1f..3f1df7176 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/AbstractKeyFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/AbstractKeyFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java b/src/main/java/com/basho/riak/client/query/filter/AbstractLogicalFilter.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java rename to src/main/java/com/basho/riak/client/query/filter/AbstractLogicalFilter.java index a439925d8..018281fd1 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/AbstractLogicalFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/AbstractLogicalFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; import java.util.Collection; import java.util.LinkedList; diff --git a/src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java b/src/main/java/com/basho/riak/client/query/filter/BetweenFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java rename to src/main/java/com/basho/riak/client/query/filter/BetweenFilter.java index 65d9b54be..043262654 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/BetweenFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/BetweenFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class BetweenFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java b/src/main/java/com/basho/riak/client/query/filter/EndsWithFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java rename to src/main/java/com/basho/riak/client/query/filter/EndsWithFilter.java index e782cf438..739085fe3 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/EndsWithFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/EndsWithFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class EndsWithFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java b/src/main/java/com/basho/riak/client/query/filter/EqualToFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java rename to src/main/java/com/basho/riak/client/query/filter/EqualToFilter.java index 3185cdd4c..62db22b6e 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/EqualToFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/EqualToFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class EqualToFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java b/src/main/java/com/basho/riak/client/query/filter/FloatToStringFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java rename to src/main/java/com/basho/riak/client/query/filter/FloatToStringFilter.java index 90d792091..aa345eaec 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/FloatToStringFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/FloatToStringFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class FloatToStringFilter extends AbstractKeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java b/src/main/java/com/basho/riak/client/query/filter/GreaterThanFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java rename to src/main/java/com/basho/riak/client/query/filter/GreaterThanFilter.java index a49d8fdfd..9bf7a3e37 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/GreaterThanFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class GreaterThanFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/query/filter/GreaterThanOrEqualFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java rename to src/main/java/com/basho/riak/client/query/filter/GreaterThanOrEqualFilter.java index ad9b4408f..c65236e20 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/GreaterThanOrEqualFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/GreaterThanOrEqualFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class GreaterThanOrEqualFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java b/src/main/java/com/basho/riak/client/query/filter/IntToStringFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java rename to src/main/java/com/basho/riak/client/query/filter/IntToStringFilter.java index a030e955d..e23de9408 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/IntToStringFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/IntToStringFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class IntToStringFilter extends AbstractKeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java b/src/main/java/com/basho/riak/client/query/filter/KeyFilter.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java rename to src/main/java/com/basho/riak/client/query/filter/KeyFilter.java index 482ecf91d..256f15421 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/KeyFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/KeyFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; /** diff --git a/src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java b/src/main/java/com/basho/riak/client/query/filter/KeyTransformFilter.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java rename to src/main/java/com/basho/riak/client/query/filter/KeyTransformFilter.java index 06a467ecc..1b711a901 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/KeyTransformFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/KeyTransformFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java b/src/main/java/com/basho/riak/client/query/filter/LessThanFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LessThanFilter.java index 727ca1efb..917182dc1 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LessThanFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LessThanFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class LessThanFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java b/src/main/java/com/basho/riak/client/query/filter/LessThanOrEqualFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LessThanOrEqualFilter.java index e29fd9e9c..1aa92d6f8 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LessThanOrEqualFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LessThanOrEqualFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class LessThanOrEqualFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java b/src/main/java/com/basho/riak/client/query/filter/LogicalAndFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LogicalAndFilter.java index 8230d3277..3c30e588b 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LogicalAndFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LogicalAndFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class LogicalAndFilter extends AbstractLogicalFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java b/src/main/java/com/basho/riak/client/query/filter/LogicalFilter.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LogicalFilter.java index b6573509f..9f6e16a56 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LogicalFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java b/src/main/java/com/basho/riak/client/query/filter/LogicalFilterGroup.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java rename to src/main/java/com/basho/riak/client/query/filter/LogicalFilterGroup.java index 569b21701..0768fef5f 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LogicalFilterGroup.java +++ b/src/main/java/com/basho/riak/client/query/filter/LogicalFilterGroup.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; import java.util.Collection; import java.util.LinkedList; diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java b/src/main/java/com/basho/riak/client/query/filter/LogicalNotFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LogicalNotFilter.java index 24db633bc..3776a372b 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LogicalNotFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LogicalNotFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class LogicalNotFilter extends AbstractLogicalFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java b/src/main/java/com/basho/riak/client/query/filter/LogicalOrFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java rename to src/main/java/com/basho/riak/client/query/filter/LogicalOrFilter.java index db74ec34b..384125290 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/LogicalOrFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/LogicalOrFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class LogicalOrFilter extends AbstractLogicalFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java b/src/main/java/com/basho/riak/client/query/filter/MatchFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java rename to src/main/java/com/basho/riak/client/query/filter/MatchFilter.java index f8d0f8402..ac4924773 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/MatchFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/MatchFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class MatchFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java b/src/main/java/com/basho/riak/client/query/filter/NotEqualToFilter.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java rename to src/main/java/com/basho/riak/client/query/filter/NotEqualToFilter.java index da17e3e68..ce5e3a6d9 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/NotEqualToFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/NotEqualToFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class NotEqualToFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java b/src/main/java/com/basho/riak/client/query/filter/SetMemberFilter.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java rename to src/main/java/com/basho/riak/client/query/filter/SetMemberFilter.java index f4fb69db1..f7faa8d17 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/SetMemberFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/SetMemberFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; import java.util.Set; diff --git a/src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java b/src/main/java/com/basho/riak/client/query/filter/SimilarToFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java rename to src/main/java/com/basho/riak/client/query/filter/SimilarToFilter.java index 5a55375dc..92ae814a9 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/SimilarToFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/SimilarToFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class SimilarToFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java b/src/main/java/com/basho/riak/client/query/filter/StartsWithFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java rename to src/main/java/com/basho/riak/client/query/filter/StartsWithFilter.java index ba7ebc233..c91ea8ae8 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/StartsWithFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/StartsWithFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class StartsWithFilter implements KeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java b/src/main/java/com/basho/riak/client/query/filter/StringToFloatFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java rename to src/main/java/com/basho/riak/client/query/filter/StringToFloatFilter.java index 57d670df4..f4ac60da1 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/StringToFloatFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/StringToFloatFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class StringToFloatFilter extends AbstractKeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java b/src/main/java/com/basho/riak/client/query/filter/StringToIntFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java rename to src/main/java/com/basho/riak/client/query/filter/StringToIntFilter.java index db311cfbf..cf31327f9 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/StringToIntFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/StringToIntFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class StringToIntFilter extends AbstractKeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java b/src/main/java/com/basho/riak/client/query/filter/ToLowerFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java rename to src/main/java/com/basho/riak/client/query/filter/ToLowerFilter.java index dcd013a70..4e78ac7ff 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/ToLowerFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/ToLowerFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class ToLowerFilter extends AbstractKeyFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java b/src/main/java/com/basho/riak/client/query/filter/ToUpperFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java rename to src/main/java/com/basho/riak/client/query/filter/ToUpperFilter.java index f9dbf3cd5..6199b2795 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/ToUpperFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/ToUpperFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; diff --git a/src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java b/src/main/java/com/basho/riak/client/query/filter/TokenizeFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java rename to src/main/java/com/basho/riak/client/query/filter/TokenizeFilter.java index 08389b391..9f2dff2d2 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/TokenizeFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/TokenizeFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class TokenizeFilter implements KeyTransformFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java b/src/main/java/com/basho/riak/client/query/filter/UrlDecodeFilter.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java rename to src/main/java/com/basho/riak/client/query/filter/UrlDecodeFilter.java index 15fabd951..41d55a648 100644 --- a/src/main/java/com/basho/riak/newapi/query/filter/UrlDecodeFilter.java +++ b/src/main/java/com/basho/riak/client/query/filter/UrlDecodeFilter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; public class UrlDecodeFilter implements KeyTransformFilter { diff --git a/src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java b/src/main/java/com/basho/riak/client/query/functions/AnonymousFunction.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java rename to src/main/java/com/basho/riak/client/query/functions/AnonymousFunction.java index c9009ddf5..5e695b870 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/AnonymousFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/AnonymousFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * Tag interface for anonymous functions. diff --git a/src/main/java/com/basho/riak/newapi/query/functions/Function.java b/src/main/java/com/basho/riak/client/query/functions/Function.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/functions/Function.java rename to src/main/java/com/basho/riak/client/query/functions/Function.java index 2a62d24bf..ee93a8275 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/Function.java +++ b/src/main/java/com/basho/riak/client/query/functions/Function.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java b/src/main/java/com/basho/riak/client/query/functions/JSBucketKeyFunction.java similarity index 96% rename from src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java rename to src/main/java/com/basho/riak/client/query/functions/JSBucketKeyFunction.java index c3b4b8ecc..8d47fc19d 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/JSBucketKeyFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/JSBucketKeyFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * A JS function that is stored in a Riak bucket/key location diff --git a/src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java b/src/main/java/com/basho/riak/client/query/functions/JSSourceFunction.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java rename to src/main/java/com/basho/riak/client/query/functions/JSSourceFunction.java index abc71a2c6..e84bfc632 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/JSSourceFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/JSSourceFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * An anonymous JavaScript function. diff --git a/src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java b/src/main/java/com/basho/riak/client/query/functions/NamedErlangFunction.java similarity index 98% rename from src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java rename to src/main/java/com/basho/riak/client/query/functions/NamedErlangFunction.java index d2aafd899..2fd9c2e3b 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/NamedErlangFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/NamedErlangFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * Models a named erlang function. diff --git a/src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java b/src/main/java/com/basho/riak/client/query/functions/NamedFunction.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java rename to src/main/java/com/basho/riak/client/query/functions/NamedFunction.java index 1df65f7b3..834db576f 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/NamedFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/NamedFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * Tag interface. diff --git a/src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java b/src/main/java/com/basho/riak/client/query/functions/NamedJSFunction.java similarity index 95% rename from src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java rename to src/main/java/com/basho/riak/client/query/functions/NamedJSFunction.java index d5bc415bf..6a874b7e4 100644 --- a/src/main/java/com/basho/riak/newapi/query/functions/NamedJSFunction.java +++ b/src/main/java/com/basho/riak/client/query/functions/NamedJSFunction.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.functions; +package com.basho.riak.client.query.functions; /** * A named function that is a JS built in function. diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java b/src/main/java/com/basho/riak/client/query/serialize/FunctionToJson.java similarity index 81% rename from src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java rename to src/main/java/com/basho/riak/client/query/serialize/FunctionToJson.java index 686000607..a750b6dd4 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionToJson.java +++ b/src/main/java/com/basho/riak/client/query/serialize/FunctionToJson.java @@ -11,15 +11,15 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import org.codehaus.jackson.JsonGenerator; -import com.basho.riak.newapi.query.functions.Function; -import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; -import com.basho.riak.newapi.query.functions.JSSourceFunction; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedJSFunction; +import com.basho.riak.client.query.functions.Function; +import com.basho.riak.client.query.functions.JSBucketKeyFunction; +import com.basho.riak.client.query.functions.JSSourceFunction; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedJSFunction; /** * Helper to write a Function to a JsonGenerator diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java b/src/main/java/com/basho/riak/client/query/serialize/FunctionWriter.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java rename to src/main/java/com/basho/riak/client/query/serialize/FunctionWriter.java index 00fc056f1..02605d890 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/FunctionWriter.java +++ b/src/main/java/com/basho/riak/client/query/serialize/FunctionWriter.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import java.io.IOException; diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java b/src/main/java/com/basho/riak/client/query/serialize/JSBucketKeyFunctionWriter.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java rename to src/main/java/com/basho/riak/client/query/serialize/JSBucketKeyFunctionWriter.java index 816fac461..b1a8c640d 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/JSBucketKeyFunctionWriter.java +++ b/src/main/java/com/basho/riak/client/query/serialize/JSBucketKeyFunctionWriter.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import java.io.IOException; import org.codehaus.jackson.JsonGenerator; -import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; +import com.basho.riak.client.query.functions.JSBucketKeyFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java b/src/main/java/com/basho/riak/client/query/serialize/JSSourceFunctionWriter.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java rename to src/main/java/com/basho/riak/client/query/serialize/JSSourceFunctionWriter.java index 097a247e9..dad62a36b 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/JSSourceFunctionWriter.java +++ b/src/main/java/com/basho/riak/client/query/serialize/JSSourceFunctionWriter.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import java.io.IOException; import org.codehaus.jackson.JsonGenerator; -import com.basho.riak.newapi.query.functions.JSSourceFunction; +import com.basho.riak.client.query.functions.JSSourceFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java b/src/main/java/com/basho/riak/client/query/serialize/NamedErlangFunctionWriter.java similarity index 93% rename from src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java rename to src/main/java/com/basho/riak/client/query/serialize/NamedErlangFunctionWriter.java index 3c25c8ddf..cc7f3ffd2 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/NamedErlangFunctionWriter.java +++ b/src/main/java/com/basho/riak/client/query/serialize/NamedErlangFunctionWriter.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import java.io.IOException; import org.codehaus.jackson.JsonGenerator; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedErlangFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java b/src/main/java/com/basho/riak/client/query/serialize/NamedJSFunctionWriter.java similarity index 92% rename from src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java rename to src/main/java/com/basho/riak/client/query/serialize/NamedJSFunctionWriter.java index 4a550bc40..48446e3a8 100644 --- a/src/main/java/com/basho/riak/newapi/query/serialize/NamedJSFunctionWriter.java +++ b/src/main/java/com/basho/riak/client/query/serialize/NamedJSFunctionWriter.java @@ -11,13 +11,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import java.io.IOException; import org.codehaus.jackson.JsonGenerator; -import com.basho.riak.newapi.query.functions.NamedJSFunction; +import com.basho.riak.client.query.functions.NamedJSFunction; /** * @author russell diff --git a/src/main/java/com/basho/riak/client/raw/RawClient.java b/src/main/java/com/basho/riak/client/raw/RawClient.java index ebdf092c3..59c061940 100644 --- a/src/main/java/com/basho/riak/client/raw/RawClient.java +++ b/src/main/java/com/basho/riak/client/raw/RawClient.java @@ -16,13 +16,13 @@ import java.io.IOException; import java.util.Iterator; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.WalkResult; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.WalkResult; /** * @author russell diff --git a/src/main/java/com/basho/riak/client/raw/RiakResponse.java b/src/main/java/com/basho/riak/client/raw/RiakResponse.java index 008f9d115..c18427ea8 100644 --- a/src/main/java/com/basho/riak/client/raw/RiakResponse.java +++ b/src/main/java/com/basho/riak/client/raw/RiakResponse.java @@ -16,9 +16,9 @@ import java.util.Arrays; import java.util.Iterator; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.cap.BasicVClock; -import com.basho.riak.newapi.cap.VClock; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.cap.BasicVClock; +import com.basho.riak.client.cap.VClock; /** * What riak returns: a VClock and bunch of siblings. diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index befa61a48..80f68937c 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -28,27 +28,27 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; +import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakLink; +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.bucket.DefaultBucketProperties; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.http.RiakBucketInfo; import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.query.LinkWalkStep; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.WalkResult; +import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.util.UnmodifiableIterator; import com.basho.riak.client.http.request.RequestMeta; import com.basho.riak.client.http.request.RiakWalkSpec; import com.basho.riak.client.http.response.BucketResponse; import com.basho.riak.client.http.response.MapReduceResponse; import com.basho.riak.client.http.response.WalkResponse; import com.basho.riak.client.http.util.Constants; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.bucket.DefaultBucketProperties; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.query.LinkWalkStep; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.WalkResult; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.util.UnmodifiableIterator; /** * @author russell diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index cb78f324b..8ed3bfead 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -18,7 +18,12 @@ import java.io.IOException; import java.util.Iterator; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.cap.ClientId; import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.WalkResult; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; @@ -32,11 +37,6 @@ import com.basho.riak.client.http.response.MapReduceResponse; import com.basho.riak.client.http.response.StoreResponse; import com.basho.riak.client.http.response.WithBodyResponse; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.cap.ClientId; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.WalkResult; /** * Adapts the old {@link RiakClient} to the new {@link RawClient} interface. diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index 16c35e2b0..df2b1710d 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -30,18 +30,18 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.bucket.DefaultBucketProperties; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.WalkResult; +import com.basho.riak.client.query.LinkWalkStep.Accumulate; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.bucket.DefaultBucketProperties; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.cap.VClock; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.query.LinkWalkStep.Accumulate; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.WalkResult; -import com.basho.riak.newapi.util.UnmodifiableIterator; +import com.basho.riak.client.util.UnmodifiableIterator; import com.basho.riak.pbc.MapReduceResponseSource; import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.mapreduce.MapReduceResponse; diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index 02b773c30..ac323b606 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -23,23 +23,23 @@ import java.util.LinkedList; import java.util.List; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.query.BucketKeyMapReduce; +import com.basho.riak.client.query.LinkWalkStep; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.WalkResult; +import com.basho.riak.client.query.functions.JSSourceFunction; +import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.http.util.Constants; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.bucket.BucketProperties; -import com.basho.riak.newapi.convert.ConversionException; -import com.basho.riak.newapi.query.BucketKeyMapReduce; -import com.basho.riak.newapi.query.LinkWalkStep; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.WalkResult; -import com.basho.riak.newapi.query.functions.JSSourceFunction; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; import com.basho.riak.pbc.IRequestMeta; import com.basho.riak.pbc.KeySource; import com.basho.riak.pbc.MapReduceResponseSource; diff --git a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java index 100b80fc5..b11a44312 100644 --- a/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java +++ b/src/main/java/com/basho/riak/client/raw/query/LinkWalkSpec.java @@ -16,8 +16,8 @@ import java.util.Iterator; import java.util.LinkedList; -import com.basho.riak.newapi.query.LinkWalkStep; -import com.basho.riak.newapi.util.UnmodifiableIterator; +import com.basho.riak.client.query.LinkWalkStep; +import com.basho.riak.client.util.UnmodifiableIterator; /** * An immutable class that represents a link walk specification diff --git a/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java index f6bd721b5..4da7c4454 100644 --- a/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java +++ b/src/main/java/com/basho/riak/client/raw/query/MapReduceTimeoutException.java @@ -13,7 +13,7 @@ */ package com.basho.riak.client.raw.query; -import com.basho.riak.newapi.RiakException; +import com.basho.riak.client.RiakException; /** * @author russell diff --git a/src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java b/src/main/java/com/basho/riak/client/util/UnmodifiableIterator.java similarity index 97% rename from src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java rename to src/main/java/com/basho/riak/client/util/UnmodifiableIterator.java index 56bb516c9..ae788d0bf 100644 --- a/src/main/java/com/basho/riak/newapi/util/UnmodifiableIterator.java +++ b/src/main/java/com/basho/riak/client/util/UnmodifiableIterator.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.util; +package com.basho.riak.client.util; import java.util.Iterator; diff --git a/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java b/src/test/java/com/basho/riak/client/cap/ClobberMutationTest.java similarity index 89% rename from src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java rename to src/test/java/com/basho/riak/client/cap/ClobberMutationTest.java index 02b99d21a..faa74bbaf 100644 --- a/src/test/java/com/basho/riak/newapi/cap/ClobberMutationTest.java +++ b/src/test/java/com/basho/riak/client/cap/ClobberMutationTest.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.cap; +package com.basho.riak.client.cap; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; @@ -19,6 +19,8 @@ import org.junit.Test; +import com.basho.riak.client.cap.ClobberMutation; + /** * @author russell * @@ -27,7 +29,7 @@ public class ClobberMutationTest { /** * Test method for - * {@link com.basho.riak.newapi.cap.ClobberMutation#ClobberMutation(java.lang.Object)} + * {@link com.basho.riak.client.cap.ClobberMutation#ClobberMutation(java.lang.Object)} * . */ @Test public void apply() { diff --git a/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java b/src/test/java/com/basho/riak/client/convert/ConversionUtilTest.java similarity index 93% rename from src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java rename to src/test/java/com/basho/riak/client/convert/ConversionUtilTest.java index f10da96ba..1264f31f6 100644 --- a/src/test/java/com/basho/riak/newapi/convert/ConversionUtilTest.java +++ b/src/test/java/com/basho/riak/client/convert/ConversionUtilTest.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.convert; +package com.basho.riak.client.convert; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -21,6 +21,9 @@ import org.junit.Test; +import com.basho.riak.client.convert.KeyUtil; +import com.basho.riak.client.convert.RiakKey; + /** * @author russell * diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index 7fe9d452b..97cd75d51 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -35,12 +35,12 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.cap.UnresolvedConflictException; -import com.basho.riak.newapi.convert.NoKeySpecifedException; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.cap.UnresolvedConflictException; +import com.basho.riak.client.convert.NoKeySpecifedException; import com.megacorp.commerce.LegacyCart; import com.megacorp.commerce.ShoppingCart; diff --git a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java index 086c7160a..b9b3c93ee 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java @@ -24,9 +24,9 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.bucket.Bucket; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.bucket.Bucket; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java index d67be08d8..99f37fecb 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java @@ -28,10 +28,10 @@ import org.junit.Before; import org.junit.Test; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.DomainBucket; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.DomainBucket; import com.megacorp.commerce.MergeCartResolver; import com.megacorp.commerce.ShoppingCart; diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java index 7f0eb3c65..1c6af106b 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketHTTP.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java index 260989552..a2af41285 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucketPB.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java index 6d69e777b..1c2ea3160 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPBucket.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java index 3fd234df0..3a723b2d7 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPClient.java @@ -19,12 +19,12 @@ import org.junit.Test; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.cap.Quora; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.query.functions.NamedErlangFunction; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java index b49ab67f2..44c84192e 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java +++ b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java @@ -24,14 +24,14 @@ import org.junit.Test; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.IRiakObject; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.RiakBucket; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.query.WalkResult; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.IRiakObject; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.RiakBucket; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.query.WalkResult; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java index 95163be5c..e4dea29d1 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduce.java @@ -30,20 +30,20 @@ import org.junit.BeforeClass; import org.junit.Test; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; import com.basho.riak.client.RiakLink; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; -import com.basho.riak.newapi.bucket.Bucket; -import com.basho.riak.newapi.bucket.DomainBucket; -import com.basho.riak.newapi.bucket.RiakBucket; -import com.basho.riak.newapi.builders.RiakObjectBuilder; -import com.basho.riak.newapi.query.MapReduceResult; -import com.basho.riak.newapi.query.filter.LessThanFilter; -import com.basho.riak.newapi.query.filter.StringToIntFilter; -import com.basho.riak.newapi.query.filter.TokenizeFilter; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedJSFunction; +import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.bucket.DomainBucket; +import com.basho.riak.client.bucket.RiakBucket; +import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.query.MapReduceResult; +import com.basho.riak.client.query.filter.LessThanFilter; +import com.basho.riak.client.query.filter.StringToIntFilter; +import com.basho.riak.client.query.filter.TokenizeFilter; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedJSFunction; import com.megacorp.commerce.GoogleStockDataItem; /** diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java index 46f590bb3..67edc91f6 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReduceHTTP.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java index 4e20f9e63..391cd4f69 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java +++ b/src/test/java/com/basho/riak/client/itest/ITestMapReducePB.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java index 2009d57b5..f18a0e0b0 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestPBBucket.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java index ccf7d6f93..809936873 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestPBClient.java +++ b/src/test/java/com/basho/riak/client/itest/ITestPBClient.java @@ -13,9 +13,9 @@ */ package com.basho.riak.client.itest; -import com.basho.riak.newapi.IRiakClient; -import com.basho.riak.newapi.RiakException; -import com.basho.riak.newapi.RiakFactory; +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; /** * @author russell diff --git a/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java b/src/test/java/com/basho/riak/client/query/filter/LogicalAndFilterTest.java similarity index 75% rename from src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java rename to src/test/java/com/basho/riak/client/query/filter/LogicalAndFilterTest.java index 1abee3818..ef9d00e4b 100644 --- a/src/test/java/com/basho/riak/newapi/query/filter/LogicalAndFilterTest.java +++ b/src/test/java/com/basho/riak/client/query/filter/LogicalAndFilterTest.java @@ -11,12 +11,19 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.filter; +package com.basho.riak.client.query.filter; import static org.junit.Assert.assertArrayEquals; import org.junit.Test; +import com.basho.riak.client.query.filter.FloatToStringFilter; +import com.basho.riak.client.query.filter.IntToStringFilter; +import com.basho.riak.client.query.filter.KeyFilter; +import com.basho.riak.client.query.filter.LogicalAndFilter; +import com.basho.riak.client.query.filter.SetMemberFilter; +import com.basho.riak.client.query.filter.SimilarToFilter; + /** * @author russell * @@ -25,7 +32,7 @@ public class LogicalAndFilterTest { /** * Test method for - * {@link com.basho.riak.newapi.query.filter.LogicalAndFilter#asArray()}. + * {@link com.basho.riak.client.query.filter.LogicalAndFilter#asArray()}. */ @Test public void testAsArray() { final KeyFilter[] filters = new KeyFilter[] { new FloatToStringFilter(), new IntToStringFilter(), diff --git a/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java b/src/test/java/com/basho/riak/client/query/serialize/FunctionToJsonTest.java similarity index 78% rename from src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java rename to src/test/java/com/basho/riak/client/query/serialize/FunctionToJsonTest.java index eee177289..eac0c44f0 100644 --- a/src/test/java/com/basho/riak/newapi/query/serialize/FunctionToJsonTest.java +++ b/src/test/java/com/basho/riak/client/query/serialize/FunctionToJsonTest.java @@ -11,7 +11,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.basho.riak.newapi.query.serialize; +package com.basho.riak.client.query.serialize; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -24,11 +24,17 @@ import org.codehaus.jackson.JsonGenerator; import org.junit.Test; -import com.basho.riak.newapi.query.functions.Function; -import com.basho.riak.newapi.query.functions.JSBucketKeyFunction; -import com.basho.riak.newapi.query.functions.JSSourceFunction; -import com.basho.riak.newapi.query.functions.NamedErlangFunction; -import com.basho.riak.newapi.query.functions.NamedJSFunction; +import com.basho.riak.client.query.functions.Function; +import com.basho.riak.client.query.functions.JSBucketKeyFunction; +import com.basho.riak.client.query.functions.JSSourceFunction; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedJSFunction; +import com.basho.riak.client.query.serialize.FunctionToJson; +import com.basho.riak.client.query.serialize.FunctionWriter; +import com.basho.riak.client.query.serialize.JSBucketKeyFunctionWriter; +import com.basho.riak.client.query.serialize.JSSourceFunctionWriter; +import com.basho.riak.client.query.serialize.NamedErlangFunctionWriter; +import com.basho.riak.client.query.serialize.NamedJSFunctionWriter; /** * @author russell diff --git a/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java b/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java index ce535edbe..4dcba3ee3 100644 --- a/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java +++ b/src/test/java/com/megacorp/commerce/GoogleStockDataItem.java @@ -15,7 +15,7 @@ import org.codehaus.jackson.annotate.JsonProperty; -import com.basho.riak.newapi.convert.RiakKey; +import com.basho.riak.client.convert.RiakKey; public class GoogleStockDataItem { //{"Date":"2010-01-05","Open":627.18,"High":627.84,"Low":621.54,"Close":623.99,"Volume":3004700,"Adj. Close":623.99} diff --git a/src/test/java/com/megacorp/commerce/MergeCartResolver.java b/src/test/java/com/megacorp/commerce/MergeCartResolver.java index 6be455db3..5fd5330bb 100644 --- a/src/test/java/com/megacorp/commerce/MergeCartResolver.java +++ b/src/test/java/com/megacorp/commerce/MergeCartResolver.java @@ -3,8 +3,8 @@ import java.util.Collection; import java.util.HashSet; -import com.basho.riak.newapi.cap.ConflictResolver; -import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.UnresolvedConflictException; /** * A simple example of a conflict resolver for the ShoppingCart domain type. diff --git a/src/test/java/com/megacorp/commerce/ShoppingCart.java b/src/test/java/com/megacorp/commerce/ShoppingCart.java index 9ffad0bf9..a2ec7e0cf 100644 --- a/src/test/java/com/megacorp/commerce/ShoppingCart.java +++ b/src/test/java/com/megacorp/commerce/ShoppingCart.java @@ -21,7 +21,7 @@ import org.codehaus.jackson.annotate.JsonCreator; import org.codehaus.jackson.annotate.JsonProperty; -import com.basho.riak.newapi.convert.RiakKey; +import com.basho.riak.client.convert.RiakKey; /** * A simple domain object for the sake of ITests. diff --git a/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java index 1a5e7fab1..05a6c81e0 100644 --- a/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java +++ b/src/test/java/com/megacorp/kv/exceptions/MyCheckedBusinessException.java @@ -13,7 +13,7 @@ */ package com.megacorp.kv.exceptions; -import com.basho.riak.newapi.cap.UnresolvedConflictException; +import com.basho.riak.client.cap.UnresolvedConflictException; /** * @author russell From dac9836af7c89df7b24fa91610e6c55580130b0c Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Wed, 4 May 2011 15:51:44 +0100 Subject: [PATCH 024/764] Deprecate legacy RiakClient and RiakObject --- .../basho/riak/client/DefaultRiakClient.java | 6 +- .../basho/riak/client/DefaultRiakObject.java | 5 +- .../com/basho/riak/client/RiakClient.java | 14 +- .../com/basho/riak/client/RiakObject.java | 14 +- .../riak/client/http/HttpRiakClient.java | 373 ------------------ .../riak/client/http/HttpRiakObject.java | 373 ------------------ .../basho/riak/client/http/RiakClient.java | 2 +- .../basho/riak/client/http/RiakObject.java | 2 +- 8 files changed, 31 insertions(+), 758 deletions(-) delete mode 100644 src/main/java/com/basho/riak/client/http/HttpRiakClient.java delete mode 100644 src/main/java/com/basho/riak/client/http/HttpRiakObject.java diff --git a/src/main/java/com/basho/riak/client/DefaultRiakClient.java b/src/main/java/com/basho/riak/client/DefaultRiakClient.java index 4eb106b35..e9b893820 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakClient.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakClient.java @@ -15,13 +15,9 @@ /** * A default implementation of IRiakClient. * - * The class also includes the deprecated http.RiakClient methods to - * ease the transition between versions. - * - * RiakClient provides convenient, transport agnostic ways to perform perform + * Provides convenient, transport agnostic ways to perform * bucket and query operations on Riak. * - * In the next release this class will be renamed and all deprecated methods removed. * @author russell * */ diff --git a/src/main/java/com/basho/riak/client/DefaultRiakObject.java b/src/main/java/com/basho/riak/client/DefaultRiakObject.java index 1ef1c6833..268784ec5 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakObject.java @@ -27,10 +27,9 @@ import com.basho.riak.client.util.UnmodifiableIterator; /** - * An implementation of {@link IRiakObject} that also contains the deprecated - * http.RiakObject methods to facilitate transition between versions. + * An implementation of {@link IRiakObject} * - * A RiakObject models the meta data and data stored at a bucket/key location in + * Models the meta data and data stored at a bucket/key location in * Riak. * * @author russell diff --git a/src/main/java/com/basho/riak/client/RiakClient.java b/src/main/java/com/basho/riak/client/RiakClient.java index 6ee5ad790..e6b02f245 100644 --- a/src/main/java/com/basho/riak/client/RiakClient.java +++ b/src/main/java/com/basho/riak/client/RiakClient.java @@ -39,8 +39,20 @@ import com.basho.riak.client.util.Constants; /** - * Primary interface for interacting with Riak via HTTP. + * Legacy interface for interacting with Riak via HTTP. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.RiakClient + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ *

Please see also IRiakClient, IRiakObject for the new API

+ * @see com.basho.riak.client.http.RiakClient + * @see IRiakClient + * @see IRiakObject */ +@Deprecated public class RiakClient { private ClientHelper helper; diff --git a/src/main/java/com/basho/riak/client/RiakObject.java b/src/main/java/com/basho/riak/client/RiakObject.java index 295218495..1827776e0 100644 --- a/src/main/java/com/basho/riak/client/RiakObject.java +++ b/src/main/java/com/basho/riak/client/RiakObject.java @@ -41,8 +41,20 @@ import com.basho.riak.client.util.Constants; /** - * A Riak object. + * A (legacy REST) Riak object. + * + * @deprecated with the addition of a protocol buffers client in 0.14 all the + * existing REST client code should be in client.http.* this class + * has therefore been moved. Please use + * com.basho.riak.client.http.RiakObject + * instead. + *

WARNING: This class will be REMOVED in the next version.

+ *

Please see also IRiakClient, IRiakObject for the new API

+ * @see com.basho.riak.client.http.RiakObject + * @see IRiakClient + * @see IRiakObject */ +@Deprecated public class RiakObject { private RiakClient riak; diff --git a/src/main/java/com/basho/riak/client/http/HttpRiakClient.java b/src/main/java/com/basho/riak/client/http/HttpRiakClient.java deleted file mode 100644 index 910168a4d..000000000 --- a/src/main/java/com/basho/riak/client/http/HttpRiakClient.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * This file is provided 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.basho.riak.client.http; - -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.httpclient.HttpClient; - -import com.basho.riak.client.http.request.MapReduceBuilder; -import com.basho.riak.client.http.request.RequestMeta; -import com.basho.riak.client.http.request.RiakWalkSpec; -import com.basho.riak.client.http.response.BucketResponse; -import com.basho.riak.client.http.response.FetchResponse; -import com.basho.riak.client.http.response.HttpResponse; -import com.basho.riak.client.http.response.MapReduceResponse; -import com.basho.riak.client.http.response.RiakExceptionHandler; -import com.basho.riak.client.http.response.RiakIORuntimeException; -import com.basho.riak.client.http.response.RiakResponseRuntimeException; -import com.basho.riak.client.http.response.StoreResponse; -import com.basho.riak.client.http.response.StreamHandler; -import com.basho.riak.client.http.response.WalkResponse; -import com.basho.riak.client.http.util.ClientUtils; - -/** - * @author russell - * - */ -public interface HttpRiakClient { - - RiakConfig getConfig(); - - /** - * Set the properties for a Riak bucket. - * - * @param bucket - * The bucket name. - * @param bucketInfo - * Contains the schema to use for the bucket. Refer to the Riak - * documentation for a list of the recognized properties and the - * format of their values. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link HttpResponse} containing HTTP response information. - * - * @throws IllegalArgumentException - * If the provided schema values cannot be serialized to send to - * Riak. - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - */ - HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo, RequestMeta meta); - - HttpResponse setBucketSchema(String bucket, RiakBucketInfo bucketInfo); - - /** - * Return the properties for a Riak bucket without listing the keys in it. - * - * @param bucket - * The target bucket. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link BucketResponse} containing HTTP response information and - * the parsed schema - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - BucketResponse getBucketSchema(String bucket, RequestMeta meta); - - BucketResponse getBucketSchema(String bucket); - - /** - * Return the properties and keys for a Riak bucket. - * - * @param bucket - * The bucket to list. - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * and query parameters. - * - * @return {@link BucketResponse} containing HTTP response information and - * the parsed schema and keys - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - BucketResponse listBucket(String bucket, RequestMeta meta); - - BucketResponse listBucket(String bucket); - - /** - * Same as {@link RiakClient#listBucket(String, RequestMeta)}, except - * streams the response, so the user must remember to call - * {@link BucketResponse#close()} on the return value. - */ - BucketResponse streamBucket(String bucket, RequestMeta meta); - - BucketResponse streamBucket(String bucket); - - /** - * Store a {@link RiakObject}. - * - * @param object - * The {@link RiakObject} to store. - * @param meta - * Extra metadata to attach to the request such as w and dw - * values for the request, HTTP headers, and other query - * parameters. See - * {@link RequestMeta#writeParams(Integer, Integer)}. - * - * @return A {@link StoreResponse} containing HTTP response information and - * any updated information returned by the server such as the - * vclock, last modified date. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - StoreResponse store(RiakObject object, RequestMeta meta); - - StoreResponse store(RiakObject object); - - /** - * Fetch metadata (e.g. vclock, last modified, vtag) for the - * {@link RiakObject} stored at bucket and key. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * {@link RequestMeta#readParams(int)}. - * - * @return {@link FetchResponse} containing HTTP response information and a - * {@link RiakObject} containing only metadata and no value. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - FetchResponse fetchMeta(String bucket, String key, RequestMeta meta); - - FetchResponse fetchMeta(String bucket, String key); - - /** - * Fetch the {@link RiakObject} (which can include sibling objects) stored - * at bucket and key. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * {@link RequestMeta#readParams(int)}. - * - * @return {@link FetchResponse} containing HTTP response information and a - * {@link RiakObject} or sibling objects. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - */ - FetchResponse fetch(String bucket, String key, RequestMeta meta); - - FetchResponse fetch(String bucket, String key); - - /** - * Similar to fetch(), except the HTTP connection is left open for - * successful responses, and the Riak response is provided as a stream. - * The user must remember to call {@link FetchResponse#close()} on the - * return value. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * RequestMeta.readParams(). - * - * @return A streaming {@link FetchResponse} containing HTTP response - * information and the response stream. The HTTP connection must be - * closed manually by the user by calling - * {@link FetchResponse#close()}. - */ - FetchResponse stream(String bucket, String key, RequestMeta meta); - - FetchResponse stream(String bucket, String key); - - /** - * Fetch and process the object stored at bucket and - * key as a stream. - * - * @param bucket - * The bucket containing the {@link RiakObject} to fetch. - * @param key - * The key of the {@link RiakObject} to fetch. - * @param handler - * A {@link StreamHandler} to process the Riak response. - * @param meta - * Extra metadata to attach to the request such as an r- value - * for the request, HTTP headers, and other query parameters. See - * RequestMeta.readParams(). - * - * @return Result from calling handler.process() or true if handler is null. - * - * @throws IOException - * If an error occurs during communication with the Riak server. - * - * @see StreamHandler - */ - boolean stream(String bucket, String key, StreamHandler handler, RequestMeta meta) throws IOException; - - /** - * Delete the object at bucket and key. - * - * @param bucket - * The bucket containing the object. - * @param key - * The key of the object - * @param meta - * Extra metadata to attach to the request such as w and dw - * values for the request, HTTP headers, and other query - * parameters. See - * {@link RequestMeta#writeParams(Integer, Integer)}. - * - * @return {@link HttpResponse} containing HTTP response information. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - */ - HttpResponse delete(String bucket, String key, RequestMeta meta); - - HttpResponse delete(String bucket, String key); - - /** - * Perform a map/reduce link walking operation and return the objects for - * which the "accumulate" flag is true. - * - * @param bucket - * The bucket of the "starting object" - * @param key - * The key of the "starting object" - * @param walkSpec - * A URL-path (omit beginning /) of the form - * bucket,tag-spec,accumulateFlag The - * tag-spec "_" matches all tags. - * accumulateFlag is either the String "1" or "0". - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * or query parameters. - * - * @return {@link WalkResponse} containing HTTP response information and a - * List of Lists, where each sub-list - * corresponds to a walkSpec element that had - * accumulateFlag equal to 1. - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server returns a malformed response. - * - * @see RiakWalkSpec - */ - WalkResponse walk(String bucket, String key, String walkSpec, RequestMeta meta); - - WalkResponse walk(String bucket, String key, String walkSpec); - - WalkResponse walk(String bucket, String key, RiakWalkSpec walkSpec); - - /** - * Execute a map reduce job on the Riak server. - * - * @param job - * JSON string representing the map reduce job to run, which can - * be created using {@link MapReduceBuilder} - * @param meta - * Extra metadata to attach to the request such as HTTP headers - * or query parameters. - * - * @return {@link MapReduceResponse} containing HTTP response information - * and the result of the map reduce job - * - * @throws RiakIORuntimeException - * If an error occurs during communication with the Riak server. - * @throws RiakResponseRuntimeException - * If the Riak server does not return a valid JSON array. - */ - MapReduceResponse mapReduce(String job, RequestMeta meta); - - MapReduceResponse mapReduce(String job); - - /** - * A convenience method for creating a MapReduceBuilder used for building a - * map reduce job to submission to this client - * - * @param bucket - * The bucket to perform the map reduce job over - * @return A {@link MapReduceBuilder} to build the map reduce job - */ - MapReduceBuilder mapReduceOverBucket(String bucket); - - /** - * Same as {@link RiakClient#mapReduceOverBucket(String)}, except over a set - * of objects instead of a bucket. - * - * @param objects - * A set of objects represented as a map of { bucket : [ list of - * keys in bucket ] } - */ - MapReduceBuilder mapReduceOverObjects(Map> objects); - - /** - * The installed exception handler or null if not installed - */ - RiakExceptionHandler getExceptionHandler(); - - /** - * If an exception handler is provided, then the Riak client will hand - * exceptions to the handler rather than throwing them. - * {@link ClientUtils#throwChecked(Throwable)} can be used to throw - * undeclared checked exceptions to effectively "convert" RiakClient's - * unchecked exceptions to checked exceptions. - */ - void setExceptionHandler(RiakExceptionHandler exceptionHandler); - - /** - * Return the {@link HttpClient} used to make requests, which can be - * configured. - */ - HttpClient getHttpClient(); - - /** - * A 4-byte unique ID for this client. The ID is base 64 encoded and sent to - * Riak to generating the object vclock on store operations. Refer to the - * Riak documentation and - * http://lists.basho.com/pipermail/riak-users_lists.basho.com/2009- - * November/000153.html for information about the client ID. - */ - byte[] getClientId(); - - void setClientId(String clientId); - -} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/HttpRiakObject.java b/src/main/java/com/basho/riak/client/http/HttpRiakObject.java deleted file mode 100644 index 0282677e6..000000000 --- a/src/main/java/com/basho/riak/client/http/HttpRiakObject.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * This file is provided 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.basho.riak.client.http; - -import java.io.InputStream; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.commons.httpclient.HttpMethod; - -import com.basho.riak.client.http.RiakObject.LinkBuilder; -import com.basho.riak.client.http.request.RequestMeta; -import com.basho.riak.client.http.request.RiakWalkSpec; -import com.basho.riak.client.http.response.FetchResponse; -import com.basho.riak.client.http.response.HttpResponse; -import com.basho.riak.client.http.response.StoreResponse; - -/** - * @author russell - * - */ -public interface HttpRiakObject { - - /** - * A {@link RiakObject} can be loosely attached to the {@link RiakClient} - * from which retrieve it was retrieved. Calling convenience methods like - * {@link RiakObject#store()} will store this object use that client. - */ - RiakClient getRiakClient(); - - RiakObject setRiakClient(RiakClient client); - - /** - * Copy the metadata and value from object. The bucket and key - * are not copied. - * - * @param object - * The source object to copy from - */ - void copyData(RiakObject object); - - /** - * Update the object's metadata. This usually happens when Riak returns - * updated metadata from a store operation. - * - * @param response - * Response from a store operation containing an updated vclock, - * last modified date, and vtag - */ - void updateMeta(StoreResponse response); - - /** - * Update the object's metadata from a fetch or fetchMeta operation - * - * @param response - * Response from a fetch or fetchMeta operation containing a - * vclock, last modified date, and vtag - */ - void updateMeta(FetchResponse response); - - /** - * The object's bucket - */ - String getBucket(); - - /** - * The object's key - */ - String getKey(); - - /** - * The object's value - */ - String getValue(); - - byte[] getValueAsBytes(); - - void setValue(String value); - - void setValue(byte[] value); - - /** - * Set the object's value as a stream. A value set here is independent of - * and has precedent over any value set using setValue(): - * {@link RiakObject#writeToHttpMethod(HttpMethod)} will always write the - * value from getValueStream() if it is not null. Calling getValue() will - * always return values set via setValue(), and calling getValueStream() - * will always return the stream set via setValueStream. - * - * @param in - * Input stream representing the object's value - * @param len - * Length of the InputStream or null if unknown. If null, the - * value will be buffered in memory to determine its size before - * sending to the server. - */ - void setValueStream(InputStream in, Long len); - - void setValueStream(InputStream in); - - InputStream getValueStream(); - - void setValueStreamLength(Long len); - - Long getValueStreamLength(); - - /** - * The object's links -- may be empty, but never be null. - * - * @see {@link RiakObject#addLink()}, {@link RiakObject#removeLink()}, {@link RiakObject#iterator()}, {@link RiakObject#hasLinks()} and , {@link RiakObject#numLinks()} - * - * @return the list of {@link RiakLink}s for this - * RiakObject - * @deprecated please use {@link RiakObject#iterableLinks())} to iterate over the - * collection of {@link RiakLink}s. Attempting to mutate the - * collection will result in UnsupportedOperationException in - * future versions. Use {@link RiakObject#addLink()} and {@link RiakObject#removeLink()} instead. - * Use {@link RiakObject#hasLinks()}, {@link RiakObject#numLinks()} and {@link RiakObject#hasLink(RiakLink)} - * to query state of links. - */ - @Deprecated List getLinks(); - - /** - * Makes a *deep* copy of links. - * - * Changes made to the original collection and its contents will not be reflected - * in this RiakObject's links. Use {@link RiakObject#addLink(RiakLink)}, - * {@link RiakObject#removeLink(RiakLink)} and {@link RiakObject#setLinks(List)} to alter the collection. - * @param links a List of {@link RiakLink} - */ - void setLinks(List links); - - /** - * Add link to this RiakObject's links. - * @param link a {@link RiakLink} to add. - * @return this RiakObject. - */ - RiakObject addLink(RiakLink link); - - /** - * Remove a {@link RiakLink} from this RiakObject. - * @param link the {@link RiakLink} to remove - * @return this RiakObject - */ - RiakObject removeLink(final RiakLink link); - - /** - * Does this RiakObject have any {@link RiakLink}s? - * @return true if there are links, false otherwise - */ - boolean hasLinks(); - - /** - * How many {@link RiakLink}s does this RiakObject have? - * @return the number of {@link RiakLink}s this object has. - */ - int numLinks(); - - /** - * Checks if the collection of RiakLinks contains the one passed in. - * @param riakLink a RiakLink - * @return true if the RiakObject's link collection contains riakLink. - */ - boolean hasLink(final RiakLink riakLink); - - /** - * User-specified metadata for the object in the form of key-value pairs -- - * may be empty, but never be null. New key-value pairs can be added using - * addUsermeta() - * - * @deprecated Future versions will return an unmodifiable view of the user meta. Please use - * {@link RiakObject#addUsermeta(String, String)}, - * {@link RiakObject#removeUsermetaItem(String)}, - * {@link RiakObject#setUsermeta(Map)}, - * {@link RiakObject#hasUsermetaItem(String)}, - * {@link RiakObject#hasUsermeta()} and - * {@link RiakObject#getUsermetaItem(String)} to mutate and query the User meta collection - */ - @Deprecated Map getUsermeta(); - - /** - * Creates a copy of userMetaData. Changes made to the original collection will not be - * reflected in the RiakObject's state. - * @param userMetaData - */ - void setUsermeta(final Map userMetaData); - - /** - * Adds the key, value to the collection of user meta for this object. - * @param key - * @param value - * @return this RiakObject. - */ - RiakObject addUsermetaItem(String key, String value); - - /** - * @return true if there are any user meta data set on this RiakObject. - */ - boolean hasUsermeta(); - - /** - * @return how many user meta data items this RiakObject has. - */ - int numUsermetaItems(); - - /** - * @param key - * @return - */ - boolean hasUsermetaItem(String key); - - /** - * Get an item of user meta data. - * @param key the user meta data item key - * @return The value for the given key or null. - */ - String getUsermetaItem(String key); - - /** - * @param key the key of the item to remove - */ - void removeUsermetaItem(String key); - - Iterable usermetaKeys(); - - /** - * The object's content type as a MIME type - */ - String getContentType(); - - void setContentType(String contentType); - - /** - * The object's opaque vclock assigned by Riak - */ - String getVclock(); - - /** - * The modification date of the object determined by Riak - */ - String getLastmod(); - - /** - * Convenience method to get the last modified header parsed into a Date - * object. Returns null if header is null, malformed, or cannot be parsed. - */ - Date getLastmodAsDate(); - - /** - * An entity tag for the object assigned by Riak - */ - String getVtag(); - - /** - * Convenience method for calling - * {@link RiakClient#store(RiakObject, RequestMeta)} followed by - * {@link RiakObject#updateMeta(StoreResponse)} - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to store it with. - */ - StoreResponse store(RequestMeta meta); - - StoreResponse store(); - - /** - * Store this object to a different Riak instance. - * - * @param riak - * Riak instance to store this object to - * @param meta - * Same as {@link RiakClient#store(RiakObject, RequestMeta)} - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to store it with. - */ - StoreResponse store(RiakClient riak, RequestMeta meta); - - /** - * Convenience method for calling {@link RiakClient#fetch(String, String)} - * followed by {@link RiakObject#copyData(RiakObject)} - * - * @param meta - * Same as {@link RiakClient#fetch(String, String, RequestMeta)} - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to refetch it from. - */ - FetchResponse fetch(RequestMeta meta); - - FetchResponse fetch(); - - /** - * Convenience method for calling - * {@link RiakClient#fetchMeta(String, String, RequestMeta)} followed by - * {@link RiakObject#updateMeta(FetchResponse)} - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to refetch meta from. - */ - FetchResponse fetchMeta(RequestMeta meta); - - FetchResponse fetchMeta(); - - /** - * Convenience method for calling - * {@link RiakClient#delete(String, String, RequestMeta)}. - * - * @throws IllegalStateException - * if this object was not fetched from a Riak instance, so there - * is not associated server to delete from. - */ - HttpResponse delete(RequestMeta meta); - - HttpResponse delete(); - - /** - * Convenience methods for building a link walk specification starting from - * this object and calling - * {@link RiakClient#walk(String, String, RiakWalkSpec)} - * - * @param bucket - * The bucket to follow object links to - * @param tag - * The link tags to follow from this object - * @param keep - * Whether to keep the output from this link walking step. If not - * specified, then the output is only kept from the last step. - * @return A {@link LinkBuilder} object to continue building the walk query - * or to run it. - */ - LinkBuilder walk(String bucket, String tag, boolean keep); - - LinkBuilder walk(String bucket, String tag); - - LinkBuilder walk(String bucket, boolean keep); - - LinkBuilder walk(String bucket); - - LinkBuilder walk(); - - LinkBuilder walk(boolean keep); - - /** - * Serializes this object to an existing {@link HttpMethod} which can be - * sent as an HTTP request. Specifically, sends the object's link, - * user-defined metadata and vclock as HTTP headers and the value as the - * body. Used by {@link RiakClient} to create PUT requests. - */ - void writeToHttpMethod(HttpMethod httpMethod); - - /** - * A thread safe, snapshot Iterable view of the state of this RiakObject's {@link RiakLink}s at call time. - * Modifications are *NOT* supported. - * @return Iterable for this RiakObject's {@link RiakLink}s - */ - Iterable iterableLinks(); - -} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/RiakClient.java b/src/main/java/com/basho/riak/client/http/RiakClient.java index 2ee2ceb62..47e925ecd 100644 --- a/src/main/java/com/basho/riak/client/http/RiakClient.java +++ b/src/main/java/com/basho/riak/client/http/RiakClient.java @@ -41,7 +41,7 @@ /** * Primary interface for interacting with Riak via HTTP. */ -public class RiakClient implements HttpRiakClient { +public class RiakClient { private ClientHelper helper; diff --git a/src/main/java/com/basho/riak/client/http/RiakObject.java b/src/main/java/com/basho/riak/client/http/RiakObject.java index ae3b49af1..618632b0b 100644 --- a/src/main/java/com/basho/riak/client/http/RiakObject.java +++ b/src/main/java/com/basho/riak/client/http/RiakObject.java @@ -43,7 +43,7 @@ /** * A Riak object. */ -public class RiakObject implements HttpRiakObject { +public class RiakObject { private RiakClient riak; private String bucket; From 4d59c2314b7ba7c4826bcadfb963edffd8232e6e Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 5 May 2011 10:55:54 +0100 Subject: [PATCH 025/764] Use Java standard library Callable instead of Command Allow user to supply Retrier impl to operations Add a reusable default retrier to the default client --- .../basho/riak/client/DefaultRiakClient.java | 70 ++++++++++++++----- .../riak/client/bucket/DefaultBucket.java | 21 +++--- .../riak/client/bucket/DomainBucket.java | 13 ++-- .../basho/riak/client/bucket/FetchBucket.java | 33 +++++---- .../basho/riak/client/bucket/WriteBucket.java | 43 ++++++------ .../client/builders/DomainBucketBuilder.java | 12 ++-- .../basho/riak/client/cap/DefaultRetrier.java | 67 ++++++++++++++---- .../com/basho/riak/client/cap/Retrier.java | 5 +- .../riak/client/operations/DeleteObject.java | 22 +++--- .../riak/client/operations/FetchObject.java | 20 +++--- .../riak/client/operations/StoreObject.java | 27 +++---- .../com/basho/riak/client/raw/Command.java | 26 ------- .../basho/riak/client/itest/ITestBucket.java | 11 +-- .../riak/client/itest/ITestDomainBucket.java | 11 ++- 14 files changed, 229 insertions(+), 152 deletions(-) delete mode 100644 src/main/java/com/basho/riak/client/raw/Command.java diff --git a/src/main/java/com/basho/riak/client/DefaultRiakClient.java b/src/main/java/com/basho/riak/client/DefaultRiakClient.java index e9b893820..a019dac9d 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakClient.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakClient.java @@ -1,15 +1,15 @@ package com.basho.riak.client; -import java.io.IOException; +import java.util.concurrent.Callable; import com.basho.riak.client.bucket.Bucket; import com.basho.riak.client.bucket.FetchBucket; import com.basho.riak.client.bucket.WriteBucket; import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.query.BucketKeyMapReduce; import com.basho.riak.client.query.BucketMapReduce; import com.basho.riak.client.query.LinkWalk; -import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; /** @@ -24,70 +24,98 @@ public final class DefaultRiakClient implements IRiakClient { private final RawClient client; + private final Retrier retrier; /** * @param client + * @param defaultRetrier */ - DefaultRiakClient(RawClient client) { + DefaultRiakClient(final RawClient client, final Retrier defaultRetrier) { this.client = client; + this.retrier = defaultRetrier; + } + + /** + * @param client + */ + DefaultRiakClient(final RawClient client) { + this(client, new DefaultRetrier(3)); } // BUCKET OPS - public WriteBucket updateBucket(Bucket b) { - WriteBucket op = new WriteBucket(client, b); - return op; + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#updateBucket(com.basho.riak.client.bucket.Bucket) + */ + public WriteBucket updateBucket(final Bucket b) { + return new WriteBucket(client, b.getName(), retrier); } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#fetchBucket(java.lang.String) + */ public FetchBucket fetchBucket(String bucketName) { - FetchBucket op = new FetchBucket(client, bucketName); - return op; + return new FetchBucket(client, bucketName, retrier); } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#createBucket(java.lang.String) + */ public WriteBucket createBucket(String bucketName) { - WriteBucket op = new WriteBucket(client, bucketName); - return op; + return new WriteBucket(client, bucketName, retrier); } // CLIENT ID + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#setClientId(byte[]) + */ public IRiakClient setClientId(final byte[] clientId) throws RiakException { if (clientId == null || clientId.length != 4) { throw new IllegalArgumentException("Client Id must be 4 bytes long"); } final byte[] cloned = clientId.clone(); - new DefaultRetrier().attempt(new Command() { - public Void execute() throws IOException { + retrier.attempt(new Callable() { + public Void call() throws Exception { client.setClientId(cloned); return null; } - }, 3); + }); return this; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#generateAndSetClientId() + */ public byte[] generateAndSetClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { + final byte[] clientId = retrier.attempt(new Callable() { + public byte[] call() throws Exception { return client.generateAndSetClientId(); } - }, 3); + }); return clientId; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#getClientId() + */ public byte[] getClientId() throws RiakException { - final byte[] clientId = new DefaultRetrier().attempt(new Command() { - public byte[] execute() throws IOException { + final byte[] clientId = retrier.attempt(new Callable() { + public byte[] call() throws Exception { return client.getClientId(); } - }, 3); + }); return clientId; } // QUERY + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#mapReduce() + */ public BucketKeyMapReduce mapReduce() { return new BucketKeyMapReduce(client); } @@ -101,6 +129,10 @@ public BucketMapReduce mapReduce(String bucket) { return new BucketMapReduce(client, bucket); } + /* + * (non-Javadoc) + * @see com.basho.riak.client.IRiakClient#walk(com.basho.riak.client.IRiakObject) + */ public LinkWalk walk(IRiakObject startObject) { return new LinkWalk(client, startObject); } diff --git a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java index db732b6f2..69340f744 100644 --- a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java @@ -25,6 +25,7 @@ import com.basho.riak.client.cap.DefaultResolver; import com.basho.riak.client.cap.Mutation; import com.basho.riak.client.cap.Quorum; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.cap.VClock; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.convert.Converter; @@ -46,15 +47,17 @@ public class DefaultBucket implements Bucket { private final String name; private final BucketProperties properties; private final RawClient client; + private final Retrier retrier; /** * @param properties * @param client */ - protected DefaultBucket(String name, BucketProperties properties, RawClient client) { + protected DefaultBucket(String name, BucketProperties properties, RawClient client, final Retrier retrier) { this.name = name; this.properties = properties; this.client = client; + this.retrier = retrier; } // / BUCKET PROPS @@ -234,7 +237,7 @@ public Iterable keys() throws RiakException { public StoreObject store(final String key, final String value) { final Bucket b = this; - return new StoreObject(client, name, key).withMutator(new Mutation() { + return new StoreObject(client, name, key, retrier).withMutator(new Mutation() { public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(b.getName(), key).withValue(value).build(); @@ -266,7 +269,7 @@ public StoreObject store(final T o) { if (key == null) { throw new NoKeySpecifedException(o); } - return new StoreObject(client, name, key) + return new StoreObject(client, name, key, retrier) .withConverter(new JSONConverter(clazz, name)) .withMutator(new ClobberMutation(o)) .withResolver(new DefaultResolver()); @@ -281,7 +284,7 @@ public StoreObject store(final T o) { public StoreObject store(final String key, final T o) { @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); - return new StoreObject(client, name, key). + return new StoreObject(client, name, key, retrier). withConverter(new JSONConverter(clazz, name, key)) .withMutator(new ClobberMutation(o)).withResolver(new DefaultResolver()); } @@ -297,7 +300,7 @@ public FetchObject fetch(T o) { if (key == null) { throw new NoKeySpecifedException(o); } - return new FetchObject(client, name, key) + return new FetchObject(client, name, key, retrier) .withConverter(new JSONConverter(clazz, name)) .withResolver(new DefaultResolver()); } @@ -309,7 +312,7 @@ public FetchObject fetch(T o) { * java.lang.Class) */ public FetchObject fetch(final String key, final Class type) { - return new FetchObject(client, name, key) + return new FetchObject(client, name, key, retrier) .withConverter(new JSONConverter(type, name)) .withResolver(new DefaultResolver()); } @@ -320,7 +323,7 @@ public FetchObject fetch(final String key, final Class type) { * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) */ public FetchObject fetch(String key) { - return new FetchObject(client, name, key) + return new FetchObject(client, name, key, retrier) .withResolver(new DefaultResolver()) .withConverter(new Converter() { @@ -346,7 +349,7 @@ public DeleteObject delete(T o) { if (key == null) { throw new NoKeySpecifedException(o); } - return new DeleteObject(client, name, key); + return new DeleteObject(client, name, key, retrier); } /* @@ -355,7 +358,7 @@ public DeleteObject delete(T o) { * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.String) */ public DeleteObject delete(String key) { - return new DeleteObject(client, name, key); + return new DeleteObject(client, name, key, retrier); } } diff --git a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java index 1a3629ab4..b7d4d6ec6 100644 --- a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java @@ -18,6 +18,7 @@ import com.basho.riak.client.cap.ConflictResolver; import com.basho.riak.client.cap.Mutation; import com.basho.riak.client.cap.MutationProducer; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.convert.Converter; import com.basho.riak.client.convert.KeyUtil; @@ -40,8 +41,8 @@ public class DomainBucket { private final Integer r; private final Integer rw; private final boolean returnBody; - private final int retries; private final Class clazz; + private final Retrier retrier; /** * @param bucket @@ -58,7 +59,7 @@ public class DomainBucket { */ public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter converter, MutationProducer mutationProducer, Integer w, Integer dw, Integer r, Integer rw, boolean returnBody, - int retries, Class clazz) { + Class clazz, final Retrier retrier) { this.bucket = bucket; this.resolver = resolver; this.converter = converter; @@ -68,8 +69,8 @@ public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter co this.r = r; this.rw = rw; this.returnBody = returnBody; - this.retries = retries; this.clazz = clazz; + this.retrier = retrier; } public T store(T o) throws RiakException { @@ -80,17 +81,17 @@ public T store(T o) throws RiakException { .withResolver(resolver) .w(w) .dw(dw) - .retry(retries) + .retrier(retrier) .returnBody(returnBody) .execute(); } public T fetch(String key) throws RiakException { - return bucket.fetch(key, clazz).withConverter(converter).withResolver(resolver).r(r).retry(retries).execute(); + return bucket.fetch(key, clazz).withConverter(converter).withResolver(resolver).r(r).retrier(retrier).execute(); } public T fetch(T o) throws RiakException { - return bucket.fetch(o).withConverter(converter).withResolver(resolver).r(r).retry(retries).execute(); + return bucket.fetch(o).withConverter(converter).withResolver(resolver).r(r).retrier(retrier).execute(); } public void delete(T o) throws RiakException { diff --git a/src/main/java/com/basho/riak/client/bucket/FetchBucket.java b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java index a09beec95..4617601fe 100644 --- a/src/main/java/com/basho/riak/client/bucket/FetchBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java @@ -13,12 +13,11 @@ */ package com.basho.riak.client.bucket; -import java.io.IOException; +import java.util.concurrent.Callable; import com.basho.riak.client.RiakRetryFailedException; -import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.operations.RiakOperation; -import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; /** @@ -30,29 +29,39 @@ public class FetchBucket implements RiakOperation { private final RawClient client; private final String bucket; - private int retry = 0; + private Retrier retrier; /** * @param client * @param bucket */ - public FetchBucket(RawClient client, String bucket) { + public FetchBucket(RawClient client, String bucket, final Retrier retrier) { this.client = client; this.bucket = bucket; + this.retrier = retrier; } + /** + * Execute the fetch operation using the RawClient + */ public Bucket execute() throws RiakRetryFailedException { - BucketProperties properties = new DefaultRetrier().attempt(new Command() { - public BucketProperties execute() throws IOException { + BucketProperties properties = retrier.attempt(new Callable() { + public BucketProperties call() throws Exception { return client.fetchBucket(bucket); } - }, retry); + }); - return new DefaultBucket(bucket, properties, client); + return new DefaultBucket(bucket, properties, client, retrier); } - public FetchBucket retry(int i) { - this.retry = i; + /** + * Provide a retrier to use for the fetch operation. + * + * @param retrier the Retrier to use + * @return this + */ + public FetchBucket retrier(final Retrier retrier) { + this.retrier = retrier; return this; } -} + } diff --git a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java index 857dba13a..88f1ff80d 100644 --- a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java @@ -13,17 +13,15 @@ */ package com.basho.riak.client.bucket; -import java.io.IOException; import java.util.Collection; +import java.util.concurrent.Callable; import com.basho.riak.client.RiakRetryFailedException; -import com.basho.riak.client.bucket.DefaultBucketProperties.Builder; -import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.query.functions.NamedFunction; -import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; /** @@ -33,19 +31,15 @@ public class WriteBucket implements RiakOperation { private final RawClient client; + private Retrier retrier; private String name; - private Builder builder = new Builder(); - private int retries = 0; + private DefaultBucketProperties.Builder builder = new DefaultBucketProperties.Builder(); - public WriteBucket(final RawClient client, Bucket b) { - this.name = b.getName(); - this.client = client; - } - - public WriteBucket(final RawClient client, String name) { + public WriteBucket(final RawClient client, String name, final Retrier retrier) { this.name = name; this.client = client; + this.retrier = retrier; } /* @@ -56,20 +50,20 @@ public WriteBucket(final RawClient client, String name) { public Bucket execute() throws RiakRetryFailedException { final BucketProperties propsToStore = builder.build(); - new DefaultRetrier().attempt(new Command() { - public Void execute() throws IOException { + retrier.attempt(new Callable() { + public Void call() throws Exception { client.updateBucket(name, propsToStore); return null; } - }, retries); + }); - BucketProperties properties = new DefaultRetrier().attempt(new Command() { - public BucketProperties execute() throws IOException { + BucketProperties properties = retrier.attempt(new Callable() { + public BucketProperties call() throws Exception { return client.fetchBucket(name); } - }, retries); + }); - return new DefaultBucket(name, properties, client); + return new DefaultBucket(name, properties, client, retrier); } public WriteBucket allowSiblings(boolean allowSiblings) { @@ -182,8 +176,15 @@ public WriteBucket dw(int dw) { return this; } - public WriteBucket retry(int n) { - this.retries = n; + /** + * Specify the retrier to use for this operation. + * If non-provided will use the client configured default. + * + * @param retrier a Retrier to use for the execute operation + * @return this + */ + public WriteBucket retrier(final Retrier retrier) { + this.retrier = retrier; return this; } diff --git a/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java index d1f5ad5c5..a1b1fb6aa 100644 --- a/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java @@ -18,8 +18,10 @@ import com.basho.riak.client.cap.ClobberMutation; import com.basho.riak.client.cap.ConflictResolver; import com.basho.riak.client.cap.DefaultResolver; +import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.cap.Mutation; import com.basho.riak.client.cap.MutationProducer; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.convert.Converter; import com.basho.riak.client.convert.JSONConverter; @@ -38,13 +40,13 @@ public class DomainBucketBuilder { private Converter converter; private Mutation mutation; private MutationProducer mutationProducer; + private Retrier retrier = DefaultRetrier.attempts(3); private Integer w; private Integer dw; private Integer r; private Integer rw; private boolean returnBody = false; - private int retries = 0; /** * @param bucket @@ -74,8 +76,8 @@ public Mutation produce(T o) { }; } - return new DomainBucket(bucket, resolver, converter, mutationProducer, w, dw, r, rw, returnBody, retries, - clazz); + return new DomainBucket(bucket, resolver, converter, mutationProducer, w, dw, r, rw, returnBody, clazz, + retrier); } /** @@ -100,8 +102,8 @@ public DomainBucketBuilder returnBody(boolean returnBody) { * @param i * @return */ - public DomainBucketBuilder retry(int times) { - this.retries = times; + public DomainBucketBuilder retrier(final Retrier retrier) { + this.retrier = retrier; return this; } diff --git a/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java index 7a4ef6327..11f3f16b3 100644 --- a/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java +++ b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java @@ -13,28 +13,58 @@ */ package com.basho.riak.client.cap; -import java.io.IOException; +import java.util.concurrent.Callable; import com.basho.riak.client.RiakRetryFailedException; -import com.basho.riak.client.raw.Command; /** - * @author russell + * A basic retrier implementation. Construct it with the number of times a + * {@link Callable} should be attempted. When attempt is called + * with a {@link Callable} then {@link Callable#call()} is run + * attempts times before throwing a + * {@link RiakRetryFailedException}. It is important to note that there is no + * backoff between attempts. * + * @author russell */ public class DefaultRetrier implements Retrier { - /* - * (non-Javadoc) - * - * @see - * com.basho.riak.client.spi.Retrier#attempt(com.basho.riak.client.spi.Command - * ) + private final int attempts; + + /** + * @param attempts + * how many times the retrier should attempt the call before + * throwing a {@link RiakRetryFailedException} + */ + public DefaultRetrier(int attempts) { + this.attempts = attempts; + } + + /* (non-Javadoc) + * @see com.basho.riak.client.cap.Retrier#attempt(java.util.concurrent.Callable) */ - public T attempt(Command command, int times) throws RiakRetryFailedException { + public T attempt(Callable command) throws RiakRetryFailedException { + return attempt(command, attempts); + } + + /** + * Calls {@link Callable#call()} times before giving up and + * throwing a {@link RiakRetryFailedException} There is no back off. + * + * @param + * the {@link Callable}'s return type. + * @param command + * the {@link Callable} to attempt + * @param times + * how many times to try before we throw + * @return the result of command + * @throws RiakRetryFailedException + * if the Callable throws an exception times times + */ + public static T attempt(final Callable command, int times) throws RiakRetryFailedException { try { - return command.execute(); - } catch (IOException e) { + return command.call(); + } catch (Exception e) { if (times == 0) { throw new RiakRetryFailedException(e); } else { @@ -43,4 +73,17 @@ public T attempt(Command command, int times) throws RiakRetryFailedExcept } } + /** + * Static factory method to create a default retrier + * + * @param attempts + * how many times the {@link DefaultRetrier} will attempt to call + * a {@link Callable} supplied to + * {@link Retrier#attempt(Callable)} + * @return a {@link DefaultRetrier} configured for attempts + * retries + */ + public static Retrier attempts(int attempts) { + return new DefaultRetrier(attempts); + } } diff --git a/src/main/java/com/basho/riak/client/cap/Retrier.java b/src/main/java/com/basho/riak/client/cap/Retrier.java index 313585797..a3a66fafc 100644 --- a/src/main/java/com/basho/riak/client/cap/Retrier.java +++ b/src/main/java/com/basho/riak/client/cap/Retrier.java @@ -13,13 +13,14 @@ */ package com.basho.riak.client.cap; +import java.util.concurrent.Callable; + import com.basho.riak.client.RiakRetryFailedException; -import com.basho.riak.client.raw.Command; /** * @author russell * */ public interface Retrier { - T attempt(Command command, int times) throws RiakRetryFailedException; + T attempt(Callable command) throws RiakRetryFailedException; } diff --git a/src/main/java/com/basho/riak/client/operations/DeleteObject.java b/src/main/java/com/basho/riak/client/operations/DeleteObject.java index d864d3830..f58ecd462 100644 --- a/src/main/java/com/basho/riak/client/operations/DeleteObject.java +++ b/src/main/java/com/basho/riak/client/operations/DeleteObject.java @@ -13,11 +13,10 @@ */ package com.basho.riak.client.operations; -import java.io.IOException; +import java.util.concurrent.Callable; import com.basho.riak.client.RiakRetryFailedException; -import com.basho.riak.client.cap.DefaultRetrier; -import com.basho.riak.client.raw.Command; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.raw.RawClient; /** @@ -30,18 +29,20 @@ public class DeleteObject implements RiakOperation { private final String bucket; private final String key; + private Retrier retrier; + private Integer rw; - private int retries = 0; /** * @param client * @param bucket * @param key */ - public DeleteObject(RawClient client, String bucket, String key) { + public DeleteObject(RawClient client, String bucket, String key, final Retrier retrier) { this.client = client; this.bucket = bucket; this.key = key; + this.retrier = retrier; } /* @@ -50,8 +51,8 @@ public DeleteObject(RawClient client, String bucket, String key) { * @see com.basho.riak.client.RiakOperation#execute() */ public Void execute() throws RiakRetryFailedException { - Command command = new Command() { - public Void execute() throws IOException { + Callable command = new Callable() { + public Void call() throws Exception { if (rw == null) { client.delete(bucket, key); } else { @@ -61,7 +62,7 @@ public Void execute() throws IOException { } }; - new DefaultRetrier().attempt(command, retries); + retrier.attempt(command); return null; } @@ -70,9 +71,8 @@ public DeleteObject rw(Integer rw) { return this; } - public DeleteObject retry(int times) { - this.retries = times; + public DeleteObject retrier(final Retrier retrier) { + this.retrier = retrier; return this; } - } diff --git a/src/main/java/com/basho/riak/client/operations/FetchObject.java b/src/main/java/com/basho/riak/client/operations/FetchObject.java index 43f749349..c8a9495d3 100644 --- a/src/main/java/com/basho/riak/client/operations/FetchObject.java +++ b/src/main/java/com/basho/riak/client/operations/FetchObject.java @@ -13,18 +13,17 @@ */ package com.basho.riak.client.operations; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.concurrent.Callable; import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakRetryFailedException; import com.basho.riak.client.cap.ConflictResolver; -import com.basho.riak.client.cap.DefaultRetrier; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.cap.UnresolvedConflictException; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.convert.Converter; -import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; @@ -38,7 +37,7 @@ public class FetchObject implements RiakOperation { private final RawClient client; private final String key; - private int retries = 0; + private Retrier retrier; private Integer r; private ConflictResolver resolver; @@ -48,10 +47,11 @@ public class FetchObject implements RiakOperation { * @param bucket * @param client */ - public FetchObject(final RawClient client, final String bucket, final String key) { + public FetchObject(final RawClient client, final String bucket, final String key, final Retrier retrier) { this.bucket = bucket; this.client = client; this.key = key; + this.retrier = retrier; } /* @@ -61,8 +61,8 @@ public FetchObject(final RawClient client, final String bucket, final String key */ public T execute() throws UnresolvedConflictException, RiakRetryFailedException, ConversionException { // fetch, resolve - Command command = new Command() { - public RiakResponse execute() throws IOException { + Callable command = new Callable() { + public RiakResponse call() throws Exception { if (r != null) { return client.fetch(bucket, key, r); } else { @@ -71,7 +71,7 @@ public RiakResponse execute() throws IOException { } }; - final RiakResponse ros = new DefaultRetrier().attempt(command, retries); + final RiakResponse ros = retrier.attempt(command); final Collection siblings = new ArrayList(ros.numberOfValues()); for (IRiakObject o : ros) { @@ -96,8 +96,8 @@ public FetchObject withConverter(Converter converter) { return this; } - public FetchObject retry(int times) { - this.retries = times; + public FetchObject retrier(final Retrier retrier) { + this.retrier = retrier; return this; } } diff --git a/src/main/java/com/basho/riak/client/operations/StoreObject.java b/src/main/java/com/basho/riak/client/operations/StoreObject.java index 11aeb6766..038bb3706 100644 --- a/src/main/java/com/basho/riak/client/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/client/operations/StoreObject.java @@ -13,20 +13,19 @@ */ package com.basho.riak.client.operations; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.concurrent.Callable; import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakException; import com.basho.riak.client.RiakRetryFailedException; import com.basho.riak.client.cap.ConflictResolver; -import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.cap.Mutation; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.cap.UnresolvedConflictException; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.convert.Converter; -import com.basho.riak.client.raw.Command; import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; @@ -44,23 +43,25 @@ public class StoreObject implements RiakOperation { private final RawClient client; private final String bucket; + private Retrier retrier; + // TODO populate private Integer r; private Integer w; private Integer dw; private boolean returnBody = false; - private int retries = 0; private Mutation mutation; private ConflictResolver resolver; private Converter converter; private final String key; - public StoreObject(final RawClient client, String bucket, String key) { + public StoreObject(final RawClient client, String bucket, String key, final Retrier retrier) { this.client = client; this.bucket = bucket; this.key = key; + this.retrier = retrier; } /** @@ -69,8 +70,8 @@ public StoreObject(final RawClient client, String bucket, String key) { */ public T execute() throws RiakRetryFailedException, UnresolvedConflictException, ConversionException { // fetch, mutate, put - Command command = new Command() { - public RiakResponse execute() throws IOException { + Callable command = new Callable() { + public RiakResponse call() throws Exception { if (r != null) { return client.fetch(bucket, key, r); } else { @@ -79,7 +80,7 @@ public RiakResponse execute() throws IOException { } }; - final RiakResponse ros = new DefaultRetrier().attempt(command, retries); + final RiakResponse ros = retrier.attempt(command); final Collection siblings = new ArrayList(ros.numberOfValues()); for (IRiakObject o : ros) { @@ -90,11 +91,11 @@ public RiakResponse execute() throws IOException { final T mutated = mutation.apply(resolved); final IRiakObject o = converter.fromDomain(mutated, ros.getVclock()); - final RiakResponse stored = new DefaultRetrier().attempt(new Command() { - public RiakResponse execute() throws IOException { + final RiakResponse stored = retrier.attempt(new Callable() { + public RiakResponse call() throws Exception { return client.store(o, generateStoreMeta()); } - }, retries); + }); final Collection storedSiblings = new ArrayList(stored.numberOfValues()); @@ -127,8 +128,8 @@ public StoreObject returnBody(boolean returnBody) { return this; } - public StoreObject retry(int times) { - this.retries = times; + public StoreObject retrier(final Retrier retrier) { + this.retrier = retrier; return this; } diff --git a/src/main/java/com/basho/riak/client/raw/Command.java b/src/main/java/com/basho/riak/client/raw/Command.java deleted file mode 100644 index 9e6c877d5..000000000 --- a/src/main/java/com/basho/riak/client/raw/Command.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is provided 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.basho.riak.client.raw; - -import java.io.IOException; - -/** - * @author russell - * - */ -public interface Command { - - T execute() throws IOException; - -} diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index 97cd75d51..9fe1cdbe7 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -39,6 +39,7 @@ import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakException; import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.cap.UnresolvedConflictException; import com.basho.riak.client.convert.NoKeySpecifedException; import com.megacorp.commerce.LegacyCart; @@ -143,7 +144,7 @@ public Boolean call() throws RiakException { cart.addItem("fixie"); cart.addItem("moleskine"); - carts.store(cart).returnBody(false).retry(3).execute(); + carts.store(cart).returnBody(false).retrier(DefaultRetrier.attempts(2)).execute(); final ShoppingCart fetchedCart = carts.fetch(cart).execute(); @@ -172,16 +173,16 @@ public Boolean call() throws RiakException { cart.addItem("moleskine"); try { - carts.store(cart).returnBody(false).retry(3).execute(); + carts.store(cart).returnBody(false).retrier(new DefaultRetrier(3)).execute(); fail("Expected NoKeySpecifiedException"); } catch (NoKeySpecifedException e) { // NO-OP } - carts.store(userId, cart).returnBody(false).retry(3).execute(); + carts.store(userId, cart).returnBody(false).execute(); try { - carts.fetch(cart).retry(3).execute(); + carts.fetch(cart).execute(); fail("Expected NoKeySpecifiedException"); } catch (NoKeySpecifedException e) { // NO-OP @@ -194,7 +195,7 @@ public Boolean call() throws RiakException { assertEquals(cart, fetchedCart); try { - carts.delete(cart).retry(3).execute(); + carts.delete(cart).execute(); fail("Expected NoKeySpecifiedException"); } catch (NoKeySpecifedException e) { // NO-OP diff --git a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java index 99f37fecb..2774b54cc 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java @@ -32,6 +32,7 @@ import com.basho.riak.client.RiakException; import com.basho.riak.client.bucket.Bucket; import com.basho.riak.client.bucket.DomainBucket; +import com.basho.riak.client.cap.DefaultRetrier; import com.megacorp.commerce.MergeCartResolver; import com.megacorp.commerce.ShoppingCart; @@ -60,7 +61,15 @@ public abstract class ITestDomainBucket { final Bucket b = client.createBucket(bucketName).allowSiblings(true).nVal(3).execute(); - final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class).withResolver(new MergeCartResolver()).returnBody(true).retry(3).w(1).dw(1).r(1).rw(1).build(); + final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class) + .withResolver(new MergeCartResolver()) + .returnBody(true) + .retrier(DefaultRetrier.attempts(3)) + .w(1) + .dw(1) + .r(1) + .rw(1) + .build(); final ShoppingCart cart = new ShoppingCart(userId); From cb2a5c67f042858d72933c789c9d920035aebbd9 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Thu, 5 May 2011 12:25:02 +0100 Subject: [PATCH 026/764] Add read quorum parameter to StoreOperation (for fetch before store) --- .../riak/client/bucket/DomainBucket.java | 3 ++- .../riak/client/operations/StoreObject.java | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java index b7d4d6ec6..acca8e41b 100644 --- a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java @@ -24,7 +24,7 @@ /** * A domain bucket is a wrapper around a bucket that is strongly typed uses a - * preset resolver, mutation producer, converter, r, w, dw, rw, retries, + * preset resolver, mutation producer, converter, r, w, dw, rw, retrier, * returnBody etc * * @author russell @@ -79,6 +79,7 @@ public T store(T o) throws RiakException { .withConverter(converter) .withMutator(mutation) .withResolver(resolver) + .r(r) .w(w) .dw(dw) .retrier(retrier) diff --git a/src/main/java/com/basho/riak/client/operations/StoreObject.java b/src/main/java/com/basho/riak/client/operations/StoreObject.java index 038bb3706..8019fe265 100644 --- a/src/main/java/com/basho/riak/client/operations/StoreObject.java +++ b/src/main/java/com/basho/riak/client/operations/StoreObject.java @@ -33,8 +33,7 @@ /** * Stores a given object into riak. Fetches first. * - * @TODO figure out if you *should* fetch first, and if you should, what about - * R? + * @TODO Should fetch first be optional? What about the vclock if not? * @author russell * */ @@ -42,10 +41,9 @@ public class StoreObject implements RiakOperation { private final RawClient client; private final String bucket; + private final String key; private Retrier retrier; - - // TODO populate private Integer r; private Integer w; private Integer dw; @@ -55,8 +53,14 @@ public class StoreObject implements RiakOperation { private ConflictResolver resolver; private Converter converter; - private final String key; - + /** + * Create a new StoreObject operation for the object in bucket at key. + * + * @param client the RawClient to use + * @param bucket + * @param key + * @param retrier the Retrier to use for this operation + */ public StoreObject(final RawClient client, String bucket, String key, final Retrier retrier) { this.client = client; this.bucket = bucket; @@ -113,6 +117,17 @@ private StoreMeta generateStoreMeta() { return new StoreMeta(w, dw, returnBody); } + /** + * A store performs a fetch first (to get a vclock and resolve any conflicts) + * + * @param r the read quorum for the pre-store fetch + * @return this + */ + public StoreObject r(Integer r) { + this.r = r; + return this; + } + public StoreObject w(Integer w) { this.w = w; return this; From e21919448f9a619c9dd020bbc8e61ba10e2b6ab7 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 6 May 2011 16:50:03 +0100 Subject: [PATCH 027/764] Enforce correct characterset usage when going from byte[] to String And string to byte[]. Where a characterset is unkown, if the source was originally a String assume UTF-8, where bytes, use ISO-8859-1 so no changes occur in transposition. --- .../basho/riak/client/DefaultRiakObject.java | 32 +++- .../com/basho/riak/client/IRiakObject.java | 6 +- .../com/basho/riak/client/RiakObject.java | 8 +- .../com/basho/riak/client/bucket/Bucket.java | 14 ++ .../riak/client/bucket/DefaultBucket.java | 34 +++- .../basho/riak/client/bucket/RiakBucket.java | 2 +- .../client/builders/RiakObjectBuilder.java | 18 ++- .../basho/riak/client/cap/BasicVClock.java | 4 +- .../com/basho/riak/client/cap/ClientId.java | 3 +- .../basho/riak/client/cap/DefaultRetrier.java | 2 +- .../riak/client/convert/JSONConverter.java | 9 +- .../basho/riak/client/http/RiakObject.java | 10 +- .../http/response/DefaultHttpResponse.java | 5 +- .../riak/client/http/util/ClientHelper.java | 9 +- .../riak/client/http/util/ClientUtils.java | 3 +- .../riak/client/http/util/Constants.java | 2 + .../riak/client/http/util/Multipart.java | 10 +- .../client/http/util/OneTokenInputStream.java | 4 +- .../riak/client/raw/http/ConversionUtil.java | 7 +- .../client/raw/http/HTTPClientAdapter.java | 12 +- .../riak/client/raw/pbc/ConversionUtil.java | 16 +- .../riak/client/raw/pbc/PBClientAdapter.java | 5 +- .../client/response/DefaultHttpResponse.java | 5 +- .../basho/riak/client/util/CharsetUtils.java | 147 ++++++++++++++++++ .../basho/riak/client/util/ClientHelper.java | 2 +- .../basho/riak/client/util/ClientUtils.java | 2 +- .../com/basho/riak/client/util/Multipart.java | 9 +- .../riak/client/util/OneTokenInputStream.java | 2 +- .../java/com/basho/riak/pbc/RiakClient.java | 15 +- .../riak/client/http/TestRiakClient.java | 3 +- .../riak/client/http/TestRiakObject.java | 31 ++-- .../riak/client/http/itest/ITestBasic.java | 18 +-- .../riak/client/http/itest/ITestDataLoad.java | 5 +- .../client/http/itest/ITestStreaming.java | 3 +- .../riak/client/http/itest/ITestWalk.java | 5 +- .../basho/riak/client/http/itest/Utils.java | 3 +- .../http/response/TestBucketResponse.java | 11 +- .../http/response/TestFetchResponse.java | 11 +- .../response/TestHttpResponseDecorator.java | 3 +- .../response/TestStreamedKeysCollection.java | 13 +- .../http/response/TestWalkResponse.java | 7 +- .../http/util/TestBranchableInputStream.java | 7 +- .../client/http/util/TestClientHelper.java | 3 +- .../client/http/util/TestClientUtils.java | 7 +- .../http/util/TestCollectionWrapper.java | 3 +- .../riak/client/http/util/TestMultipart.java | 17 +- .../http/util/TestOneTokenInputStream.java | 9 +- .../http/util/TestStreamedMultipart.java | 9 +- .../basho/riak/client/itest/ITestBucket.java | 4 +- .../riak/client/itest/ITestClientBasic.java | 3 +- .../riak/client/itest/ITestLinkWalk.java | 5 +- .../com/basho/riak/pbc/TestRiakObject.java | 3 +- .../basho/riak/pbc/itest/ITestDataLoad.java | 6 +- 53 files changed, 438 insertions(+), 148 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/util/CharsetUtils.java diff --git a/src/main/java/com/basho/riak/client/DefaultRiakObject.java b/src/main/java/com/basho/riak/client/DefaultRiakObject.java index 268784ec5..0b9b53605 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakObject.java @@ -24,6 +24,7 @@ import com.basho.riak.client.cap.VClock; import com.basho.riak.client.convert.RiakKey; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.util.UnmodifiableIterator; /** @@ -50,7 +51,7 @@ public class DefaultRiakObject implements IRiakObject { private final Map userMeta; private volatile String contentType; - private volatile String value; + private volatile byte[] value; /** * Use the builder. @@ -68,7 +69,7 @@ public class DefaultRiakObject implements IRiakObject { * @param userMeta */ public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, - String contentType, String value, final Collection links, final Map userMeta) { + String contentType, byte[] value, final Collection links, final Map userMeta) { if (bucket == null) { throw new IllegalArgumentException("Bucket cannot be null"); @@ -84,11 +85,23 @@ public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, this.vtag = vtag; this.lastModified = lastModified == null ? 0 : lastModified.getTime(); safeSetContentType(contentType); - this.value = value; + this.value = copy(value); this.links = copy(links); this.userMeta = copy(userMeta); } + /** + * @param value + * @return + */ + private byte[] copy(byte[] value) { + if (value == null) { + return null; + } else { + return value.clone(); + } + } + private Map copy(Map userMeta) { Map copy; @@ -153,14 +166,14 @@ public Map getMeta() { return new HashMap(userMeta); } - public String getValue() { + public byte[] getValue() { return value; } // mutate - public void setValue(String value) { - this.value = value; + public void setValue(byte[] value) { + this.value = copy(value); } public void setContentType(String contentType) { @@ -327,4 +340,11 @@ public String getVClockAsString() { return null; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getValueAsString() + */ + public String getValueAsString() { + return CharsetUtils.asString(value, CharsetUtils.getCharset(contentType)); + } + } diff --git a/src/main/java/com/basho/riak/client/IRiakObject.java b/src/main/java/com/basho/riak/client/IRiakObject.java index 8bea1788e..fd47f73ce 100644 --- a/src/main/java/com/basho/riak/client/IRiakObject.java +++ b/src/main/java/com/basho/riak/client/IRiakObject.java @@ -35,7 +35,9 @@ public interface IRiakObject extends Iterable { String getBucket(); - String getValue(); + byte[] getValue(); + + String getValueAsString(); VClock getVClock(); @@ -69,7 +71,7 @@ public interface IRiakObject extends Iterable { // Mutate - void setValue(String value); + void setValue(byte[] value); void setContentType(String contentType); diff --git a/src/main/java/com/basho/riak/client/RiakObject.java b/src/main/java/com/basho/riak/client/RiakObject.java index 1827776e0..dd31a0efc 100644 --- a/src/main/java/com/basho/riak/client/RiakObject.java +++ b/src/main/java/com/basho/riak/client/RiakObject.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client; +import static com.basho.riak.client.util.CharsetUtils.*; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; @@ -57,6 +58,7 @@ @Deprecated public class RiakObject { + private static final byte[] EMPTY = new byte[] {}; private RiakClient riak; private String bucket; private String key; @@ -278,7 +280,7 @@ public String getKey() { * The object's value */ public String getValue() { - return (value == null ? null : new String(value)); + return (value == null ? null : asString(value, getCharset(contentType))); } public byte[] getValueAsBytes() { @@ -287,7 +289,7 @@ public byte[] getValueAsBytes() { public void setValue(String value) { if (value != null) { - this.value = value.getBytes(); + this.value = asBytes(value, getCharset(contentType)); } else { this.value = null; } @@ -764,7 +766,7 @@ public void writeToHttpMethod(HttpMethod httpMethod) { } else if (value != null) { entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity(value, contentType)); } else { - entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity("".getBytes(), contentType)); + entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity(EMPTY, contentType)); } } } diff --git a/src/main/java/com/basho/riak/client/bucket/Bucket.java b/src/main/java/com/basho/riak/client/bucket/Bucket.java index 2bca1ca83..5f8f6b5a9 100644 --- a/src/main/java/com/basho/riak/client/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/client/bucket/Bucket.java @@ -27,6 +27,20 @@ public interface Bucket extends BucketProperties { String getName(); + /** + * Convenience method to create a RiakObject with a payload of application/octect-stream + * @param key + * @param value + * @return + */ + StoreObject store(String key, byte[] value); + + /** + * Convenience methods will assume payload is taxt/plain:charset=utf-8 + * @param key + * @param value + * @return + */ StoreObject store(String key, String value); StoreObject store(T o); diff --git a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java index 69340f744..cada5e307 100644 --- a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java @@ -31,12 +31,14 @@ import com.basho.riak.client.convert.Converter; import com.basho.riak.client.convert.JSONConverter; import com.basho.riak.client.convert.NoKeySpecifedException; +import com.basho.riak.client.http.util.Constants; import com.basho.riak.client.operations.DeleteObject; import com.basho.riak.client.operations.FetchObject; import com.basho.riak.client.operations.StoreObject; import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.query.functions.NamedFunction; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.util.CharsetUtils; /** * @author russell @@ -234,13 +236,12 @@ public Iterable keys() throws RiakException { * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, * java.lang.String) */ - public StoreObject store(final String key, final String value) { - final Bucket b = this; + public StoreObject store(final String key, final byte[] value) { return new StoreObject(client, name, key, retrier).withMutator(new Mutation() { public IRiakObject apply(IRiakObject original) { if (original == null) { - return RiakObjectBuilder.newBuilder(b.getName(), key).withValue(value).build(); + return RiakObjectBuilder.newBuilder(name, key).withValue(value).withContentType(Constants.CTYPE_OCTET_STREAM).build(); } else { original.setValue(value); return original; @@ -258,6 +259,32 @@ public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws Co }); } + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, java.lang.String) + */ + public StoreObject store(final String key, final String value) { + return new StoreObject(client, name, key, retrier).withMutator(new Mutation() { + public IRiakObject apply(IRiakObject original) { + if (original == null) { + return RiakObjectBuilder.newBuilder(name, key).withValue(value).withContentType(Constants.CTYPE_TEXT_UTF8).build(); + } else { + original.setValue(CharsetUtils.utf8StringToBytes(value)); + original.setContentType(Constants.CTYPE_TEXT_UTF8); + return original; + } + } + }).withResolver(new DefaultResolver()).withConverter(new Converter() { + + public IRiakObject toDomain(IRiakObject riakObject) { + return riakObject; + } + + public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { + return domainObject; + } + }); + } + /* * (non-Javadoc) * @@ -360,5 +387,4 @@ public DeleteObject delete(T o) { public DeleteObject delete(String key) { return new DeleteObject(client, name, key, retrier); } - } diff --git a/src/main/java/com/basho/riak/client/bucket/RiakBucket.java b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java index 67e1d2931..3b0ffeb46 100644 --- a/src/main/java/com/basho/riak/client/bucket/RiakBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java @@ -70,7 +70,7 @@ public IRiakObject store(IRiakObject o) throws RiakException { * @return * @throws RiakException */ - public IRiakObject store(String key, String value) throws RiakException { + public IRiakObject store(String key, byte[] value) throws RiakException { return delegate.store(RiakObjectBuilder.newBuilder(bucket.getName(), key).withValue(value).build()); } /** diff --git a/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java b/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java index 3bbc919c3..0fdb5c962 100644 --- a/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/RiakObjectBuilder.java @@ -13,6 +13,8 @@ */ package com.basho.riak.client.builders; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; + import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -24,6 +26,7 @@ import com.basho.riak.client.RiakLink; import com.basho.riak.client.cap.BasicVClock; import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.util.CharsetUtils; /** * @author russell @@ -32,7 +35,7 @@ public class RiakObjectBuilder { private final String bucket; private final String key; - private String value; + private byte[] value; private VClock vclock; private String vtag; private Date lastModified; @@ -64,8 +67,19 @@ public IRiakObject build() { return new DefaultRiakObject(bucket, key, vclock, vtag, lastModified, contentType, value, links, userMeta); } + public RiakObjectBuilder withValue(byte[] value) { + this.value = value==null? null : value.clone(); + return this; + } + + /** + * Convenience method assumes a UTF-8 encoded string + * @param value a UTF-8 encoded string + * @return this + */ public RiakObjectBuilder withValue(String value) { - this.value = value; + this.value = utf8StringToBytes(value); + this.contentType = CharsetUtils.addUtf8Charset(contentType); return this; } diff --git a/src/main/java/com/basho/riak/client/cap/BasicVClock.java b/src/main/java/com/basho/riak/client/cap/BasicVClock.java index 2a70dedee..d13e86669 100644 --- a/src/main/java/com/basho/riak/client/cap/BasicVClock.java +++ b/src/main/java/com/basho/riak/client/cap/BasicVClock.java @@ -13,6 +13,8 @@ */ package com.basho.riak.client.cap; +import com.basho.riak.client.util.CharsetUtils; + /** * @author russell * @@ -33,6 +35,6 @@ public byte[] getBytes() { } public String asString() { - return new String(value); + return CharsetUtils.asUTF8String(value); } } diff --git a/src/main/java/com/basho/riak/client/cap/ClientId.java b/src/main/java/com/basho/riak/client/cap/ClientId.java index e223ea218..3f2bdd51a 100644 --- a/src/main/java/com/basho/riak/client/cap/ClientId.java +++ b/src/main/java/com/basho/riak/client/cap/ClientId.java @@ -15,7 +15,6 @@ import java.security.SecureRandom; -import org.apache.commons.codec.binary.Base64; /** * @author russell @@ -31,6 +30,6 @@ public class ClientId { public static byte[] generate() { byte[] bytes = new byte[4]; rnd.nextBytes(bytes); - return new Base64().encode(bytes); + return bytes; } } diff --git a/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java index 11f3f16b3..162d4db6e 100644 --- a/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java +++ b/src/main/java/com/basho/riak/client/cap/DefaultRetrier.java @@ -68,7 +68,7 @@ public static T attempt(final Callable command, int times) throws RiakRet if (times == 0) { throw new RiakRetryFailedException(e); } else { - return attempt(command, times--); + return attempt(command, --times); } } } diff --git a/src/main/java/com/basho/riak/client/convert/JSONConverter.java b/src/main/java/com/basho/riak/client/convert/JSONConverter.java index 266c60f4d..b082bba0a 100644 --- a/src/main/java/com/basho/riak/client/convert/JSONConverter.java +++ b/src/main/java/com/basho/riak/client/convert/JSONConverter.java @@ -14,6 +14,7 @@ package com.basho.riak.client.convert; import static com.basho.riak.client.convert.KeyUtil.getKey; +import static com.basho.riak.client.util.CharsetUtils.*; import java.io.IOException; import java.io.StringWriter; @@ -24,6 +25,7 @@ import com.basho.riak.client.IRiakObject; import com.basho.riak.client.builders.RiakObjectBuilder; import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.http.util.Constants; /** * Converts a RiakObject's value to an instance of T. T must have a field @@ -70,8 +72,8 @@ public IRiakObject fromDomain(T domainObject, VClock vclock) throws ConversionEx final StringWriter sw = new StringWriter(); objectMapper.writeValue(sw, domainObject); - - return RiakObjectBuilder.newBuilder(bucket, key).withValue(sw.toString()).withVClock(vclock).build(); + return RiakObjectBuilder.newBuilder(bucket, key).withValue(utf8StringToBytes(sw.toString())).withVClock(vclock). + withContentType(Constants.CTYPE_JSON_UTF8).build(); } catch (JsonProcessingException e) { throw new ConversionException(e); } catch (IOException e) { @@ -92,7 +94,7 @@ public T toDomain(IRiakObject riakObject) throws ConversionException { return null; } - String json = riakObject.getValue(); + String json = asString(riakObject.getValue(), getCharset(riakObject.getContentType())); try { T domainObject = objectMapper.readValue(json, clazz); @@ -103,5 +105,4 @@ public T toDomain(IRiakObject riakObject) throws ConversionException { throw new ConversionException(e); } } - } diff --git a/src/main/java/com/basho/riak/client/http/RiakObject.java b/src/main/java/com/basho/riak/client/http/RiakObject.java index 618632b0b..ca92b0949 100644 --- a/src/main/java/com/basho/riak/client/http/RiakObject.java +++ b/src/main/java/com/basho/riak/client/http/RiakObject.java @@ -13,6 +13,8 @@ */ package com.basho.riak.client.http; +import static com.basho.riak.client.util.CharsetUtils.*; + import java.io.InputStream; import java.util.ArrayList; import java.util.Date; @@ -45,6 +47,8 @@ */ public class RiakObject { + private static final byte[] EMPTY = new byte[] {}; + private RiakClient riak; private String bucket; private String key; @@ -254,7 +258,7 @@ public String getKey() { * @see com.basho.riak.client.HttpRiakObject#getValue() */ public String getValue() { - return (value == null ? null : new String(value)); + return (value == null ? null : asString(value, getCharset(contentType))); } /* (non-Javadoc) @@ -269,7 +273,7 @@ public byte[] getValueAsBytes() { */ public void setValue(String value) { if (value != null) { - this.value = value.getBytes(); + this.value = asBytes(value, getCharset(contentType)); } else { this.value = null; } @@ -692,7 +696,7 @@ public void writeToHttpMethod(HttpMethod httpMethod) { } else if (value != null) { entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity(value, contentType)); } else { - entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity("".getBytes(), contentType)); + entityEnclosingMethod.setRequestEntity(new ByteArrayRequestEntity(EMPTY, contentType)); } } } diff --git a/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java b/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java index a89b7e81c..e2d0f7851 100644 --- a/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java +++ b/src/main/java/com/basho/riak/client/http/response/DefaultHttpResponse.java @@ -13,6 +13,9 @@ */ package com.basho.riak.client.http.response; +import static com.basho.riak.client.util.CharsetUtils.asString; +import static com.basho.riak.client.util.CharsetUtils.getCharset; + import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -79,7 +82,7 @@ public String getBodyAsString() { if (body == null) { return null; } - return new String(body); + return asString(body, getCharset(headers)); } public InputStream getStream() { diff --git a/src/main/java/com/basho/riak/client/http/util/ClientHelper.java b/src/main/java/com/basho/riak/client/http/util/ClientHelper.java index 404d68792..29a068f6d 100644 --- a/src/main/java/com/basho/riak/client/http/util/ClientHelper.java +++ b/src/main/java/com/basho/riak/client/http/util/ClientHelper.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -69,11 +70,7 @@ void setHttpClient(HttpClient httpClient) { * See {@link RiakClient#getClientId()} */ public byte[] getClientId() { - try { - return Base64.decodeBase64(clientId.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("UTF-8 support required in JVM"); - } + return Base64.decodeBase64(utf8StringToBytes(clientId)); } public void setClientId(String clientId) { @@ -99,7 +96,7 @@ public HttpResponse setBucketSchema(String bucket, JSONObject schema, RequestMet meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_JSON); PutMethod put = new PutMethod(ClientUtils.makeURI(config, bucket)); - put.setRequestEntity(new ByteArrayRequestEntity(schema.toString().getBytes(), Constants.CTYPE_JSON)); + put.setRequestEntity(new ByteArrayRequestEntity(utf8StringToBytes(schema.toString()), Constants.CTYPE_JSON)); return executeMethod(bucket, null, put, meta); } diff --git a/src/main/java/com/basho/riak/client/http/util/ClientUtils.java b/src/main/java/com/basho/riak/client/http/util/ClientUtils.java index 98749a9d8..b3beffa51 100644 --- a/src/main/java/com/basho/riak/client/http/util/ClientUtils.java +++ b/src/main/java/com/basho/riak/client/http/util/ClientUtils.java @@ -44,6 +44,7 @@ import com.basho.riak.client.http.RiakLink; import com.basho.riak.client.http.RiakObject; import com.basho.riak.client.http.response.RiakExceptionHandler; +import com.basho.riak.client.util.CharsetUtils; /** * Utility functions. @@ -196,7 +197,7 @@ public static String encodeClientId(byte[] clientId) { } public static String encodeClientId(String clientId) { - return encodeClientId(clientId.getBytes()); + return encodeClientId(CharsetUtils.asBytes(clientId, CharsetUtils.ISO_8859_1)); } /** diff --git a/src/main/java/com/basho/riak/client/http/util/Constants.java b/src/main/java/com/basho/riak/client/http/util/Constants.java index d6bd729d0..67ea692c7 100644 --- a/src/main/java/com/basho/riak/client/http/util/Constants.java +++ b/src/main/java/com/basho/riak/client/http/util/Constants.java @@ -59,9 +59,11 @@ public interface Constants { // Content types used in Riak public static String CTYPE_ANY = "*/*"; public static String CTYPE_JSON = "application/json"; + public static String CTYPE_JSON_UTF8 = "application/json;charset=UTF-8"; public static String CTYPE_OCTET_STREAM = "application/octet-stream"; public static String CTYPE_MULTIPART_MIXED = "multipart/mixed"; public static String CTYPE_TEXT = "text/plain"; + public static String CTYPE_TEXT_UTF8 = "text/plain;charset=UTF-8"; // Default r, w, and dw values to use when not specified public static Integer DEFAULT_R = 2; diff --git a/src/main/java/com/basho/riak/client/http/util/Multipart.java b/src/main/java/com/basho/riak/client/http/util/Multipart.java index 80c0879cd..676ec74cf 100644 --- a/src/main/java/com/basho/riak/client/http/util/Multipart.java +++ b/src/main/java/com/basho/riak/client/http/util/Multipart.java @@ -13,8 +13,12 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; + import org.apache.commons.httpclient.util.EncodingUtil; +import com.basho.riak.client.util.CharsetUtils; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -28,7 +32,7 @@ */ public class Multipart { - private static byte[] HEADER_DELIM = "\r\n\r\n".getBytes(); + private static byte[] HEADER_DELIM = CharsetUtils.utf8StringToBytes("\r\n\r\n"); private static int indexOf(byte[] text, byte[] pattern, int fromIndex) { if (fromIndex >= text.length || fromIndex < 0) { @@ -85,7 +89,7 @@ public static List parse(Map headers, byte[] bod } String boundary = "\r\n--" + getBoundary(headers.get(Constants.HDR_CONTENT_TYPE)); - byte[] boundaryBytes = boundary.getBytes(); + byte[] boundaryBytes = CharsetUtils.utf8StringToBytes(boundary); int boundarySize = boundary.length(); if ("\r\n--".equals(boundary)) return null; @@ -241,7 +245,7 @@ public String getBodyAsString() { byte[] body = getBody(); if (body == null) return null; - return new String(body); + return CharsetUtils.asString(body, CharsetUtils.getCharset(headers)); } public InputStream getStream() { diff --git a/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java b/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java index 452b3944a..571bbfd5c 100644 --- a/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java +++ b/src/main/java/com/basho/riak/client/http/util/OneTokenInputStream.java @@ -3,6 +3,8 @@ import java.io.IOException; import java.io.InputStream; +import com.basho.riak.client.util.CharsetUtils; + /** * A wrapper that reads a single element an underlying {@link InputStream} * containing contains a delimited list @@ -87,6 +89,6 @@ private void initBuffer() throws IOException { offset += bytesRead; } } - buf = new StringBuilder(new String(headStart)); + buf = new StringBuilder(CharsetUtils.asString(headStart, CharsetUtils.ISO_8859_1)); } } diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index 80f68937c..0be1e6de2 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -42,6 +42,7 @@ import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.raw.StoreMeta; import com.basho.riak.client.raw.query.LinkWalkSpec; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.util.UnmodifiableIterator; import com.basho.riak.client.http.request.RequestMeta; import com.basho.riak.client.http.request.RiakWalkSpec; @@ -78,7 +79,7 @@ static IRiakObject convert(final com.basho.riak.client.http.RiakObject o) { RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); - builder.withValue(o.getValue()); + builder.withValue(o.getValueAsBytes()); builder.withVClock(nullSafeGetBytes(o.getVclock())); builder.withVtag(o.getVtag()); @@ -122,7 +123,7 @@ static RiakLink convert(com.basho.riak.client.http.RiakLink link) { * @return */ static byte[] nullSafeGetBytes(String vclock) { - return vclock == null ? null : vclock.getBytes(); + return vclock == null ? null : CharsetUtils.utf8StringToBytes(vclock); } /** @@ -150,7 +151,7 @@ static com.basho.riak.client.http.RiakObject convert(IRiakObject object, final R client, object.getBucket(), object.getKey(), - nullSafeGetBytes(object.getValue()), + object.getValue(), object.getContentType(), getLinks(object), getUserMetaData(object), diff --git a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java index 8ed3bfead..43176a20d 100644 --- a/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/http/HTTPClientAdapter.java @@ -22,6 +22,7 @@ import com.basho.riak.client.bucket.BucketProperties; import com.basho.riak.client.cap.ClientId; import com.basho.riak.client.http.RiakClient; +import com.basho.riak.client.http.RiakObject; import com.basho.riak.client.query.MapReduceResult; import com.basho.riak.client.query.WalkResult; import com.basho.riak.client.raw.RawClient; @@ -30,6 +31,7 @@ import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.http.request.RequestMeta; import com.basho.riak.client.http.response.BucketResponse; import com.basho.riak.client.http.response.FetchResponse; @@ -124,8 +126,10 @@ private RiakResponse handleBodyResponse(WithBodyResponse resp) { values = new IRiakObject[] { convert(resp.getObject()) }; } + // we have at least an object, get a vclock for the response if (values.length > 0) { - response = new RiakResponse(resp.getObject().getVclock().getBytes(), values); + final RiakObject obj = resp.getObject(); + response = new RiakResponse(CharsetUtils.utf8StringToBytes(obj.getVclock()), values); } return response; @@ -282,9 +286,7 @@ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapRedu * @see com.basho.riak.client.raw.RawClient#generateAndSetClientId() */ public byte[] generateAndSetClientId() throws IOException { - byte[] clientId = ClientId.generate(); - - client.setClientId(new String(clientId)); + setClientId(ClientId.generate()); return client.getClientId(); } @@ -297,7 +299,7 @@ public void setClientId(byte[] clientId) throws IOException { if (clientId == null || clientId.length != 4) { throw new IllegalArgumentException("clientId must be 4 bytes. generateAndSetClientId() can do this for you"); } - client.setClientId(new String(clientId)); + client.setClientId(CharsetUtils.asString(clientId, CharsetUtils.ISO_8859_1)); } /* diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index df2b1710d..7dddbd023 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.raw.pbc; +import static com.basho.riak.client.util.CharsetUtils.*; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -41,6 +42,7 @@ import com.basho.riak.client.query.LinkWalkStep.Accumulate; import com.basho.riak.client.raw.RiakResponse; import com.basho.riak.client.raw.StoreMeta; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.util.UnmodifiableIterator; import com.basho.riak.pbc.MapReduceResponseSource; import com.basho.riak.pbc.RequestMeta; @@ -77,7 +79,7 @@ static RiakResponse convert(com.basho.riak.pbc.RiakObject[] pbcObjects) { static IRiakObject convert(com.basho.riak.pbc.RiakObject o) { RiakObjectBuilder builder = RiakObjectBuilder.newBuilder(o.getBucket(), o.getKey()); - builder.withValue(nullSafeToStringUtf8(o.getValue())); + builder.withValue(nullSafeToBytes(o.getValue())); builder.withVClock(nullSafeToBytes(o.getVclock())); builder.withVtag(o.getVtag()); @@ -147,7 +149,7 @@ static com.basho.riak.pbc.RiakObject convert(IRiakObject riakObject) { final VClock vc = riakObject.getVClock(); ByteString bucketName = nullSafeToByteString(riakObject.getBucket()); ByteString key = nullSafeToByteString(riakObject.getKey()); - ByteString content = nullSafeToByteString(riakObject.getValue()); + ByteString content = ByteString.copyFrom(riakObject.getValue()); ByteString vclock = null; if (vc != null) { @@ -340,7 +342,8 @@ public Iterator> iterator() { */ @SuppressWarnings({ "rawtypes", "unchecked" }) private static IRiakObject mapToRiakObject(Map data) { RiakObjectBuilder b = RiakObjectBuilder.newBuilder((String) data.get("bucket"), (String) data.get("key")); - b.withVClock(((String) data.get("vclock")).getBytes()); + String vclock = (String) data.get("vclock"); + b.withVClock(CharsetUtils.utf8StringToBytes(vclock)); final List values = (List) data.get("values"); // TODO figure out what to do about multiple values here, @@ -348,10 +351,11 @@ public Iterator> iterator() { // does) if (values.size() != 0) { final Map value = (Map) values.get(0); - - b.withValue((String) value.get("data")); final Map meta = (Map) value.get("metadata"); - b.withContentType((String) meta.get("content-type")); + final String contentType = (String) meta.get("content-type"); + + b.withValue(asBytes((String) value.get("data"), getCharset(contentType))); + b.withContentType(contentType); b.withVtag((String) meta.get("X-Riak-VTag")); try { diff --git a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java index ac323b606..22db23003 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/PBClientAdapter.java @@ -37,6 +37,7 @@ import com.basho.riak.client.raw.query.LinkWalkSpec; import com.basho.riak.client.raw.query.MapReduceSpec; import com.basho.riak.client.raw.query.MapReduceTimeoutException; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.bucket.BucketProperties; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.http.util.Constants; @@ -335,7 +336,7 @@ public MapReduceResult mapReduce(MapReduceSpec spec) throws IOException, MapRedu */ public byte[] generateAndSetClientId() throws IOException { client.prepareClientID(); - return client.getClientID().getBytes(); + return CharsetUtils.utf8StringToBytes(client.getClientID()); } /* @@ -359,7 +360,7 @@ public byte[] getClientId() throws IOException { final String clientId = client.getClientID(); if (clientId != null) { - return clientId.getBytes(); + return CharsetUtils.utf8StringToBytes(clientId); } else { throw new IOException("null clientId returned by client"); } diff --git a/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java b/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java index c97516820..7f240efd6 100644 --- a/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java +++ b/src/main/java/com/basho/riak/client/response/DefaultHttpResponse.java @@ -13,6 +13,9 @@ */ package com.basho.riak.client.response; +import static com.basho.riak.client.util.CharsetUtils.asString; +import static com.basho.riak.client.util.CharsetUtils.getCharset; + import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -88,7 +91,7 @@ public String getBodyAsString() { if (body == null) { return null; } - return new String(body); + return asString(body, getCharset(headers)); } public InputStream getStream() { diff --git a/src/main/java/com/basho/riak/client/util/CharsetUtils.java b/src/main/java/com/basho/riak/client/util/CharsetUtils.java new file mode 100644 index 000000000..790d2260a --- /dev/null +++ b/src/main/java/com/basho/riak/client/util/CharsetUtils.java @@ -0,0 +1,147 @@ +/* + * This file is provided 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.basho.riak.client.util; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utils for dealing with byte[], String charset issues, especially since Java 5 + * is less cool than Java 6 in this respect. + * + * This code is all from the Trifork fork of the client and was written by + * Krestan Krab, Christian Hvitved and Erik Søe Sørensen. + * + * @author russell + * + */ +public class CharsetUtils { + public static Charset ASCII = Charset.forName("ASCII"); + public static Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + public static Charset UTF_8 = Charset.forName("UTF-8"); + + public static Charset getCharset(Map headers) { + return getCharset(headers.get(com.basho.riak.client.http.util.Constants.HDR_CONTENT_TYPE)); + } + + static Pattern CHARSET_PATT = Pattern.compile("\\bcharset *= *\"?([^ ;\"]+)\"?", Pattern.CASE_INSENSITIVE); + + /** + * Attempts to parse the {@link Charset} from a contentType string. + * + * If contentType is null or no charset declaration found, then UTF-8 is returned. + * If the found Charset declaration is unknown on this platform then a runtime exception is thrown. + * @param contentType + * @return a {@link Charset} parsed from a charset declaration in a contentType strng. + */ + public static Charset getCharset(String contentType) { + if (contentType == null) { + return ISO_8859_1; + } + + if (com.basho.riak.client.http.util.Constants.CTYPE_JSON_UTF8.equals(contentType)) { + return UTF_8; // Fast-track + } + + Matcher matcher = CHARSET_PATT.matcher(contentType); + if (matcher.find()) { + String encstr = matcher.group(1); + + if (encstr.equalsIgnoreCase("UTF-8")) { + return UTF_8; // Fast-track + } else { + try { + return Charset.forName(encstr.toUpperCase()); + } catch (Exception e) { + // ignore // + } + } + } + + return ISO_8859_1; + } + + /** + * Adds the utf-8 charset to a content type. + * @param contentType + * @return the contentType with ;charset=utf-8 appended. + */ + public static String addUtf8Charset(String contentType) { + if (contentType == null) { + return "text/plain;charset=utf-8"; + } + + Matcher matcher = CHARSET_PATT.matcher(contentType); + if (matcher.find()) { + // replace what ever content-type with utf8 + return contentType.substring(0, matcher.start(1)) + "utf-8" + contentType.substring(matcher.end(1)); + } + + return contentType + ";charset=utf-8"; + } + + /** + * Turns a byte[] array into a string in the provided {@link Charset} + * @param bytes + * @param charset + * @return a String + */ + public static String asString(byte[] bytes, Charset charset) { + return charset.decode(ByteBuffer.wrap(bytes)).toString(); + } + + /** + * Turns a byte[] array into a UTF8 string + * @param bytes + * @param charset + * @return a String + */ + public static String asUTF8String(byte[] bytes) { + try { + return new String(bytes, UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF8 must be present", e); + } + } + + /** + * Turn a string into an array of bytes using the passed {@link Charset} + * @param string + * @param charset + * @return a byte[] array + */ + public static byte[] asBytes(String string, Charset charset) { + try { + return string.getBytes(charset.name()); + } catch (UnsupportedEncodingException e) { + //since we are using *actual* charsets, not string lookups, this + //should *never* happen. But it is better to throw it up than swallow it. + throw new IllegalStateException("Charset present", e); + } + } + + /** + * Turn a UTF-8 encoded string into an array of bytes + * @param string + * @return + */ + public static byte[] utf8StringToBytes(String string) { + return asBytes(string, UTF_8); + } + +} diff --git a/src/main/java/com/basho/riak/client/util/ClientHelper.java b/src/main/java/com/basho/riak/client/util/ClientHelper.java index bcec5130b..032b3392d 100644 --- a/src/main/java/com/basho/riak/client/util/ClientHelper.java +++ b/src/main/java/com/basho/riak/client/util/ClientHelper.java @@ -108,7 +108,7 @@ public HttpResponse setBucketSchema(String bucket, JSONObject schema, RequestMet meta.setHeader(Constants.HDR_ACCEPT, Constants.CTYPE_JSON); PutMethod put = new PutMethod(ClientUtils.makeURI(config, bucket)); - put.setRequestEntity(new ByteArrayRequestEntity(schema.toString().getBytes(), Constants.CTYPE_JSON)); + put.setRequestEntity(new ByteArrayRequestEntity(CharsetUtils.utf8StringToBytes(schema.toString()), Constants.CTYPE_JSON)); return executeMethod(bucket, null, put, meta); } diff --git a/src/main/java/com/basho/riak/client/util/ClientUtils.java b/src/main/java/com/basho/riak/client/util/ClientUtils.java index 517c5b1e2..aefdc6590 100644 --- a/src/main/java/com/basho/riak/client/util/ClientUtils.java +++ b/src/main/java/com/basho/riak/client/util/ClientUtils.java @@ -205,7 +205,7 @@ public static String encodeClientId(byte[] clientId) { } public static String encodeClientId(String clientId) { - return encodeClientId(clientId.getBytes()); + return encodeClientId(CharsetUtils.utf8StringToBytes(clientId)); } /** diff --git a/src/main/java/com/basho/riak/client/util/Multipart.java b/src/main/java/com/basho/riak/client/util/Multipart.java index 2a7c52613..63e4c8bf9 100644 --- a/src/main/java/com/basho/riak/client/util/Multipart.java +++ b/src/main/java/com/basho/riak/client/util/Multipart.java @@ -13,6 +13,9 @@ */ package com.basho.riak.client.util; +import static com.basho.riak.client.util.CharsetUtils.asString; +import static com.basho.riak.client.util.CharsetUtils.getCharset; + import org.apache.commons.httpclient.util.EncodingUtil; import java.io.ByteArrayInputStream; @@ -37,7 +40,7 @@ @Deprecated public class Multipart { - private static byte[] HEADER_DELIM = "\r\n\r\n".getBytes(); + private static byte[] HEADER_DELIM = CharsetUtils.utf8StringToBytes("\r\n\r\n"); private static int indexOf(byte[] text, byte[] pattern, int fromIndex) { if (fromIndex >= text.length || fromIndex < 0) { @@ -94,7 +97,7 @@ public static List parse(Map headers, byte[] bod } String boundary = "\r\n--" + getBoundary(headers.get(Constants.HDR_CONTENT_TYPE)); - byte[] boundaryBytes = boundary.getBytes(); + byte[] boundaryBytes = CharsetUtils.utf8StringToBytes(boundary); int boundarySize = boundary.length(); if ("\r\n--".equals(boundary)) return null; @@ -250,7 +253,7 @@ public String getBodyAsString() { byte[] body = getBody(); if (body == null) return null; - return new String(body); + return asString(body, getCharset(headers)); } public InputStream getStream() { diff --git a/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java b/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java index 2b74f60ff..6027063bc 100644 --- a/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java +++ b/src/main/java/com/basho/riak/client/util/OneTokenInputStream.java @@ -96,6 +96,6 @@ private void initBuffer() throws IOException { offset += bytesRead; } } - buf = new StringBuilder(new String(headStart)); + buf = new StringBuilder(CharsetUtils.asString(headStart, CharsetUtils.ISO_8859_1)); } } diff --git a/src/main/java/com/basho/riak/pbc/RiakClient.java b/src/main/java/com/basho/riak/pbc/RiakClient.java index e79ae4dcd..37bc5eeb8 100644 --- a/src/main/java/com/basho/riak/pbc/RiakClient.java +++ b/src/main/java/com/basho/riak/pbc/RiakClient.java @@ -33,6 +33,7 @@ import org.json.JSONObject; import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.pbc.RPB.RpbDelReq; import com.basho.riak.pbc.RPB.RpbGetClientIdResp; import com.basho.riak.pbc.RPB.RpbGetReq; @@ -111,6 +112,8 @@ void release(RiakConnection c) { /** * helper method to use a reasonable default client id + * beware, it caches the client id. If you call it multiple times on the same client + * you get the *same* id (not good for reusing a client with different ids) * * @throws IOException */ @@ -127,7 +130,7 @@ public void prepareClientID() throws IOException { } byte[] data = new byte[6]; sr.nextBytes(data); - clid = new String(Base64.encodeBase64Chunked(data)); + clid = CharsetUtils.asString(Base64.encodeBase64Chunked(data), CharsetUtils.ISO_8859_1); prefs.put("client_id", clid); try { prefs.flush(); @@ -149,11 +152,19 @@ public void ping() throws IOException { } } + /** + * Warning: the riak client id is 4 bytes. This method silently truncates anymore bytes than that. + * Be aware that if you have two client Ids, "boris1" and "boris2" this method will leave you with 1 client id, "bori". + * Use {@link RiakClient#prepareClientID()} to generate a reasonably unique Id. + * @see RiakClient#prepareClientID() + * @param id + * @throws IOException + */ public void setClientID(String id) throws IOException { if(id == null || id.length() < Constants.RIAK_CLIENT_ID_LENGTH) { throw new IllegalArgumentException("Client ID must be at least " + Constants.RIAK_CLIENT_ID_LENGTH + " bytes long"); } - setClientID(ByteString.copyFrom(id.getBytes(), 0, Constants.RIAK_CLIENT_ID_LENGTH)); + setClientID(ByteString.copyFrom(CharsetUtils.utf8StringToBytes(id), 0, Constants.RIAK_CLIENT_ID_LENGTH)); } // ///////////////////// diff --git a/src/test/java/com/basho/riak/client/http/TestRiakClient.java b/src/test/java/com/basho/riak/client/http/TestRiakClient.java index d960a7704..74cca1c50 100644 --- a/src/test/java/com/basho/riak/client/http/TestRiakClient.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakClient.java @@ -42,6 +42,7 @@ import com.basho.riak.client.http.response.WalkResponse; import com.basho.riak.client.http.util.ClientHelper; import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.util.CharsetUtils; public class TestRiakClient { @@ -274,7 +275,7 @@ public HttpResponse answer(InvocationOnMock invocation) throws Throwable { when(mockHelper.walk(anyString(), anyString(), anyString(), any(RequestMeta.class))).thenReturn(mockHttpResponse); when(mockHttpResponse.getHttpHeaders()).thenReturn(HEADERS); - when(mockHttpResponse.getBody()).thenReturn(BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(CharsetUtils.utf8StringToBytes(BODY)); when(mockHttpResponse.getBodyAsString()).thenReturn(BODY); when(mockHttpResponse.isSuccess()).thenReturn(true); diff --git a/src/test/java/com/basho/riak/client/http/TestRiakObject.java b/src/test/java/com/basho/riak/client/http/TestRiakObject.java index 34b2f4086..60f8315d4 100644 --- a/src/test/java/com/basho/riak/client/http/TestRiakObject.java +++ b/src/test/java/com/basho/riak/client/http/TestRiakObject.java @@ -13,7 +13,10 @@ */ package com.basho.riak.client.http; +import static com.basho.riak.client.util.CharsetUtils.*; + import static org.junit.Assert.*; + import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; @@ -82,7 +85,7 @@ public class TestRiakObject { final String value = "value"; final InputStream valueStream = mock(InputStream.class); final long valueStreamLength = 10; - final String ctype = "ctype"; + final String ctype = Constants.CTYPE_JSON_UTF8; final List links = new ArrayList(); final Map usermeta = new HashMap(); usermeta.put("testKey", "testValue"); @@ -92,7 +95,7 @@ public class TestRiakObject { final RiakLink link = new RiakLink("b", "l", "t"); links.add(link); - RiakObject copy = new RiakObject("b", "k2", value.getBytes(), ctype, links, usermeta, vclock, lastmod, vtag); + RiakObject copy = new RiakObject("b", "k2", utf8StringToBytes(value), ctype, links, usermeta, vclock, lastmod, vtag); copy.setValueStream(valueStream, valueStreamLength); impl.copyData(copy); @@ -147,7 +150,7 @@ public class TestRiakObject { @Test public void copyData_copies_null_data() { final String value = "value"; - final String ctype = "ctype"; + final String ctype = Constants.CTYPE_JSON_UTF8; final List links = new ArrayList(); final Map usermeta = new HashMap(); final String vclock = "vclock"; @@ -156,7 +159,7 @@ public class TestRiakObject { final RiakLink link = new RiakLink("b", "l", "t"); links.add(link); - impl = new RiakObject("b", "k", value.getBytes(), ctype, links, usermeta, vclock, lastmod, vtag); + impl = new RiakObject("b", "k", utf8StringToBytes(value), ctype, links, usermeta, vclock, lastmod, vtag); impl.copyData(new RiakObject(null, null)); assertEquals("b", impl.getBucket()); @@ -191,7 +194,7 @@ public class TestRiakObject { @Test public void value_stream_is_separate_from_value() { final String value = "value"; - final byte[] isvalue = "isbytes".getBytes(); + final byte[] isvalue = utf8StringToBytes("isbytes"); final InputStream is = new ByteArrayInputStream(isvalue); impl.setValue(value); @@ -387,7 +390,7 @@ public class TestRiakObject { @SuppressWarnings("unchecked") @Test public void write_to_http_method_gives_value_stream_priority_over_value() { final String value = "value"; - final byte[] isvalue = "isbytes".getBytes(); + final byte[] isvalue = utf8StringToBytes("isbytes"); final InputStream is = new ByteArrayInputStream(isvalue); final ByteArrayOutputStream os = new ByteArrayOutputStream(); final EntityEnclosingMethod mockHttpMethod = mock(EntityEnclosingMethod.class); @@ -512,7 +515,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { final List links = Arrays.asList(new RiakLink("b", "l", "t"), new RiakLink("b", "e", "c"), new RiakLink("g", "c", "s"), new RiakLink("q", "p", "c")); - final RiakObject riakObject = new RiakObject("b", "k", "v".getBytes(), "", links, (Map) null, "", "", ""); + final RiakObject riakObject = new RiakObject("b", "k", utf8StringToBytes("v"), "", links, (Map) null, "", "", ""); assertEquals(links.size(), riakObject.numLinks()); assertTrue(riakObject.hasLinks()); @@ -576,7 +579,7 @@ private boolean linkPresent(final RiakObject riakObject, final RiakLink link) { userMeta.put("acl", "admin"); userMeta.put("my-meta", "my-value"); - final RiakObject riakObject = new RiakObject("b", "k", "v".getBytes(), "", null, userMeta, "", "", ""); + final RiakObject riakObject = new RiakObject("b", "k", utf8StringToBytes("v"), "", null, userMeta, "", "", ""); assertTrue(riakObject.hasUsermeta()); assertTrue(riakObject.hasUsermetaItem("acl")); @@ -608,7 +611,7 @@ private boolean linkPresent(final RiakObject riakObject, final RiakLink link) { } @Test public void modifyLinksAndWriteToMethodConcurrently() throws InterruptedException { - final RiakObject riakObject = new RiakObject("b", "k", "v".getBytes()); + final RiakObject riakObject = new RiakObject("b", "k", utf8StringToBytes("v")); final EntityEnclosingMethod mockHttpMethod = mock(EntityEnclosingMethod.class); when(mockHttpMethod.getPath()).thenReturn("/riak/b/k"); @@ -646,7 +649,7 @@ public void run() { } @Test public void modifyUserMetaAndWriteToMethodConcurrently() throws InterruptedException { - final RiakObject riakObject = new RiakObject("b", "k", "v".getBytes()); + final RiakObject riakObject = new RiakObject("b", "k", utf8StringToBytes("v")); final EntityEnclosingMethod mockHttpMethod = mock(EntityEnclosingMethod.class); when(mockHttpMethod.getPath()).thenReturn("/riak/b/k"); @@ -683,16 +686,16 @@ public void run() { } @Test public void valueByteArraySafelyEncapsulated() { - final byte[] value = "vvvv".getBytes(); + final byte[] value = utf8StringToBytes("vvvv"); final RiakObject riakObject = new RiakObject("b", "k", value); - assertArrayEquals("vvvv".getBytes(), riakObject.getValueAsBytes()); + assertArrayEquals(utf8StringToBytes("vvvv"), riakObject.getValueAsBytes()); value[0] = 'b'; - assertArrayEquals("vvvv".getBytes(), riakObject.getValueAsBytes()); + assertArrayEquals(utf8StringToBytes("vvvv"), riakObject.getValueAsBytes()); byte[] roInternalValue = riakObject.getValueAsBytes(); roInternalValue[0] = 'z'; - assertArrayEquals("vvvv".getBytes(), riakObject.getValueAsBytes()); + assertArrayEquals(utf8StringToBytes("vvvv"), riakObject.getValueAsBytes()); } } diff --git a/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java b/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java index 19ce2e1b7..e08e33583 100644 --- a/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestBasic.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.itest; +import static com.basho.riak.client.util.CharsetUtils.*; import static com.basho.riak.client.http.Hosts.RIAK_URL; import static com.basho.riak.client.http.itest.Utils.*; import static org.junit.Assert.*; @@ -65,7 +66,7 @@ public class ITestBasic { assertEquals(404, fetchresp.getStatusCode()); // Store a new object - RiakObject o = new RiakObject(BUCKET, KEY, VALUE1.getBytes()); + RiakObject o = new RiakObject(BUCKET, KEY, utf8StringToBytes(VALUE1)); StoreResponse storeresp = c.store(o, WRITE_3_REPLICAS()); assertSuccess(storeresp); @@ -106,9 +107,9 @@ public class ITestBasic { final String CHASH_FUN = "chash_bucketonly_keyfun"; // Add a few objects - assertSuccess(c.store(new RiakObject(BUCKET, KEY1, "v".getBytes()), WRITE_3_REPLICAS())); - assertSuccess(c.store(new RiakObject(BUCKET, KEY2, "v".getBytes()), WRITE_3_REPLICAS())); - assertSuccess(c.store(new RiakObject(BUCKET, KEY3, "v".getBytes()), WRITE_3_REPLICAS())); + assertSuccess(c.store(new RiakObject(BUCKET, KEY1, utf8StringToBytes("v")), WRITE_3_REPLICAS())); + assertSuccess(c.store(new RiakObject(BUCKET, KEY2, utf8StringToBytes("v")), WRITE_3_REPLICAS())); + assertSuccess(c.store(new RiakObject(BUCKET, KEY3, utf8StringToBytes("v")), WRITE_3_REPLICAS())); // Get the current bucket schema and contents BucketResponse bucketresp = c.listBucket(BUCKET); @@ -145,7 +146,7 @@ public class ITestBasic { final String bucket = UUID.randomUUID().toString(); final String key = UUID.randomUUID().toString(); - final byte[] value = "value".getBytes(); + final byte[] value = utf8StringToBytes("value"); RiakBucketInfo bucketInfo = new RiakBucketInfo(); bucketInfo.setNVal(3); @@ -188,7 +189,7 @@ public class ITestBasic { final RiakClient c = new RiakClient(RIAK_URL); final String bucket = UUID.randomUUID().toString(); final String key = UUID.randomUUID().toString(); - final byte[] value = "value".getBytes(); + final byte[] value = utf8StringToBytes("value"); RiakObject o = new RiakObject(bucket, key, value); StoreResponse storeresp = c.store(o, WRITE_3_REPLICAS()); @@ -205,8 +206,8 @@ public class ITestBasic { final String bucket = UUID.randomUUID().toString(); final String key = UUID.randomUUID().toString(); - final byte[] value = "value".getBytes(); - final byte[] newValue = "new_value".getBytes(); + final byte[] value = utf8StringToBytes("value"); + final byte[] newValue = utf8StringToBytes("new_value"); RiakBucketInfo bucketInfo = new RiakBucketInfo(); bucketInfo.setAllowMult(true); @@ -225,6 +226,5 @@ public class ITestBasic { assertSuccess(storeresp); assertTrue(storeresp.hasObject()); assertTrue(storeresp.hasSiblings()); - assertEquals(2, storeresp.getSiblings().size()); } } diff --git a/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java b/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java index 6ccdf5f94..8c1daedeb 100644 --- a/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestDataLoad.java @@ -26,6 +26,7 @@ import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.http.RiakObject; +import com.basho.riak.client.util.CharsetUtils; /** * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. @@ -60,10 +61,10 @@ public void run() { Random rnd = new Random(); for (int i = 0; i < NUM_OBJECTS / NUM_THREADS; i++) { String key = "data-load-" + idx.getAndIncrement(); - String value = new String(data[rnd.nextInt(NUM_VALUES)]); + String value = CharsetUtils.asUTF8String(data[rnd.nextInt(NUM_VALUES)]); RiakObject o = riak.fetch(BUCKET, key).getObject(); if (o == null) { - o = new RiakObject(riak, BUCKET, key, value.getBytes()); + o = new RiakObject(riak, BUCKET, key, CharsetUtils.utf8StringToBytes(value)); } else { o.setValue(value); } diff --git a/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java b/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java index c7e11d1ce..e76827d02 100644 --- a/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestStreaming.java @@ -33,6 +33,7 @@ import com.basho.riak.client.http.response.FetchResponse; import com.basho.riak.client.http.util.ClientUtils; import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.util.CharsetUtils; /** * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. @@ -47,7 +48,7 @@ public class ITestStreaming { // Add objects for (int i = 0; i < NUM_KEYS; i++) { - assertSuccess(c.store(new RiakObject(BUCKET, "key" + Integer.toString(i), "v".getBytes()), + assertSuccess(c.store(new RiakObject(BUCKET, "key" + Integer.toString(i), CharsetUtils.utf8StringToBytes("v")), WRITE_3_REPLICAS())); } diff --git a/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java b/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java index 5cf7d115d..666376b1c 100644 --- a/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java +++ b/src/test/java/com/basho/riak/client/http/itest/ITestWalk.java @@ -26,6 +26,7 @@ import com.basho.riak.client.http.RiakLink; import com.basho.riak.client.http.RiakObject; import com.basho.riak.client.http.response.WalkResponse; +import com.basho.riak.client.util.CharsetUtils; /** * Assumes Riak is reachable at {@link com.basho.riak.client.http.Hosts#RIAK_URL }. @@ -41,8 +42,8 @@ public void test_walk() { final String LEAF1 = "leaf1"; final String LEAF2 = "leaf2"; final String EXCLUDED_LEAF = "excluded_leaf"; - final byte[] INCLUDED_VALUE = "included".getBytes(); - final byte[] EXCLUDED_VALUE = "excluded".getBytes(); + final byte[] INCLUDED_VALUE = CharsetUtils.utf8StringToBytes("included"); + final byte[] EXCLUDED_VALUE = CharsetUtils.utf8StringToBytes("excluded"); final String TAG_INCLUDE = "tag_include"; final String TAG_EXCLUDE = "tag_exclude"; diff --git a/src/test/java/com/basho/riak/client/http/itest/Utils.java b/src/test/java/com/basho/riak/client/http/itest/Utils.java index aed88b29b..3453db1c8 100644 --- a/src/test/java/com/basho/riak/client/http/itest/Utils.java +++ b/src/test/java/com/basho/riak/client/http/itest/Utils.java @@ -19,6 +19,7 @@ import com.basho.riak.client.http.request.RequestMeta; import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.util.CharsetUtils; public class Utils { @@ -36,7 +37,7 @@ public static void assertSuccess(HttpResponse response) { msg.append(" -- ") .append(response.getHttpMethod().getStatusLine()).append("; ") .append("Response headers: ").append(response.getHttpHeaders().toString()).append("; ") - .append("Response body: ").append(new String(response.getBody())); + .append("Response body: ").append(CharsetUtils.asUTF8String(response.getBody())); fail(msg.toString()); } } diff --git a/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java b/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java index 9fba524b5..59c866dbf 100644 --- a/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestBucketResponse.java @@ -27,6 +27,7 @@ import com.basho.riak.client.http.response.BucketResponse; import com.basho.riak.client.http.response.HttpResponse; +import com.basho.riak.client.util.CharsetUtils; public class TestBucketResponse { @@ -47,9 +48,9 @@ public class TestBucketResponse { "\"young_vclock\":20}," + "\"keys\":" + "[\"j\",\"k\",\"l\"]}"; - final byte[] BODY = TEXT_BODY.getBytes(); + final byte[] BODY = CharsetUtils.utf8StringToBytes(TEXT_BODY); final InputStream STREAM = new ByteArrayInputStream( - ("{\"props\":" + + (CharsetUtils.utf8StringToBytes("{\"props\":" + "{\"name\":\"b\"," + "\"allow_mult\":false," + "\"big_vclock\":50," + @@ -64,7 +65,7 @@ public class TestBucketResponse { "\"small_vclock\":10," + "\"young_vclock\":20}}" + "{\"keys\":[\"j\"]}{\"keys\":[]}{\"keys\":[]}{\"keys\":[\"k\",\"l\"]}") - .getBytes()); + )); @Test public void doesnt_throw_on_null_impl() throws JSONException, IOException { new BucketResponse(null); @@ -129,10 +130,10 @@ public class TestBucketResponse { } @Test public void returns_empty_keys_list_if_keys_element_not_in_response() throws JSONException, IOException { - final byte[] body = "{\"props\": {\"name\":\"b\"}}".getBytes(); + final byte[] body = CharsetUtils.utf8StringToBytes("{\"props\": {\"name\":\"b\"}}"); HttpResponse mockHttpResponse = mock(HttpResponse.class); when(mockHttpResponse.getBody()).thenReturn(body); - when(mockHttpResponse.getBodyAsString()).thenReturn(new String(body)); + when(mockHttpResponse.getBodyAsString()).thenReturn(CharsetUtils.asUTF8String(body)); when(mockHttpResponse.isSuccess()).thenReturn(true); BucketResponse impl = new BucketResponse(mockHttpResponse); diff --git a/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java b/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java index cc1dd07cc..9a91bdc46 100644 --- a/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestFetchResponse.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.response; +import static com.basho.riak.client.util.CharsetUtils.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -101,7 +102,7 @@ public class TestFetchResponse { when(mockHttpResponse.getBucket()).thenReturn(BUCKET); when(mockHttpResponse.getKey()).thenReturn(KEY); when(mockHttpResponse.getHttpHeaders()).thenReturn(SINGLE_HEADERS); - when(mockHttpResponse.getBody()).thenReturn(SINGLE_BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes(SINGLE_BODY)); when(mockHttpResponse.isSuccess()).thenReturn(true); FetchResponse impl = new FetchResponse(mockHttpResponse, mockRiakClient); @@ -123,7 +124,7 @@ public class TestFetchResponse { when(mockHttpResponse.getBucket()).thenReturn(BUCKET); when(mockHttpResponse.getKey()).thenReturn(KEY); when(mockHttpResponse.getHttpHeaders()).thenReturn(SIBLING_HEADERS); - when(mockHttpResponse.getBody()).thenReturn(SIBLING_BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes(SIBLING_BODY)); when(mockHttpResponse.getBodyAsString()).thenReturn(SIBLING_BODY); when(mockHttpResponse.getStatusCode()).thenReturn(300); @@ -163,7 +164,7 @@ public class TestFetchResponse { when(mockHttpResponse.getBucket()).thenReturn(BUCKET); when(mockHttpResponse.getKey()).thenReturn(KEY); when(mockHttpResponse.getHttpHeaders()).thenReturn(SIBLING_HEADERS); - when(mockHttpResponse.getBody()).thenReturn(SIBLING_BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes(SIBLING_BODY)); when(mockHttpResponse.getBodyAsString()).thenReturn(SIBLING_BODY); when(mockHttpResponse.getStatusCode()).thenReturn(300); @@ -192,7 +193,7 @@ public class TestFetchResponse { } @Test public void returns_streamed_collection_on_streaming_300_response() throws IOException { - final ByteArrayInputStream is = new ByteArrayInputStream(SIBLING_BODY.getBytes()); + final ByteArrayInputStream is = new ByteArrayInputStream(utf8StringToBytes(SIBLING_BODY)); when(mockHttpResponse.getStatusCode()).thenReturn(300); when(mockHttpResponse.getBucket()).thenReturn(BUCKET); @@ -240,7 +241,7 @@ public class TestFetchResponse { } @Test public void does_not_close_stream_on_streaming_300_response() throws IOException { - final ByteArrayInputStream is = new ByteArrayInputStream(SIBLING_BODY.getBytes()); + final ByteArrayInputStream is = new ByteArrayInputStream(utf8StringToBytes(SIBLING_BODY)); when(mockHttpResponse.getStatusCode()).thenReturn(300); when(mockHttpResponse.getBucket()).thenReturn(BUCKET); diff --git a/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java b/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java index e04dc11f4..e88574604 100644 --- a/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java +++ b/src/test/java/com/basho/riak/client/http/response/TestHttpResponseDecorator.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.response; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -32,7 +33,7 @@ public class TestHttpResponseDecorator { final String BUCKET = "bucket"; final String KEY = "key"; - final byte[] BODY = "body".getBytes(); + final byte[] BODY = utf8StringToBytes("body"); final int STATUS_CODE = 1; final Map HTTP_HEADERS = new HashMap(); final HttpMethod HTTP_METHOD = mock(HttpMethod.class); diff --git a/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java b/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java index a494a3769..33ee155cd 100644 --- a/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java +++ b/src/test/java/com/basho/riak/client/http/response/TestStreamedKeysCollection.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.response; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; @@ -31,7 +32,7 @@ public class TestStreamedKeysCollection { @Test public void gets_all_keys() { final String keys = "{\"keys\":[\"key1\"]}{\"keys\":[]}{\"keys\":[]}{\"keys\":[\"key2\",\"key3\"]}{\"keys\":[]}"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); Iterator iter = impl.iterator(); @@ -44,7 +45,7 @@ public class TestStreamedKeysCollection { @Test public void iterator_iterates_all_keys() { final String keys = "{\"keys\":[\"key1\"]}{\"keys\":[]}{\"keys\":[]}{\"keys\":[\"key2\",\"key3\"]}{\"keys\":[]}"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); StreamedKeysCollection impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); int i = 0; @@ -56,7 +57,7 @@ public class TestStreamedKeysCollection { @Test public void reads_an_input_array() { final String keys = "[\"key1\", \"key2\"]"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); StreamedKeysCollection impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); Iterator iter = impl.iterator(); @@ -66,7 +67,7 @@ public class TestStreamedKeysCollection { @Test public void cacheNext_finds_first_embedded_array() { final String keys = "{\"keys\":[\"key1\",\"key2\",\"key3\"]}"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); StreamedKeysCollection impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); assertEquals("key1", impl.iterator().next()); @@ -74,7 +75,7 @@ public class TestStreamedKeysCollection { @Test public void finds_next_array() { final String keys = "{\"keys\":[\"key1\"]}{\"j\": 1, \"k\": \"v\", \"l\": [ ]}[\"key2\", \"key3\"]"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); StreamedKeysCollection impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); Iterator iter = impl.iterator(); @@ -85,7 +86,7 @@ public class TestStreamedKeysCollection { @Test public void cache_next_returns_false_after_calling_close_backend() { final String keys = "[\"key1\", \"key2\"]"; - final InputStream stream = new ByteArrayInputStream(keys.getBytes()); + final InputStream stream = new ByteArrayInputStream(utf8StringToBytes(keys)); impl = new StreamedKeysCollection(new JSONTokener(new InputStreamReader(stream))); assertTrue(impl.cacheNext()); diff --git a/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java b/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java index 2fb311b11..69ba852e1 100644 --- a/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java +++ b/src/test/java/com/basho/riak/client/http/response/TestWalkResponse.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.response; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -54,7 +55,7 @@ public class TestWalkResponse { } @Test public void returns_empty_list_on_no_content() { - when(mockHttpResponse.getBody()).thenReturn("".getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes("")); when(mockHttpResponse.isSuccess()).thenReturn(true); WalkResponse impl = new WalkResponse(mockHttpResponse, mockRiakClient); @@ -81,7 +82,7 @@ public class TestWalkResponse { + "\r\n" + "--BCVLGEKnH0gY7KsH5nW3xnzhYbU--\r\n"; - when(mockHttpResponse.getBody()).thenReturn(BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes(BODY)); when(mockHttpResponse.getBodyAsString()).thenReturn(BODY); when(mockHttpResponse.isSuccess()).thenReturn(true); @@ -113,7 +114,7 @@ public class TestWalkResponse { + "\r\n" + "--BCVLGEKnH0gY7KsH5nW3xnzhYbU--\r\n"; - when(mockHttpResponse.getBody()).thenReturn(BODY.getBytes()); + when(mockHttpResponse.getBody()).thenReturn(utf8StringToBytes(BODY)); when(mockHttpResponse.getBodyAsString()).thenReturn(BODY); when(mockHttpResponse.isSuccess()).thenReturn(true); diff --git a/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java b/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java index ed1075049..feab4192b 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java +++ b/src/test/java/com/basho/riak/client/http/util/TestBranchableInputStream.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.*; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; @@ -33,7 +34,7 @@ public class TestBranchableInputStream { BranchableInputStream impl; @Test public void behaves_as_standard_input_stream_for_short_inputs() throws IOException { - byte[] bytes = "short buffer".getBytes(); + byte[] bytes = utf8StringToBytes("short buffer"); ByteArrayInputStream is = new ByteArrayInputStream(bytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); impl = new BranchableInputStream(is); @@ -88,7 +89,7 @@ public class TestBranchableInputStream { } @Test public void read_position_updates_when_reading() throws IOException { - byte[] bytes = "012345678901234567890123456789".getBytes(); + byte[] bytes = utf8StringToBytes("012345678901234567890123456789"); ByteArrayInputStream is = new ByteArrayInputStream(bytes); impl = new BranchableInputStream(is); @@ -99,7 +100,7 @@ public class TestBranchableInputStream { } @Test public void primary_and_branch_positions_updates_when_reading_from_branch() throws IOException { - byte[] bytes = "012345678901234567890123456789".getBytes(); + byte[] bytes = utf8StringToBytes("012345678901234567890123456789"); ByteArrayInputStream is = new ByteArrayInputStream(bytes); InputStreamBranch[] branches = new InputStreamBranch[5]; impl = new BranchableInputStream(is); diff --git a/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java b/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java index 67f219dde..d2e30ec25 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java +++ b/src/test/java/com/basho/riak/client/http/util/TestClientHelper.java @@ -47,6 +47,7 @@ import com.basho.riak.client.http.util.ClientHelper; import com.basho.riak.client.http.util.ClientUtils; import com.basho.riak.client.http.util.Constants; +import com.basho.riak.client.util.CharsetUtils; public class TestClientHelper { @@ -74,7 +75,7 @@ public class TestClientHelper { } @Test public void client_helper_uses_passed_in_client_id() throws UnsupportedEncodingException { - assertEquals(clientId, new String(impl.getClientId())); + assertEquals(clientId, CharsetUtils.asUTF8String(impl.getClientId())); } @Test public void client_helper_generates_client_id_if_null() { diff --git a/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java b/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java index d64bc395b..ad7078cab 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java +++ b/src/test/java/com/basho/riak/client/http/util/TestClientUtils.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -278,7 +279,7 @@ public class TestClientUtils { headers.put("x-riak-vclock", "vclock"); String body = "\r\n--boundary\r\n" + "\r\n" + "--boundary--"; - List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, body.getBytes()); + List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, utf8StringToBytes(body)); assertEquals(1, objects.size()); assertSame(mockRiakClient, objects.get(0).getRiakClient()); assertEquals("b", objects.get(0).getBucket()); @@ -293,7 +294,7 @@ public class TestClientUtils { + "Link: ; riaktag=t\r\n" + "ETag: vtag\r\n" + "X-Riak-Meta-Test: value\r\n" + "\r\n" + "--boundary--"; - List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, body.getBytes()); + List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, utf8StringToBytes(body)); assertEquals(1, objects.get(0).numLinks()); assertTrue(objects.get(0).hasLink(new RiakLink("b", "l", "t"))); @@ -313,7 +314,7 @@ public class TestClientUtils { headers.put("x-riak-vclock", "vclock"); String body = "\r\n--boundary\r\n" + "\r\n" + "foo\r\n" + "--boundary--"; - List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, body.getBytes()); + List objects = ClientUtils.parseMultipart(mockRiakClient, "b", "k", headers, utf8StringToBytes(body)); assertEquals("foo", objects.get(0).getValue()); } diff --git a/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java b/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java index 6447ddc29..840ef804c 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java +++ b/src/test/java/com/basho/riak/client/http/util/TestCollectionWrapper.java @@ -25,6 +25,7 @@ import org.junit.Test; import com.basho.riak.client.http.util.CollectionWrapper; +import com.basho.riak.client.util.CharsetUtils; public class TestCollectionWrapper { @@ -62,7 +63,7 @@ class CollectionWrapperStub extends CollectionWrapper { return false; byte[] bytes = new byte[10]; new Random().nextBytes(bytes); - String el = new String(bytes); + String el = CharsetUtils.asUTF8String(bytes); els.add(el); impl.cache(el); return true; diff --git a/src/test/java/com/basho/riak/client/http/util/TestMultipart.java b/src/test/java/com/basho/riak/client/http/util/TestMultipart.java index 13979a82a..cde08ae40 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestMultipart.java +++ b/src/test/java/com/basho/riak/client/http/util/TestMultipart.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import org.junit.Test; import com.basho.riak.client.http.util.Constants; @@ -32,7 +33,7 @@ public class TestMultipart { Map headers = new HashMap(); headers.put("content-type", "text/plain"); String body = "abc"; - assertNull(Multipart.parse(headers, body.getBytes())); + assertNull(Multipart.parse(headers, utf8StringToBytes(body))); } @Test public void null_result_if_not_content_type_missing_boundary_parameter() { @@ -40,7 +41,7 @@ public class TestMultipart { headers.put("content-type", "multipart/mixed"); String body = "\r\n--boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "subpart\r\n" + "--boundary--"; - assertNull(Multipart.parse(headers, body.getBytes())); + assertNull(Multipart.parse(headers, utf8StringToBytes(body))); } @Test public void parses_multipart_with_1_empty_part() { @@ -48,7 +49,7 @@ public class TestMultipart { headers.put("content-type", "multipart/mixed; boundary=boundary"); String body = "\r\n--boundary\r\n" + "\r\n" + "--boundary--"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(1, parts.size()); assertEquals(0, parts.get(0).getHeaders().size()); assertEquals("", parts.get(0).getBodyAsString()); @@ -59,7 +60,7 @@ public class TestMultipart { headers.put("content-type", "multipart/mixed; boundary=boundary"); String body = "\r\n--boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "subpart\r\n" + "--boundary--"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(1, parts.size()); assertEquals(1, parts.get(0).getHeaders().size()); assertEquals("text/plain", parts.get(0).getHeaders().get(Constants.HDR_CONTENT_TYPE)); @@ -99,7 +100,7 @@ public class TestMultipart { String body = "\r\n--boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "part1\r\n" + "--boundary\r\n" + "\r\n" + "part2\r\n" + "--boundary--"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(2, parts.size()); assertEquals("part1", parts.get(0).getBodyAsString()); assertEquals("part2", parts.get(1).getBodyAsString()); @@ -113,7 +114,7 @@ public class TestMultipart { + "subpart1\r\n" + "--5hgaasMxj1NIcoxJBpWd4j9IuaW\r\n" + "Content-Type: application/octet-stream\r\n" + "\r\n" + "subpart2\r\n" + "--5hgaasMxj1NIcoxJBpWd4j9IuaW--\r\n" + "\r\n" + "--boundary--\r\n"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(1, parts.size()); List subparts = Multipart.parse(parts.get(0).getHeaders(), parts.get(0).getBody()); @@ -130,7 +131,7 @@ public class TestMultipart { "Location: /riak/test/key\r\n" + "Content-Type: application/octet-stream\r\n" + "\r\n" + PART_BODY + "\r\n--boundary--"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(3, parts.get(0).getHeaders().size()); assertEquals("a85hYGBgzGDKBVIsLOLmazKYEhnzWBkmzFt4hC8LAA==", parts.get(0).getHeaders().get(Constants.HDR_VCLOCK)); @@ -148,7 +149,7 @@ public class TestMultipart { // \x" String body = "\r\n--\\x\"\r\n" + "\r\n" + "part\r\n" + "--\\x\"--"; - List parts = Multipart.parse(headers, body.getBytes()); + List parts = Multipart.parse(headers, utf8StringToBytes(body)); assertEquals(1, parts.size()); assertEquals(0, parts.get(0).getHeaders().size()); assertEquals("part", parts.get(0).getBodyAsString()); diff --git a/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java b/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java index c6ae8f10b..53dccbda4 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java +++ b/src/test/java/com/basho/riak/client/http/util/TestOneTokenInputStream.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -36,7 +37,7 @@ public class TestOneTokenInputStream { part1 + delim + "\r\n" + part2; - InputStream stream = new ByteArrayInputStream(body.getBytes()); + InputStream stream = new ByteArrayInputStream(utf8StringToBytes(body)); impl = new OneTokenInputStream(stream, delim); ByteArrayOutputStream os = new ByteArrayOutputStream(); @@ -47,7 +48,7 @@ public class TestOneTokenInputStream { @Test public void no_content_if_stream_starts_with_delimiter() throws IOException { String delim = "\r\n--boundary"; String body = delim + "abcdef"; - InputStream stream = new ByteArrayInputStream(body.getBytes()); + InputStream stream = new ByteArrayInputStream(utf8StringToBytes(body)); impl = new OneTokenInputStream(stream, delim); assertEquals(-1, impl.read()); @@ -57,7 +58,7 @@ public class TestOneTokenInputStream { String delim = "\r\n--boundary"; String part1 = "abcdefghijklmnop"; String body = part1 + delim; - InputStream stream = new ByteArrayInputStream(body.getBytes()); + InputStream stream = new ByteArrayInputStream(utf8StringToBytes(body)); impl = new OneTokenInputStream(stream, delim); ByteArrayOutputStream os = new ByteArrayOutputStream(); @@ -69,7 +70,7 @@ public class TestOneTokenInputStream { String delim = "\r\n--boundary"; String part1 = "abcdefghijklmnop"; String body = part1; - InputStream stream = new ByteArrayInputStream(body.getBytes()); + InputStream stream = new ByteArrayInputStream(utf8StringToBytes(body)); impl = new OneTokenInputStream(stream, delim); ByteArrayOutputStream os = new ByteArrayOutputStream(); diff --git a/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java b/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java index 7e7e548ad..5a2d30011 100644 --- a/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java +++ b/src/test/java/com/basho/riak/client/http/util/TestStreamedMultipart.java @@ -13,6 +13,7 @@ */ package com.basho.riak.client.http.util; +import static com.basho.riak.client.util.CharsetUtils.utf8StringToBytes; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; @@ -57,7 +58,7 @@ public class TestStreamedMultipart { "--boundary--\r\n" + "postlude\n" + "\r\n"; - InputStream stream = new ByteArrayInputStream(body.getBytes()); + InputStream stream = new ByteArrayInputStream(utf8StringToBytes(body)); StreamedMultipart impl; @@ -67,7 +68,7 @@ public class TestStreamedMultipart { "--boundary\r\n" + "message\r\n" + "--boundary--"; - stream = new ByteArrayInputStream(body.getBytes()); + stream = new ByteArrayInputStream(utf8StringToBytes(body)); new StreamedMultipart(headers, stream); } @@ -77,7 +78,7 @@ public class TestStreamedMultipart { "--boundary\r\n" + "message\r\n" + "--boundary--"; - stream = new ByteArrayInputStream(body.getBytes()); + stream = new ByteArrayInputStream(utf8StringToBytes(body)); new StreamedMultipart(headers, stream); } @@ -87,7 +88,7 @@ public class TestStreamedMultipart { "--wrong\r\n" + "message\r\n" + "--wrong--"; - stream = new ByteArrayInputStream(body.getBytes()); + stream = new ByteArrayInputStream(utf8StringToBytes(body)); new StreamedMultipart(headers, stream); } diff --git a/src/test/java/com/basho/riak/client/itest/ITestBucket.java b/src/test/java/com/basho/riak/client/itest/ITestBucket.java index 9fe1cdbe7..7934610d9 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestBucket.java +++ b/src/test/java/com/basho/riak/client/itest/ITestBucket.java @@ -67,12 +67,12 @@ public abstract class ITestBucket { assertNull(o); IRiakObject fetched = b.fetch("k").execute(); - assertEquals("v", fetched.getValue()); + assertEquals("v", fetched.getValueAsString()); // now update that riak object b.store("k", "my new value").execute(); fetched = b.fetch("k").execute(); - assertEquals("my new value", fetched.getValue()); + assertEquals("my new value", fetched.getValueAsString()); b.delete("k").execute(); diff --git a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java index b9b3c93ee..bb5bdfc68 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java +++ b/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java @@ -27,6 +27,7 @@ import com.basho.riak.client.IRiakClient; import com.basho.riak.client.RiakException; import com.basho.riak.client.bucket.Bucket; +import com.basho.riak.client.util.CharsetUtils; /** * @author russell @@ -86,7 +87,7 @@ public abstract class ITestClientBasic { } @Test public void clientIds() throws Exception { - final byte[] clientId = "abcd".getBytes("UTF-8"); + final byte[] clientId = CharsetUtils.utf8StringToBytes("abcd"); client.setClientId(clientId.clone()); assertArrayEquals(clientId, client.getClientId()); diff --git a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java index 44c84192e..44d440106 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java +++ b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java @@ -32,6 +32,7 @@ import com.basho.riak.client.bucket.RiakBucket; import com.basho.riak.client.builders.RiakObjectBuilder; import com.basho.riak.client.query.WalkResult; +import com.basho.riak.client.util.CharsetUtils; /** * @author russell @@ -44,7 +45,7 @@ public class ITestLinkWalk { final String fooVal = "fooer"; final String barVal = "barrer"; - + final String bucketName = "test_walk_" + UUID.randomUUID().toString(); final String[] first = { "first", "the first" }; final String[] second = { "second", fooVal }; @@ -95,7 +96,7 @@ public class ITestLinkWalk { for (IRiakObject object : s) { keys.add(object.getKey()); - assertEquals(fooVal, object.getValue()); + assertEquals(fooVal, CharsetUtils.asString(object.getValue(), CharsetUtils.UTF_8)); } assertEquals(1, s.size()); diff --git a/src/test/java/com/basho/riak/pbc/TestRiakObject.java b/src/test/java/com/basho/riak/pbc/TestRiakObject.java index 4a135a959..7acb9a420 100644 --- a/src/test/java/com/basho/riak/pbc/TestRiakObject.java +++ b/src/test/java/com/basho/riak/pbc/TestRiakObject.java @@ -21,6 +21,7 @@ import org.junit.Test; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.pbc.RPB.RpbContent; @@ -41,7 +42,7 @@ public class TestRiakObject { } @Test public void constuctFromStringsAndBytes() { - final RiakObject riakObject = new RiakObject(BUCKET, KEY, CONTENT.getBytes()); + final RiakObject riakObject = new RiakObject(BUCKET, KEY, CharsetUtils.utf8StringToBytes(CONTENT)); assertBasicValues(riakObject); } diff --git a/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java b/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java index 5827dac77..cf6a36e0f 100644 --- a/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java +++ b/src/test/java/com/basho/riak/pbc/itest/ITestDataLoad.java @@ -27,9 +27,11 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.commons.codec.binary.Base64; import org.junit.Before; import org.junit.Test; +import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.pbc.RequestMeta; import com.basho.riak.pbc.RiakClient; import com.basho.riak.pbc.RiakObject; @@ -68,7 +70,7 @@ public class ITestDataLoad { Random rnd = new Random(); for (int i = 0; i < NUM_OBJECTS; i++) { String key = "data-load-" + idx; - String value = new String(data[rnd.nextInt(NUM_VALUES)]); + String value = CharsetUtils.asString(data[rnd.nextInt(NUM_VALUES)], CharsetUtils.ISO_8859_1);; RiakObject o = new RiakObject(bucket, key, value); objects[i] = o; idx++; @@ -113,7 +115,7 @@ public void run() { Random rnd = new Random(); for (int i = 0; i < NUM_OBJECTS / NUM_THREADS; i++) { String key = "data-load-" + idx.getAndIncrement(); - String value = new String(data[rnd.nextInt(NUM_VALUES)]); + String value = CharsetUtils.asString(data[rnd.nextInt(NUM_VALUES)], CharsetUtils.ISO_8859_1); RiakObject[] objects = riak.fetch(BUCKET, key); RiakObject o = null; if (objects.length == 0) { From 4e4b25ab9ebfee5fdb4ca427f586247d540dc40c Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 6 May 2011 16:54:28 +0100 Subject: [PATCH 028/764] Fix whitespace in comment header --- src/main/java/com/basho/riak/client/util/CharsetUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/basho/riak/client/util/CharsetUtils.java b/src/main/java/com/basho/riak/client/util/CharsetUtils.java index 790d2260a..5cfa5e446 100644 --- a/src/main/java/com/basho/riak/client/util/CharsetUtils.java +++ b/src/main/java/com/basho/riak/client/util/CharsetUtils.java @@ -23,10 +23,10 @@ /** * Utils for dealing with byte[], String charset issues, especially since Java 5 * is less cool than Java 6 in this respect. - * + * * This code is all from the Trifork fork of the client and was written by * Krestan Krab, Christian Hvitved and Erik Søe Sørensen. - * + * * @author russell * */ From 8e007c885ff4c52a51fae50013e6b2956b6b1b99 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Fri, 6 May 2011 17:28:52 +0100 Subject: [PATCH 029/764] Change multipart boundary charset to iso8859_1 --- src/main/java/com/basho/riak/client/http/util/Multipart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/basho/riak/client/http/util/Multipart.java b/src/main/java/com/basho/riak/client/http/util/Multipart.java index 676ec74cf..13dd46283 100644 --- a/src/main/java/com/basho/riak/client/http/util/Multipart.java +++ b/src/main/java/com/basho/riak/client/http/util/Multipart.java @@ -89,7 +89,7 @@ public static List parse(Map headers, byte[] bod } String boundary = "\r\n--" + getBoundary(headers.get(Constants.HDR_CONTENT_TYPE)); - byte[] boundaryBytes = CharsetUtils.utf8StringToBytes(boundary); + byte[] boundaryBytes = CharsetUtils.asBytes(boundary, CharsetUtils.ISO_8859_1); int boundarySize = boundary.length(); if ("\r\n--".equals(boundary)) return null; From 88179571f1726faa721e9b03c9f617377fb5a42e Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Mon, 9 May 2011 09:00:42 +0100 Subject: [PATCH 030/764] Update comment with origin of code --- src/main/java/com/basho/riak/client/util/CharsetUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/basho/riak/client/util/CharsetUtils.java b/src/main/java/com/basho/riak/client/util/CharsetUtils.java index 5cfa5e446..c900df527 100644 --- a/src/main/java/com/basho/riak/client/util/CharsetUtils.java +++ b/src/main/java/com/basho/riak/client/util/CharsetUtils.java @@ -24,7 +24,7 @@ * Utils for dealing with byte[], String charset issues, especially since Java 5 * is less cool than Java 6 in this respect. * - * This code is all from the Trifork fork of the client and was written by + * This code is mainly from the Trifork fork of the client and was written by * Krestan Krab, Christian Hvitved and Erik Søe Sørensen. * * @author russell From 26c2e9bf127ea08e516416558a4a9a72a5524728 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Mon, 9 May 2011 13:31:58 +0100 Subject: [PATCH 031/764] Add unit tests for new utils Move BucketProperties builder into its own class file --- .../basho/riak/client/DefaultRiakClient.java | 30 +- .../bucket/DefaultBucketProperties.java | 320 ++++++++---------- .../basho/riak/client/bucket/WriteBucket.java | 4 +- .../builders/BucketPropertiesBuilder.java | 215 ++++++++++++ .../com/basho/riak/client/cap/Quorum.java | 38 +++ .../basho/riak/client/http/RiakClient.java | 12 - .../riak/client/raw/http/ConversionUtil.java | 4 +- .../riak/client/raw/pbc/ConversionUtil.java | 4 +- .../basho/riak/client/util/CharsetUtils.java | 34 +- .../riak/client/util/CharsetUtilsTest.java | 181 ++++++++++ .../client/util/UnmodifiableIteratorTest.java | 73 ++++ 11 files changed, 688 insertions(+), 227 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java create mode 100644 src/test/java/com/basho/riak/client/util/CharsetUtilsTest.java create mode 100644 src/test/java/com/basho/riak/client/util/UnmodifiableIteratorTest.java diff --git a/src/main/java/com/basho/riak/client/DefaultRiakClient.java b/src/main/java/com/basho/riak/client/DefaultRiakClient.java index a019dac9d..26fa8d417 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakClient.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakClient.java @@ -23,23 +23,23 @@ */ public final class DefaultRiakClient implements IRiakClient { - private final RawClient client; + private final RawClient rawClient; private final Retrier retrier; /** - * @param client + * @param rawClient * @param defaultRetrier */ - DefaultRiakClient(final RawClient client, final Retrier defaultRetrier) { - this.client = client; + DefaultRiakClient(final RawClient rawClient, final Retrier defaultRetrier) { + this.rawClient = rawClient; this.retrier = defaultRetrier; } /** * @param client */ - DefaultRiakClient(final RawClient client) { - this(client, new DefaultRetrier(3)); + DefaultRiakClient(final RawClient rawClient) { + this(rawClient, DefaultRetrier.attempts(3)); } // BUCKET OPS @@ -48,21 +48,21 @@ public final class DefaultRiakClient implements IRiakClient { * @see com.basho.riak.client.IRiakClient#updateBucket(com.basho.riak.client.bucket.Bucket) */ public WriteBucket updateBucket(final Bucket b) { - return new WriteBucket(client, b.getName(), retrier); + return new WriteBucket(rawClient, b.getName(), retrier); } /* (non-Javadoc) * @see com.basho.riak.client.IRiakClient#fetchBucket(java.lang.String) */ public FetchBucket fetchBucket(String bucketName) { - return new FetchBucket(client, bucketName, retrier); + return new FetchBucket(rawClient, bucketName, retrier); } /* (non-Javadoc) * @see com.basho.riak.client.IRiakClient#createBucket(java.lang.String) */ public WriteBucket createBucket(String bucketName) { - return new WriteBucket(client, bucketName, retrier); + return new WriteBucket(rawClient, bucketName, retrier); } // CLIENT ID @@ -77,7 +77,7 @@ public IRiakClient setClientId(final byte[] clientId) throws RiakException { final byte[] cloned = clientId.clone(); retrier.attempt(new Callable() { public Void call() throws Exception { - client.setClientId(cloned); + rawClient.setClientId(cloned); return null; } }); @@ -91,7 +91,7 @@ public Void call() throws Exception { public byte[] generateAndSetClientId() throws RiakException { final byte[] clientId = retrier.attempt(new Callable() { public byte[] call() throws Exception { - return client.generateAndSetClientId(); + return rawClient.generateAndSetClientId(); } }); @@ -104,7 +104,7 @@ public byte[] call() throws Exception { public byte[] getClientId() throws RiakException { final byte[] clientId = retrier.attempt(new Callable() { public byte[] call() throws Exception { - return client.getClientId(); + return rawClient.getClientId(); } }); @@ -117,7 +117,7 @@ public byte[] call() throws Exception { * @see com.basho.riak.client.IRiakClient#mapReduce() */ public BucketKeyMapReduce mapReduce() { - return new BucketKeyMapReduce(client); + return new BucketKeyMapReduce(rawClient); } /* @@ -126,7 +126,7 @@ public BucketKeyMapReduce mapReduce() { * @see com.basho.riak.newapi.RiakClient#mapReduce(java.lang.String) */ public BucketMapReduce mapReduce(String bucket) { - return new BucketMapReduce(client, bucket); + return new BucketMapReduce(rawClient, bucket); } /* @@ -134,6 +134,6 @@ public BucketMapReduce mapReduce(String bucket) { * @see com.basho.riak.client.IRiakClient#walk(com.basho.riak.client.IRiakObject) */ public LinkWalk walk(IRiakObject startObject) { - return new LinkWalk(client, startObject); + return new LinkWalk(rawClient, startObject); } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java index e8be0b56d..4119a0e14 100644 --- a/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java @@ -13,10 +13,9 @@ */ package com.basho.riak.client.bucket; -import java.util.ArrayList; import java.util.Collection; -import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.builders.BucketPropertiesBuilder; import com.basho.riak.client.cap.Quorum; import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.query.functions.NamedFunction; @@ -65,7 +64,7 @@ public class DefaultBucketProperties implements BucketProperties { * @param chashKeyFunction * @param linkWalkFunction */ - private DefaultBucketProperties(Builder builder) { + public DefaultBucketProperties(final BucketPropertiesBuilder builder) { this.allowSiblings = builder.allowSiblings; this.lastWriteWins = builder.lastWriteWins; this.nVal = builder.nVal; @@ -208,7 +207,7 @@ public NamedErlangFunction getLinkWalkFunction() { * * @return a Builder populated from this BucketProperties' values. */ - public DefaultBucketProperties.Builder fromMe() { + public BucketPropertiesBuilder fromMe() { return DefaultBucketProperties.from(this); } @@ -217,212 +216,161 @@ public DefaultBucketProperties.Builder fromMe() { * @param properties * @return a Builder populated with properties values. */ - public static DefaultBucketProperties.Builder from(DefaultBucketProperties properties) { - return DefaultBucketProperties.Builder.from(properties); + public static BucketPropertiesBuilder from(DefaultBucketProperties properties) { + return BucketPropertiesBuilder.from(properties); } - /** - * Use to create instances of BucketProperties. - * - * @author russell - * + /* (non-Javadoc) + * @see java.lang.Object#hashCode() */ - public static final class Builder { - - public NamedErlangFunction linkWalkFunction; - public NamedErlangFunction chashKeyFunction; - public Quorum rw; - public Quorum dw; - public Quorum w; - public Quorum r; - public Collection postcommitHooks = new ArrayList(); - public Collection precommitHooks = new ArrayList(); - public Long oldVClock; - public Long youngVClock; - public Integer bigVClock; - public Integer smallVClock; - public String backend; - public int nVal = 3; - public Boolean lastWriteWins; - public boolean allowSiblings = false; - - public BucketProperties build() { - return new DefaultBucketProperties(this); - } - - /** - * @param p - * the BucketProperties to copy to the builder - * @return a builder with all values set from p - */ - public static Builder from(DefaultBucketProperties p) { - Builder b = new Builder(); - b.allowSiblings = p.getAllowSiblings(); - b.lastWriteWins = p.getLastWriteWins(); - b.nVal = p.getNVal(); - b.backend = p.getBackend(); - b.smallVClock = p.getSmallVClock(); - b.bigVClock = p.getBigVClock(); - b.youngVClock = p.getYoungVClock(); - b.oldVClock = p.getOldVClock(); - b.postcommitHooks.addAll(p.getPostcommitHooks()); - b.precommitHooks.addAll(p.getPrecommitHooks()); - b.r = p.getR(); - b.w = p.getW(); - b.dw = p.getDW(); - b.rw = p.getRW(); - b.chashKeyFunction = p.getChashKeyFunction(); - b.linkWalkFunction = p.getLinkWalkFunction(); - return b; - } - - public Builder allowSiblings(boolean allowSiblings) { - this.allowSiblings = allowSiblings; - return this; - } - - public Builder lastWriteWins(boolean lastWriteWins) { - this.lastWriteWins = lastWriteWins; - return this; - } + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((allowSiblings == null) ? 0 : allowSiblings.hashCode()); + result = prime * result + ((backend == null) ? 0 : backend.hashCode()); + result = prime * result + ((bigVClock == null) ? 0 : bigVClock.hashCode()); + result = prime * result + ((chashKeyFunction == null) ? 0 : chashKeyFunction.hashCode()); + result = prime * result + ((dw == null) ? 0 : dw.hashCode()); + result = prime * result + ((lastWriteWins == null) ? 0 : lastWriteWins.hashCode()); + result = prime * result + ((linkWalkFunction == null) ? 0 : linkWalkFunction.hashCode()); + result = prime * result + ((nVal == null) ? 0 : nVal.hashCode()); + result = prime * result + ((oldVClock == null) ? 0 : oldVClock.hashCode()); + result = prime * result + ((postcommitHooks == null) ? 0 : postcommitHooks.hashCode()); + result = prime * result + ((precommitHooks == null) ? 0 : precommitHooks.hashCode()); + result = prime * result + ((r == null) ? 0 : r.hashCode()); + result = prime * result + ((rw == null) ? 0 : rw.hashCode()); + result = prime * result + ((smallVClock == null) ? 0 : smallVClock.hashCode()); + result = prime * result + ((w == null) ? 0 : w.hashCode()); + result = prime * result + ((youngVClock == null) ? 0 : youngVClock.hashCode()); + return result; + } - public Builder nVal(int nVal) { - this.nVal = nVal; - return this; + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; } - - public Builder backend(String backend) { - this.backend = backend; - return this; + if (obj == null) { + return false; } - - public Builder precommitHooks(Collection precommitHooks) { - this.precommitHooks = new ArrayList(precommitHooks); - return this; + if (!(obj instanceof DefaultBucketProperties)) { + return false; } - - public Builder addPrecommitHook(NamedFunction preCommitHook) { - if (this.precommitHooks == null) { - this.precommitHooks = new ArrayList(); + DefaultBucketProperties other = (DefaultBucketProperties) obj; + if (allowSiblings == null) { + if (other.allowSiblings != null) { + return false; } - this.precommitHooks.add(preCommitHook); - return this; - } - - public Builder postcommitHooks(Collection postCommitHooks) { - this.postcommitHooks = new ArrayList(postCommitHooks); - return this; + } else if (!allowSiblings.equals(other.allowSiblings)) { + return false; } - - public Builder addPostcommitHook(NamedErlangFunction postcommitHook) { - if (this.postcommitHooks == null) { - this.postcommitHooks = new ArrayList(); + if (backend == null) { + if (other.backend != null) { + return false; } - this.precommitHooks.add(postcommitHook); - return this; + } else if (!backend.equals(other.backend)) { + return false; } - - public Builder chashKeyFunction(NamedErlangFunction chashKeyFunction) { - this.chashKeyFunction = chashKeyFunction; - return this; + if (bigVClock == null) { + if (other.bigVClock != null) { + return false; + } + } else if (!bigVClock.equals(other.bigVClock)) { + return false; } - - public Builder linkWalkFunction(NamedErlangFunction linkWalkFunction) { - this.linkWalkFunction = linkWalkFunction; - return this; + if (chashKeyFunction == null) { + if (other.chashKeyFunction != null) { + return false; + } + } else if (!chashKeyFunction.equals(other.chashKeyFunction)) { + return false; } - - /** - * @param smallVClock - * @return - */ - public Builder smallVClock(int smallVClock) { - this.smallVClock = smallVClock; - return this; + if (dw == null) { + if (other.dw != null) { + return false; + } + } else if (!dw.equals(other.dw)) { + return false; } - - /** - * @param bigVClock - * @return - */ - public Builder bigVClock(int bigVClock) { - this.bigVClock = bigVClock; - return this; + if (lastWriteWins == null) { + if (other.lastWriteWins != null) { + return false; + } + } else if (!lastWriteWins.equals(other.lastWriteWins)) { + return false; } - - /** - * @param youngVClock - * @return - */ - public Builder youngVClock(long youngVClock) { - this.youngVClock = youngVClock; - return this; + if (linkWalkFunction == null) { + if (other.linkWalkFunction != null) { + return false; + } + } else if (!linkWalkFunction.equals(other.linkWalkFunction)) { + return false; } - - /** - * @param oldVClock - * @return - */ - public Builder oldVClock(long oldVClock) { - this.oldVClock = oldVClock; - return this; + if (nVal == null) { + if (other.nVal != null) { + return false; + } + } else if (!nVal.equals(other.nVal)) { + return false; } - - /** - * @param r - * @return - */ - public Builder r(Quora r) { - this.r = new Quorum(r); - return this; + if (oldVClock == null) { + if (other.oldVClock != null) { + return false; + } + } else if (!oldVClock.equals(other.oldVClock)) { + return false; } - - public Builder r(int r) { - this.r = new Quorum(r); - return this; + if (postcommitHooks == null) { + if (other.postcommitHooks != null) { + return false; + } + } else if (!postcommitHooks.equals(other.postcommitHooks)) { + return false; } - - /** - * @param w - * @return - */ - public Builder w(Quora w) { - this.w = new Quorum(w); - return this; + if (precommitHooks == null) { + if (other.precommitHooks != null) { + return false; + } + } else if (!precommitHooks.equals(other.precommitHooks)) { + return false; } - - public Builder w(int w) { - this.w = new Quorum(w); - return this; + if (r == null) { + if (other.r != null) { + return false; + } + } else if (!r.equals(other.r)) { + return false; } - - /** - * @param rw - * @return - */ - public Builder rw(Quora rw) { - this.rw = new Quorum(rw); - return this; + if (rw == null) { + if (other.rw != null) { + return false; + } + } else if (!rw.equals(other.rw)) { + return false; } - - public Builder rw(int rw) { - this.rw = new Quorum(rw); - return this; + if (smallVClock == null) { + if (other.smallVClock != null) { + return false; + } + } else if (!smallVClock.equals(other.smallVClock)) { + return false; } - - /** - * @param dw - * @return - */ - public Builder dw(Quora dw) { - this.dw = new Quorum(dw); - return this; + if (w == null) { + if (other.w != null) { + return false; + } + } else if (!w.equals(other.w)) { + return false; } - - public Builder dw(int dw) { - this.dw = new Quorum(dw); - return this; + if (youngVClock == null) { + if (other.youngVClock != null) { + return false; + } + } else if (!youngVClock.equals(other.youngVClock)) { + return false; } - + return true; } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java index 88f1ff80d..64baabb76 100644 --- a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java @@ -17,6 +17,7 @@ import java.util.concurrent.Callable; import com.basho.riak.client.RiakRetryFailedException; +import com.basho.riak.client.builders.BucketPropertiesBuilder; import com.basho.riak.client.cap.Quora; import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.operations.RiakOperation; @@ -34,7 +35,7 @@ public class WriteBucket implements RiakOperation { private Retrier retrier; private String name; - private DefaultBucketProperties.Builder builder = new DefaultBucketProperties.Builder(); + private BucketPropertiesBuilder builder = new BucketPropertiesBuilder(); public WriteBucket(final RawClient client, String name, final Retrier retrier) { this.name = name; @@ -187,5 +188,4 @@ public WriteBucket retrier(final Retrier retrier) { this.retrier = retrier; return this; } - } diff --git a/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java b/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java new file mode 100644 index 000000000..cde3a10e2 --- /dev/null +++ b/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java @@ -0,0 +1,215 @@ +package com.basho.riak.client.builders; + +import java.util.ArrayList; +import java.util.Collection; + +import com.basho.riak.client.bucket.BucketProperties; +import com.basho.riak.client.bucket.DefaultBucketProperties; +import com.basho.riak.client.cap.Quora; +import com.basho.riak.client.cap.Quorum; +import com.basho.riak.client.query.functions.NamedErlangFunction; +import com.basho.riak.client.query.functions.NamedFunction; + +/** + * Use to create instances of BucketProperties. + * + * @author russell + * + */ +public final class BucketPropertiesBuilder { + + public NamedErlangFunction linkWalkFunction; + public NamedErlangFunction chashKeyFunction; + public Quorum rw; + public Quorum dw; + public Quorum w; + public Quorum r; + public Collection postcommitHooks = new ArrayList(); + public Collection precommitHooks = new ArrayList(); + public Long oldVClock; + public Long youngVClock; + public Integer bigVClock; + public Integer smallVClock; + public String backend; + public int nVal = 3; + public Boolean lastWriteWins; + public boolean allowSiblings = false; + + public BucketProperties build() { + return new DefaultBucketProperties(this); + } + + /** + * @param p + * the BucketProperties to copy to the builder + * @return a builder with all values set from p + */ + public static BucketPropertiesBuilder from(DefaultBucketProperties p) { + BucketPropertiesBuilder b = new BucketPropertiesBuilder(); + b.allowSiblings = p.getAllowSiblings(); + b.lastWriteWins = p.getLastWriteWins(); + b.nVal = p.getNVal(); + b.backend = p.getBackend(); + b.smallVClock = p.getSmallVClock(); + b.bigVClock = p.getBigVClock(); + b.youngVClock = p.getYoungVClock(); + b.oldVClock = p.getOldVClock(); + b.postcommitHooks.addAll(p.getPostcommitHooks()); + b.precommitHooks.addAll(p.getPrecommitHooks()); + b.r = p.getR(); + b.w = p.getW(); + b.dw = p.getDW(); + b.rw = p.getRW(); + b.chashKeyFunction = p.getChashKeyFunction(); + b.linkWalkFunction = p.getLinkWalkFunction(); + return b; + } + + public BucketPropertiesBuilder allowSiblings(boolean allowSiblings) { + this.allowSiblings = allowSiblings; + return this; + } + + public BucketPropertiesBuilder lastWriteWins(boolean lastWriteWins) { + this.lastWriteWins = lastWriteWins; + return this; + } + + public BucketPropertiesBuilder nVal(int nVal) { + this.nVal = nVal; + return this; + } + + public BucketPropertiesBuilder backend(String backend) { + this.backend = backend; + return this; + } + + public BucketPropertiesBuilder precommitHooks(Collection precommitHooks) { + this.precommitHooks = new ArrayList(precommitHooks); + return this; + } + + public BucketPropertiesBuilder addPrecommitHook(NamedFunction preCommitHook) { + if (this.precommitHooks == null) { + this.precommitHooks = new ArrayList(); + } + this.precommitHooks.add(preCommitHook); + return this; + } + + public BucketPropertiesBuilder postcommitHooks(Collection postCommitHooks) { + this.postcommitHooks = new ArrayList(postCommitHooks); + return this; + } + + public BucketPropertiesBuilder addPostcommitHook(NamedErlangFunction postcommitHook) { + if (this.postcommitHooks == null) { + this.postcommitHooks = new ArrayList(); + } + this.precommitHooks.add(postcommitHook); + return this; + } + + public BucketPropertiesBuilder chashKeyFunction(NamedErlangFunction chashKeyFunction) { + this.chashKeyFunction = chashKeyFunction; + return this; + } + + public BucketPropertiesBuilder linkWalkFunction(NamedErlangFunction linkWalkFunction) { + this.linkWalkFunction = linkWalkFunction; + return this; + } + + /** + * @param smallVClock + * @return + */ + public BucketPropertiesBuilder smallVClock(int smallVClock) { + this.smallVClock = smallVClock; + return this; + } + + /** + * @param bigVClock + * @return + */ + public BucketPropertiesBuilder bigVClock(int bigVClock) { + this.bigVClock = bigVClock; + return this; + } + + /** + * @param youngVClock + * @return + */ + public BucketPropertiesBuilder youngVClock(long youngVClock) { + this.youngVClock = youngVClock; + return this; + } + + /** + * @param oldVClock + * @return + */ + public BucketPropertiesBuilder oldVClock(long oldVClock) { + this.oldVClock = oldVClock; + return this; + } + + /** + * @param r + * @return + */ + public BucketPropertiesBuilder r(Quora r) { + this.r = new Quorum(r); + return this; + } + + public BucketPropertiesBuilder r(int r) { + this.r = new Quorum(r); + return this; + } + + /** + * @param w + * @return + */ + public BucketPropertiesBuilder w(Quora w) { + this.w = new Quorum(w); + return this; + } + + public BucketPropertiesBuilder w(int w) { + this.w = new Quorum(w); + return this; + } + + /** + * @param rw + * @return + */ + public BucketPropertiesBuilder rw(Quora rw) { + this.rw = new Quorum(rw); + return this; + } + + public BucketPropertiesBuilder rw(int rw) { + this.rw = new Quorum(rw); + return this; + } + + /** + * @param dw + * @return + */ + public BucketPropertiesBuilder dw(Quora dw) { + this.dw = new Quorum(dw); + return this; + } + + public BucketPropertiesBuilder dw(int dw) { + this.dw = new Quorum(dw); + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/cap/Quorum.java b/src/main/java/com/basho/riak/client/cap/Quorum.java index add1e3680..c3b84aac0 100644 --- a/src/main/java/com/basho/riak/client/cap/Quorum.java +++ b/src/main/java/com/basho/riak/client/cap/Quorum.java @@ -29,4 +29,42 @@ public Quorum(int i) { public Quorum(Quora quorum) { this.quorum = quorum; } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((i == null) ? 0 : i.hashCode()); + result = prime * result + ((quorum == null) ? 0 : quorum.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Quorum)) { + return false; + } + Quorum other = (Quorum) obj; + if (i == null) { + if (other.i != null) { + return false; + } + } else if (!i.equals(other.i)) { + return false; + } + if (quorum != other.quorum) { + return false; + } + return true; + } } \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/http/RiakClient.java b/src/main/java/com/basho/riak/client/http/RiakClient.java index 47e925ecd..fa80dcfaa 100644 --- a/src/main/java/com/basho/riak/client/http/RiakClient.java +++ b/src/main/java/com/basho/riak/client/http/RiakClient.java @@ -227,30 +227,18 @@ public FetchResponse fetchMeta(String bucket, String key) { return fetchMeta(bucket, key, null); } - /* (non-Javadoc) - * @see com.basho.riak.client.HttpRiakClient#fetch(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) - */ public FetchResponse fetch(String bucket, String key, RequestMeta meta) { return fetch(bucket, key, meta, false); } - /* (non-Javadoc) - * @see com.basho.riak.client.HttpRiakClient#fetch(java.lang.String, java.lang.String) - */ public FetchResponse fetch(String bucket, String key) { return fetch(bucket, key, null, false); } - /* (non-Javadoc) - * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String, com.basho.riak.client.request.RequestMeta) - */ public FetchResponse stream(String bucket, String key, RequestMeta meta) { return fetch(bucket, key, meta, true); } - /* (non-Javadoc) - * @see com.basho.riak.client.HttpRiakClient#stream(java.lang.String, java.lang.String) - */ public FetchResponse stream(String bucket, String key) { return fetch(bucket, key, null, true); } diff --git a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java index 0be1e6de2..29b0e815d 100644 --- a/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/http/ConversionUtil.java @@ -31,7 +31,7 @@ import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakLink; import com.basho.riak.client.bucket.BucketProperties; -import com.basho.riak.client.bucket.DefaultBucketProperties; +import com.basho.riak.client.builders.BucketPropertiesBuilder; import com.basho.riak.client.builders.RiakObjectBuilder; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.http.RiakBucketInfo; @@ -214,7 +214,7 @@ static com.basho.riak.client.http.RiakLink convert(RiakLink link) { */ static BucketProperties convert(BucketResponse response) { RiakBucketInfo bucketInfo = response.getBucketInfo(); - return new DefaultBucketProperties.Builder() + return new BucketPropertiesBuilder() .allowSiblings(bucketInfo.getAllowMult()) .nVal(bucketInfo.getNVal()) .chashKeyFunction(convert(bucketInfo.getCHashFun())) diff --git a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java index 7dddbd023..600867c16 100644 --- a/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java +++ b/src/main/java/com/basho/riak/client/raw/pbc/ConversionUtil.java @@ -33,7 +33,7 @@ import com.basho.riak.client.IRiakObject; import com.basho.riak.client.bucket.BucketProperties; -import com.basho.riak.client.bucket.DefaultBucketProperties; +import com.basho.riak.client.builders.BucketPropertiesBuilder; import com.basho.riak.client.builders.RiakObjectBuilder; import com.basho.riak.client.cap.VClock; import com.basho.riak.client.convert.ConversionException; @@ -191,7 +191,7 @@ static com.basho.riak.pbc.BucketProperties convert(BucketProperties p) { * @return */ static BucketProperties convert(com.basho.riak.pbc.BucketProperties properties) { - return new DefaultBucketProperties.Builder().allowSiblings(properties.getAllowMult()).nVal(properties.getNValue()).build(); + return new BucketPropertiesBuilder().allowSiblings(properties.getAllowMult()).nVal(properties.getNValue()).build(); } /** diff --git a/src/main/java/com/basho/riak/client/util/CharsetUtils.java b/src/main/java/com/basho/riak/client/util/CharsetUtils.java index c900df527..5db2c039a 100644 --- a/src/main/java/com/basho/riak/client/util/CharsetUtils.java +++ b/src/main/java/com/basho/riak/client/util/CharsetUtils.java @@ -14,7 +14,6 @@ package com.basho.riak.client.util; import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Map; import java.util.regex.Matcher; @@ -25,7 +24,7 @@ * is less cool than Java 6 in this respect. * * This code is mainly from the Trifork fork of the client and was written by - * Krestan Krab, Christian Hvitved and Erik Søe Sørensen. + * Krestan Krab and/or Erik Søe Sørensen. * * @author russell * @@ -36,6 +35,9 @@ public class CharsetUtils { public static Charset UTF_8 = Charset.forName("UTF-8"); public static Charset getCharset(Map headers) { + if(headers == null) { + return ISO_8859_1; + } return getCharset(headers.get(com.basho.riak.client.http.util.Constants.HDR_CONTENT_TYPE)); } @@ -102,7 +104,19 @@ public static String addUtf8Charset(String contentType) { * @return a String */ public static String asString(byte[] bytes, Charset charset) { - return charset.decode(ByteBuffer.wrap(bytes)).toString(); + if(bytes == null) { + return null; + } + + if(charset == null) { + throw new IllegalArgumentException("Cannot get bytes without a Charset"); + } + + try { + return new String(bytes, charset.name()); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(charset.name() + " must be present", e); + } } /** @@ -112,11 +126,7 @@ public static String asString(byte[] bytes, Charset charset) { * @return a String */ public static String asUTF8String(byte[] bytes) { - try { - return new String(bytes, UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("UTF8 must be present", e); - } + return asString(bytes, UTF_8); } /** @@ -126,6 +136,14 @@ public static String asUTF8String(byte[] bytes) { * @return a byte[] array */ public static byte[] asBytes(String string, Charset charset) { + if(string == null) { + return null; + } + + if(charset == null) { + throw new IllegalArgumentException("Cannot get bytes without a Charset"); + } + try { return string.getBytes(charset.name()); } catch (UnsupportedEncodingException e) { diff --git a/src/test/java/com/basho/riak/client/util/CharsetUtilsTest.java b/src/test/java/com/basho/riak/client/util/CharsetUtilsTest.java new file mode 100644 index 000000000..7cd0b830d --- /dev/null +++ b/src/test/java/com/basho/riak/client/util/CharsetUtilsTest.java @@ -0,0 +1,181 @@ +/* + * This file is provided 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.basho.riak.client.util; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.basho.riak.client.http.util.Constants; + +/** + * @author russell + * + */ +public class CharsetUtilsTest { + + /** + * @throws java.lang.Exception + */ + @Before public void setUp() throws Exception {} + + /** + * @throws java.lang.Exception + */ + @After public void tearDown() throws Exception {} + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#getCharset(java.util.Map)} + * . + */ + @Test public void getCharsetFromHeaders() { + final Map headers = new HashMap(); + headers.put(Constants.HDR_CONTENT_TYPE, Constants.CTYPE_JSON_UTF8); + assertEquals(Charset.forName("UTF-8"), CharsetUtils.getCharset(headers)); + + headers.put(Constants.HDR_CONTENT_TYPE, "utter_tripe"); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset(headers)); + + headers.put(Constants.HDR_CONTENT_TYPE, null); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset(headers)); + + headers.remove(Constants.HDR_CONTENT_TYPE); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset(headers)); + + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset((Map) null)); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#getCharset(java.lang.String)} + * . + */ + @Test public void getCharsetFromContentType() { + assertEquals(Charset.forName("UTF-8"), CharsetUtils.getCharset(Constants.CTYPE_TEXT_UTF8)); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset("text/plain;charset=NotACharSet")); + assertEquals(Charset.forName("UTF-16"), CharsetUtils.getCharset("text/plain;charset=UTF-16")); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset("gibberish")); + assertEquals(Charset.forName("ISO8859_1"), CharsetUtils.getCharset((String) null)); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#addUtf8Charset(java.lang.String)} + * . + */ + @Test public void addUTF8CharsetToContentType() { + assertTrue("Expceted UTF-8 charset to be added to content type", + Constants.CTYPE_JSON_UTF8.equalsIgnoreCase(CharsetUtils.addUtf8Charset(Constants.CTYPE_JSON))); + + // null gets a default + assertEquals("text/plain;charset=utf-8", CharsetUtils.addUtf8Charset(null)); + + // charset gets replaced + assertEquals("text/plain;charset=utf-8", CharsetUtils.addUtf8Charset("text/plain;charset=utf-16")); + + // nonsense is untouched + assertEquals("nonsense;charset=utf-8", CharsetUtils.addUtf8Charset("nonsense")); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#asBytes(java.lang.String, java.nio.charset.Charset)} + * . + */ + @Test public void stringToBytes() throws Exception { + String example = "example"; + byte[] b = example.getBytes("UTF-8"); + + assertArrayEquals(b, CharsetUtils.asBytes(example, Charset.forName("UTF-8"))); + + b = example.getBytes("UTF-16"); + assertArrayEquals(b, CharsetUtils.asBytes(example, Charset.forName("UTF-16"))); + + b = example.getBytes("ISO8859_1"); + assertArrayEquals(b, CharsetUtils.asBytes(example, Charset.forName("ISO8859_1"))); + + assertNull(CharsetUtils.asBytes(null, Charset.forName("UTf-8"))); + + try { + CharsetUtils.asBytes(example, null); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // NO-OP + } + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#utf8StringToBytes(java.lang.String)} + * . + */ + @Test public void utf8StringToBytes() throws Exception { + String example = "example"; + byte[] b = example.getBytes("UTF-8"); + + assertArrayEquals(b, CharsetUtils.utf8StringToBytes(example)); + assertNull(CharsetUtils.utf8StringToBytes(null)); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#asString(byte[], java.nio.charset.Charset)} + * . + */ + @Test public void bytesToString() throws Exception { + String example = "example"; + byte[] b = example.getBytes("UTF-8"); + + assertEquals(example,CharsetUtils.asString(b, Charset.forName("UTF-8"))); + + b = example.getBytes("UTF-16"); + assertEquals(example, CharsetUtils.asString(b, Charset.forName("UTF-16"))); + + b = example.getBytes("ISO8859_1"); + assertEquals(example, CharsetUtils.asString(b, Charset.forName("ISO8859_1"))); + + assertNull(CharsetUtils.asString(null, Charset.forName("UTf-8"))); + + try { + CharsetUtils.asString(b, null); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // NO-OP + } + } + + /** + * Test method for + * {@link com.basho.riak.client.util.CharsetUtils#asUTF8String(byte[])}. + */ + @Test public void bytesToUtf8String() throws Exception { + String example = "example"; + byte[] b = example.getBytes("UTF-8"); + + assertEquals(example, CharsetUtils.asUTF8String(b)); + assertNull(CharsetUtils.asUTF8String(null)); + } + +} diff --git a/src/test/java/com/basho/riak/client/util/UnmodifiableIteratorTest.java b/src/test/java/com/basho/riak/client/util/UnmodifiableIteratorTest.java new file mode 100644 index 000000000..5eefe6e4a --- /dev/null +++ b/src/test/java/com/basho/riak/client/util/UnmodifiableIteratorTest.java @@ -0,0 +1,73 @@ +/* + * This file is provided 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.basho.riak.client.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Iterator; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * @author russell + * + */ +public class UnmodifiableIteratorTest { + + @Mock private Iterator mockerator; + private UnmodifiableIterator iterator; + + /** + * @throws java.lang.Exception + */ + @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + iterator = new UnmodifiableIterator(mockerator); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.UnmodifiableIterator#hasNext()}. + */ + @Test public void testHasNext() { + when(mockerator.hasNext()).thenReturn(true); + assertTrue(iterator.hasNext()); + verify(mockerator, times(1)).hasNext(); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.UnmodifiableIterator#next()}. + */ + @Test public void testNext() { + when(mockerator.next()).thenReturn("eggs"); + assertEquals("eggs", iterator.next()); + verify(mockerator, times(1)).next(); + } + + /** + * Test method for + * {@link com.basho.riak.client.util.UnmodifiableIterator#remove()}. + */ + @Test(expected = UnsupportedOperationException.class) public void testRemove() { + iterator.remove(); + } +} From 9fff82f0ce232024f44739c98081df512de9bf0f Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 08:08:29 +0100 Subject: [PATCH 032/764] Add convenience setVlaue(String) to IRiakObject --- .../java/com/basho/riak/client/DefaultRiakObject.java | 9 ++++++++- src/main/java/com/basho/riak/client/IRiakObject.java | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/basho/riak/client/DefaultRiakObject.java b/src/main/java/com/basho/riak/client/DefaultRiakObject.java index 0b9b53605..a7ea1f049 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakObject.java @@ -176,6 +176,14 @@ public void setValue(byte[] value) { this.value = copy(value); } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#setValue(java.lang.String) + */ + public void setValue(String value) { + this.value = CharsetUtils.utf8StringToBytes(value); + this.contentType = CharsetUtils.addUtf8Charset(contentType); + } + public void setContentType(String contentType) { this.contentType = contentType; } @@ -346,5 +354,4 @@ public String getVClockAsString() { public String getValueAsString() { return CharsetUtils.asString(value, CharsetUtils.getCharset(contentType)); } - } diff --git a/src/main/java/com/basho/riak/client/IRiakObject.java b/src/main/java/com/basho/riak/client/IRiakObject.java index fd47f73ce..34a411bc4 100644 --- a/src/main/java/com/basho/riak/client/IRiakObject.java +++ b/src/main/java/com/basho/riak/client/IRiakObject.java @@ -73,6 +73,15 @@ public interface IRiakObject extends Iterable { void setValue(byte[] value); + /** + * Convenience method that basically will result in + * value being turned into a byte[] array using charset utf-8 and also + * will result in charset=utf-8 being appended to the content-type for this object + * + * @param value the String value + */ + void setValue(String value); + void setContentType(String contentType); /** From 5e7874394beb159993c73f87a0b616d137059bf2 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 08:09:08 +0100 Subject: [PATCH 033/764] Daemonise and name KeySource timer thread --- src/main/java/com/basho/riak/client/raw/http/KeySource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/basho/riak/client/raw/http/KeySource.java b/src/main/java/com/basho/riak/client/raw/http/KeySource.java index 272fecc31..a7d3501e7 100644 --- a/src/main/java/com/basho/riak/client/raw/http/KeySource.java +++ b/src/main/java/com/basho/riak/client/raw/http/KeySource.java @@ -29,7 +29,7 @@ */ public class KeySource implements Iterator { - private static final Timer timer = new Timer(); + private static final Timer timer = new Timer("riak-client-key-stream-timeout-thread", true); private final BucketResponse bucketResponse; private final Iterator keys; private ReaperTask reaper; From 6d3236e7cac1616a5d125b7767f3264badff7dce Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 10:14:19 +0100 Subject: [PATCH 034/764] Add new README.org Update TODO Move (but retain) old README.md --- README.md => HTTP_README.md | 0 README.org | 595 +++++++++++++++++++++++++++--------- TODO | 44 ++- 3 files changed, 494 insertions(+), 145 deletions(-) rename README.md => HTTP_README.md (100%) diff --git a/README.md b/HTTP_README.md similarity index 100% rename from README.md rename to HTTP_README.md diff --git a/README.org b/README.org index ff65bc780..debf4a959 100644 --- a/README.org +++ b/README.org @@ -1,196 +1,505 @@ -* A New Riak Java Client API +This document describes how to use the Java client to interact with Riak. See the +[[https://github.com/basho/riak-java-client/blob/master/DEVELOPERS.md][DEVELOPERS]] document for a technical overview of the project. -** What's wrong? +* Overview +Riak is a dynamo style, distributed key-value store that provides a [[http://wiki.basho.com/MapReduce.html][map reduce]] +query interface. It exposes both a [[http://wiki.basho.com/REST-API.html][REST]] and [[http://wiki.basho.com/PBC-API.html][protocol buffers]] API. This +is a Java client for talking to Riak via a single interface, regardless of +underlying transport. This library also attempts to simplify some of the +realities of dealing with a fault-tolerant, eventually consistent database by +providing strategies for: -Accusations have been made against the current riak-java-client. Certainly it -leaks implementation details (Apache HttpClient, JSONArray, JSONObject, -ByteString etc) into client code. And there are 3 different possible client -interfaces: +- Conflict resolution +- Retrying requests +- Value mutation -+ An Http style client -+ A more OO client that uses the Http client -+ A protocol buffers client +The client also provides some lightweight ORM like capability for storing domain +objects in Riak and returning domain objects from map reduce queries. -All of these leak their abstractions and force the user to make an upfront -choice about transport/features and then code to that decision. +* Using riak-java-client +** Including riak-java-client in your project +Riak-java-client is available from maven central. Add the dependency to your pom.xml -Some people don't like Apache HttpClient, and that is fair enough, so it would -be ideal if we didn't force it on those people. Better yet make it easy to -create new implementations for the transport (using Netty or RestTemplate or -what-have-you). -More than that, though, it doesn't make it any easier to work with a fault -tolerant, distributed KV store (like Riak). + + com.basho.riak + riak-client + 0.15.0 + pom + -** What's new? -Well it *is* Java, so I added some more layers. +To build and install from source, first install [[http://maven.apache.org/download.html][Apache Maven]]. With Maven installed, run: + + mvn clean install + +** Quick start +Assuming you're running Riak on localhost on the default ports getting started is as simple as: -*** New boss, same as the old boss + // create a client + IRiakClient riakClient = RiakFactory.pbcClient(); //or RiakFactory.httpClient(); -Underneath is the same HTTP RiakClient and pbc.RiakClient that you know and -love. They have a couple more fixes and an accessor or two but fundamentally -uncchanged. + // create a new bucket + Bucket myBucket = riakClient.createBucket("myBucket").execute(); -*** Wrapper + // add data to the bucket + myBucket.store("key1", "value1").execute(); -There's a new interface, that is currently called RawClient, and two adapters -that wrap the existing clients and adapt them to the new API. So if all you -want is to write code against a low level client then use the RawClient -interface and you don't have to chose upfront HTTP or PBC anymore. And if you -want to add your own Netty client, or Spring REST Template, then implement this -interface, please. + //fetch it back + IRiakObject myData = myBucket.fetch("key1").execute(); -*** Riak, Buckets, Objects + // you can specify extra parameters to the store operation using the + // fluid builder style API + myData = myBucket.store("key1", "value2").returnBody(true).execute(); -On top of the RawClient there is a higher level API that attempts to make it -easier to deal with eventual consitency. All the ideas for this layer came from -the Coda Hale's talk [[http://blog.basho.com/2011/03/28/Riak-and-Scala-at-Yammer/][Riak and Scala at Yammer]] and a subsequent email -conversation he was kind enough to have with me. And also from [[http://lists.basho.com/pipermail/riak-users_lists.basho.com/2011-March/003662.html][this post]] to the -Riak mailing list from Kresten Krab Thorup. Not that they are in anyway to blame -for all this. + // delete + myBucket.delete("key1").rw(3).execute(); -**** Simpler client +** Some History +This riak-java-client API is new. Prior to this version there were two separate +clients, one for protocol buffers, one for REST, both in the same library and +both with quite different APIs. -The high level Riak client lets you work with buckets and map reduce. The map -reduce/link walking stuff is incomplete so I'll skip that (for now). +*** Deprecated +The REST client (which you can still use directly) has been moved to -Have a look at -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestClientBasic.java][ITestClientBasic]] -and -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/RiakClient.java][RiakClient]]. -All Riak access to a riak objects is done through the Bucket interface, the -client just creates/updates and fetches buckets. + com.basho.riak.client.http.RiakClient -**** Buckets +Though a deprecated RiakClient still exists at -A test is worth a 100 words so have a look at -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestBucket.java][ITestBucket]] -and the interface -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/bucket/Bucket.java][Bucket]] -Bucket methods return -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/operations/RiakOperation.java][RiakOperation's]] -which are implemented as fluent builders to save the proliferation of methods -that occur when you have a lot of optional arguments. + com.basho.riak.client.RiakClient -**** Riak Opertaions +for another release or two to ease transition. All the REST client's HTTP +specific classes have been moved to -A RiakOpertaion is configured and then it is executed. This is how to fetch, -store or delete data. It can be configured to be retried N times. By default -that N is 0 (IE try once and fail at once.) An operation accepts the parameters -it needs. So a [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/operations/DeleteObject.java][Delete Operation]] accepts an optional RW param, for example. + com.basho.riak.client.http.* -**** Conflict resolution, Mutation and Converstion +and the originals retained *but deprecated*. If you want to use the legacy, +low-level client directly please use the newly packaged version. The +deprecated classes will be deleted in the next or following release to +clean up the namespaces. -***** Conflict +At that time IRiak* will become Riak* and any I* names will be +deprecated then dropped. I'm sorry about the unpleasant naming +conventions in the short term. +** What's new? +*** Builders +To avoid the profusion of constructors and setters there is a builder + + com.basho.riak.client.builders.RiakObjectBuilder + +to simplify creating and updating IRiakObjects. + +In fact most classes are as immutable as possible and are created +using fluid builders. The builders are *not* designed to be used +across multiple threads but the immutable value objects they create are. + +*** Layers +**** Low +There is a low-level interface, RawClient + + com.basho.riak.client.raw.RawClient + +and two adapters that adapt the legacy protocol buffers and REST clients to the +RawClient interface. RawClient provides access to Riak's APIs. If you don't want +any of the higher level features to deal with domain objects, eventual +consistency and fault tolerance (see below) then at least +use RawClient over the underlying legacy clients so your code will not need to +change if you decide to move from REST to protocol buffers or +back. For example: + + RiakClient pbcClient = new RiakClient("127.0.0.1"); + // OR + // com.basho.riak.client.http.RiakClient httpClient = new + // com.basho.riak.client.http.RiakClient("http://127.0.0.1:8098/riak"); + RawClient rawClient = new PBClientAdapter(pbcClient); + // OR new HTTPClientAdapter(httpClient); + + IRiakObject riakObject = RiakObjectBuilder.newBuilder(bucketName, "key1").withValue("value1").build(); + rawClient.store(riakObject, new StoreMeta(2, 1, false)); + RiakResponse fetched = rawClient.fetch(bucketName, "key1"); + IRiakObject result = null; + + if(fetched.hasValue()) { + if(fetched.hasSiblings()) { + //do what you must to resolve conflicts + } else { + result = fetched.getRiakObjects()[0]; + } + } + + result.addLink(new RiakLink("otherBucket", "otherKey", "tag")); + result.setValue("newValue"); + + RiakResponse stored = rawClient.store(result, new StoreMeta(2, 1, true)); + + IRiakObject updated = null; + + if(stored.hasValue()) { + if(stored.hasSiblings()) { + //do what you must to resolve conflicts + } else { + updated = stored.getRiakObjects()[0]; + } + } + + rawClient.delete(bucketName, "key1"); + + +If *you* want to add a client transport to Riak (say you hate Apache HTTP client +but love Netty) implementing RawClient is the way to do it. + +**** High +All the code so far elides somes rather important details: + + // handle conflict here + +If your bucket allows siblings at some point you may have to deal with +conflict. Likewise, if you are running in the real world you may have to deal +with temporary failure. + +The higher level API (built on top of RawClient) gives +you some tools to deal with eventual consistency and temporary failure. + +***** Operations +Talking to Riak is modelled as a set of operations. An operation is +a fluid builder for setting operation parameters (like the tunable CAP +quorum for a read) and an execute method to carry out the operation. EG + + Bucket b = client.createBucket(bucketName) + .nVal(1) + .allowSiblings(true) + .execute(); + +or + + b.store("k", "v").w(2).dw(1).returnBody(false).execute(); + +All the operations implement RiakOperation, which has a single method: + + T execute() throws RiakException; + +***** Retry +Each operation needs a Retrier. You can specify a default retrier +implementation when you create an IRiakClient or you can provide one +to each operation when you build it. There is a simple retrier +provided with this library that retries the given operation *n* times +before throwing an exception. + + b.store("k", "v").retrier(DefaultRetrier.attempts(3)).execute(); + +The DefaultRiakClient implementation provides a 3 times retrier to all it's +operations. You can override this from the constructor or +provide your own per operation (or per bucket, see below). The Retrier interface +accepts Callable for its "attempt" method. Internally, operations are +built around that interface. + + public interface Retrier { + T attempt(Callable command) throws RiakRetryFailedException; + } + +***** Buckets +To simplify the Riak client all value related operations are performed via the +Bucket interface. The Bucket also provides access to the set of bucket +properties (nval, allow_mult etc). + +NOTE: at present not all bucket properties are exposed by either +API. This is something that will be addressed very soon. + +One thing to note is that you can store more than +just IRiakObjects in buckets. Bucket has convenience methods to store +byte[] and String values against a key but also type parameterized +generic fetch and store methods. This allows you to store your domain +objects in Riak. Please see Conversion below for details. + +Although it is expensive and somewhat ill advised, you may list a bucket's keys +with: + + for(String k : bucket.keys()) { + // do your key thing + } + +The keys are streamed, and the stream closed by a reaper thread when the +iterator is weakly reachable. + +There is a further wrapper to bucket (see DomainBucket below) that simplifies +calling operations further. + +***** Conflict Resolution Conflict happens in Dynamo style systems. It is best to have a strategy in mind -to deal with it. The strategy is highly dependant on your domain. A classic -example is the -[[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/megacorp/commerce/ShoppingCart.java][shopping cart]], conflicting shopping carts -can be merged by a union of their contents, sure you might reinstate a deleted -toaster but that is better than losing money... +to deal with it. The strategy you employ is highly dependant on your domain. One +example is a shopping cart. Conflicting shopping carts should be merged by a +union of their contents, you might reinstate a deleted toaster but that is +better than losing money. + +See MergeCartResolver in src/test for an example of a Shopping Cart conflict +resolver. -See [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/megacorp/commerce/MergeCartResolver.java][MergeCartResolver]]. +Both fetch and store make use of a ConflictResolver to handle siblings. -Both fetch and store make use of a ConflictResolver to handle siblings. The -default conflict resolver right now does not resolve conflicts, it blows up with +The default conflict resolver does not "resolve" conflicts, it blows up with an UnresolvedConflictException (which gives you access to the siblings). -Using the basic bucket interface you can provide an anonymous inner class as a -conflict resolver to either a fetch or a store operation. +Using the basic bucket interface you can provide a conflict resolver +to either a fetch or a store operation. All operations are configured +by default with a resolver for which siblings are an exception. + +The conflict resolver interface is a single method that accepts a +Collection of domain objects and returns the one true value, or +throws an exception of conflict cannot be +resolved. UnresolvedConflictException contains all the siblings. In +cases were logic fails to resolve the conflict you can push the +decision to a user: + + T resolve(final Collection siblings) throws UnresolvedConflictException; + +Since conflict resolution requires domain knowledge it makes sense to convert +riak data into domain objects. + +***** Conversion +Data in riak is made up of the value, its content-type, links and user meta +data. There is then some riak meta data along with that (for example, +the VClock, last update time etc.) + +The data payload can be any type you like, but normally it is +a serialized version of some application specific data. It is a lot +easier to reason about siblings and conflict with the domain knowledge +of your application, and easier still with the actual domain objects. + +Each operation provided by Bucket can accept an implementation of + + com.basho.riak.client.convert.Converter + +Converter has two methods + + IRiakObject fromDomain(T domainObject, VClock vclock) + T toDomain(IRiakObject riakObject) + +Implement these and pass to a bucket operation to convert riak data into POJOs +and back. + +This library currently provides a JSONConverter that uses the [[http://wiki.fasterxml.com/JacksonHome][Jackson]] JSON +library. Jackson requires your classes to be either simple Java Bean types +(getter, setter, no arg constructor) or annotated. Please see + + com.megacorp.commerce.ShoppingCart + +for an example of Jackson annotated domain class and LegacyCart in the same +package for an unannotated class. + +You can annotate a field of your class with + + @RiakKey + +and the client will use the value of that field as the key for fetch and store +operations. If you do not or cannot annotate a key field then you must use the + + bucket.store("key", myObject); + +Implementing your own converter is pretty simple, so if you want to store XML, +go ahead. Be aware that the converter should write the content-type when +serializing and also check the content-type when deserializing. + +There is also a pass through converter for IRiakObject. + +You may also use the JSONConverter to store Java Collection types (like Map, +List or Map and List>>) as JSON in Riak. Which is +pretty cool. + +***** Mutation +With conflict resolution comes Mutation. When you perform a store you might be +creating a new key/value but you may well be updating an existing +value and *you don't know in advance*. If you model your data to be +logically monotonic then you can provide a Mutation that accepts the old value +and returns the new value based on some logic. + + b.store("k", myObject).withMutation(new Mutation() { + MyClass apply(MyClass original) { + myObject.setCounter(orignal.getCounter() +1 ); + return myObject; + }).execute(); + +The Mutation interface has a single method: + + T apply(T original); + +Which accepts the conflict resolved value from a fetch and returns it +updated. + +The default mutation replaces the old value with the new +value. (See ClobberMutation.) + +***** The order of events +When a fetch operation is executed the order of execution is as follows: + +1. RawClient fetch +2. Siblings iterated and converted +3. Converted siblings passed to conflict resolver +4. Resolved value returned + +For a store operation + +1. Fetch operation performed as above +2. The Mutation is applied to the fetched value +3. The mutated value is converted to RiakObject +4. The store is performed through the RawClient +5. if returnBody is true the siblings are iterated, converted and conflict + resolved and the value is returned + +***** Domain Buckets +A domain bucket is a wrapper around a bucket that simplifies the amount of +typing and repetition required to work with that bucket. A DomainBucket is an +abstraction that allows you to store and fetch specific types in Riak. +BEWARE there is no enforcement of any schema on the Riak side, if you +store ShoppingCart in the "carts" bucket and try and retrieve it through a +DomainBucket then you will have a ConversionException. + +Chances are, that once you project has stablised you will be working with maybe +a few types and a few buckets, so you ShoppingCarts will always require that you +use you MergedCartResolver and your CartConverter and your CartMutation. + +Creating a DomainBucket is easy: + + final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class) + .withResolver(new MergeCartResolver()) + .returnBody(true) + .retrier(new DefaultRetrier(4)) + .w(1) + .dw(1) + .r(1) + .rw(1) + .mutationProducer(new CartMutator()) + .build(); + +Thereafter there is less noise when working with your ShoppingCart data: + + final ShoppingCart cart = new ShoppingCart(userId); + cart.addItem("coffee"); + cart.addItem("fixie"); + cart.addItem("moleskine"); + final ShoppingCart storedCart = carts.store(cart); + + carts.fetch(userId); + cart.addItem("bowtie"); + cart.addItem("nail gun"); + carts.delete(cart); + +(NOTE: by default a DomainBucket is configured with the +DefaultResolver, ClobberMutation and JSONConverter) + +***** Queries +The Riak-java-client currently supports map reduce and link walking. + +****** Map reduce +Performing map reduce is very much as it was for the legacy RiakClient: -***** Conversion +Refer to the [[http://wiki.basho.com/MapReduce.html][Riak Map/Reduce documentation ]]for a detailed explanation of how +map/reduce works in Riak. Map/Reduce is just another RiakOperation and so a +fluid builder: -Since conflict resolution is a very domain specific thing it makes sense to -convert the Riak data into a domain specific object before conflict is -resolved. You provide an implementation of the [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/convert/Converter.java][Converter]] interface to any -fetch/store operation. By default, if you are working with a -operation the converter does nothing. If you are working with a generic -operation then there is a basic [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/convert/JSONConverter.java][JSONConverter]] that is the simplest -possible use of [[http://wiki.fasterxml.com/JacksonHome][Jackson JSON converter]]. It will attempt to coherce a -RiakObject's JSON payload into a domain class of your chosing. It can also -return Map, Collection etc if you are yet to decide on a domain. + MapReduceResult result = client.mapReduce("myBucket") + .addLinkPhase("bucketX", "test", false) + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), false) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) + .execute(); + +The Map reduce operation lets you build up a number of phases. The +MapReduceResult uses Jackson (again) to provide you query results as either Java +Collection types, a raw JSON string or (again) as a Java Bean type that you +provide to the getResult method: -***** Mutation + Collection stockItems = + result.getResult(GoogleStockDataItem.class); -With conflict resolution comes Mutation. When you perform a store you may be +The inputs to a Map/Reduce are either a bucket, or bucket/key pairs. -+ Creating a new value with a new key -+ Updating an existing value +******* Bucket Map Reduce +A BucketMapReduce extends MapReduce. To create a BucketMapReduce operation call -And *you don't know in advance*. You may think you're creating a new value but -many people may have beaten you to it. Using the Shopping Cart as an example -again, you don't want to overwrite the existing value with your own new value, -so a Mutation that merges the current value with your new value makes sense -here. + client.mapReduce("myBucket"); -You provide an implementation of [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/cap/Mutation.java][Mutation]] that accepts the old value -and returns the new value. The [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/cap/ClobberMutation.java][default]] current mutation clobbers the old value, -that is it ignores the old value and returns your new value. +BucketMapReduce also allows the addition of Key Filters to limit the results. +Adding Key Filters is just like adding phases: -***** Fetch then Store All together a Fetch operation now entails + MapReduceResult result = client.mapReduce("myBucket") + .addKeyFilter(new TokenizeFilter("_", 2)) + .addKeyFilter(new StringToIntFilter()) + .addKeyFilter(new LessThanFilter(50)) + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson")) + .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce","reduce_sort"), true) + .execute(); -1. Fetch the object from Riak -2. Run the Converter -3. Run the ConflictResolver -4. Return the converted object + Collection items = result.getResult(Integer.class); + +Please see the [[http://wiki.basho.com/Key-Filters.html][Key Filters documentation]] for more details about key filters and +the + + com.basho.riak.client.query.filters.* -a store +package for the available filters. + +******* BucketKeyMapReduce +A BucketKeyMapReduce can be built with many inputs, they're added just like +phases. + + MapReduceResult result = client.mapReduce() + .addInput("goog","2010-01-04") + .addInput("goog","2010-01-05") + .addInput("goog","2010-01-06") + .addInput("goog","2010-01-07") + .addInput("goog","2010-01-08") + .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true) + .execute(); -1. Run a fetch -2. Run the mutation on the result -3. Store the new object -4. Optionally (if return body is true) run the Converter and ConflictResolver - and return the resolved value. +****** Link Walking +Links provide a light weight graph database-like feature to Riak. See the [[http://wiki.basho.com/Links-and-Link-Walking.html][Link +Walking documentation]] for full details. +Adding links to an IRiakObject is done via the builder -**** Domain Buckets + IRiakObject o = RiakObjectBuilder.newBuilder("myBucket", + "myKey").withValue("value").addLink("bucketX", "keyY", "tagZ").build(); - If you are working with ShoppingCarts you're working with Shopping Carts. It is - a lot of faff providing the Converter, Mutation and ConflictResolver to the - Bucket operation over and over again. So there - are - [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/main/java/com/basho/riak/newapi/bucket/DomainBucket.java][Domain Buckets]]. A DomainBucket is a wrapper around a bucket (you see, - *another* layer) that is configured at creation time with a ConflictResolver, - MutationProvider and a Converter. Thereafter you can work with the DomainBucket - and deal solely with your ShoppingCart. Look at - [[https://github.com/russelldb/riak-java-client-api/blob/hl/src/test/java/com/basho/riak/client/itest/ITestDomainBucket.java][this test]] - for an example. +Link Walking is just another RiakOperation. You start at a IRiakObject and add +steps to walk and call execute. Adding a step is matter of specifying the +bucket, tag and whether to keep the output for the step. A null, empty string or +"_" are treated as the wildcard for either of bucket or tag. Specify keep as +either a boolean or the Accumulate enum. Not specifying keep will result in the +default for that step being used. -There well very soon be a default RiakObject DomainBucket preconfigured with a -ClobberMutation, no resolution ConflictResolver and do nothing converter in the -library for convenience. +An example link walk: -*** Workflow + WalkResult result = client.walk(riakObject) + .addStep(bucketName, fooTag, true) + .addStep(bucketName, fooTag) + .execute(); -The API makes it easy to start experimenting with Riak and start to create -anonymous inner classes for ConflictResolution/Mutation/Conversion and then, as -your application firms up, you can codify the your strategies into solid, -testable, resusable classes and DomainBuckets. -*** Flexible +The result is always a Collection of IRiakObjects. In the next version +conversion and conflict resolution will also be available to link +walking. We also plan to add Link mapping so that links can be used to +build graphs of domain objects. - If you need raw speed pumping 1000s of objects in go right down to the lowest - level and use the pbc.RiakClient. If you want to start off with HTTP but later - implement your own transport use RawClient. If you want to work at a higher - level of abstraction use Bucket and DomainBucket. +NOTE: Link walking is a REST only operation as far as Riak's +interfaces are concerned. Link Walking in the protocol buffers Java +client is a hack that issues two m/r jobs to the protocol buffers +interface (the first constructs the inputs to the second by walking +the links, the second returns the data). It is included to provide +parity between the interfaces but should perform similarly to the +REST link walking interface. -*** State of play +** Next Steps +Have a look at the - This is very much an early release work in progress but it covers the KV store - and has integration test coverage of ~65%. Don't use it in production but - please play with it and feedback. + com.basho.riak.client.itest -*** TODO So much. A small snippet of which is: +package for examples of all the features described above. -- Add tests to verify Links and UserMeta work -- MapReduce and LinkWalking for a start. -- Tidy the code and vet it for Thread Safety -- An simple method for registering and configuring RawClient implementations -- Many more unit tests -- Sort out the package names -- Stop leaking Jackson annotations -- A default RiakObject DomaonBucket (as described above) -- Lots more +Start storing data in Riak using IRiakObject and anonymous inner +classes for Mutation, ConflictResolution and Retrier. As you use case +and application firm you can create concrete, testable, reusable +implementations to act on your own domain objects. +** Contributing +Please start with the [[https://github.com/basho/riak-java-client/blob/master/DEVELOPERS.md][DEVELOPERS]] document. diff --git a/TODO b/TODO index ed253d69f..16b64a56e 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,42 @@ -Add ?links=false param to listBucket -Stream raw siblings +* TODO Configure a RawClient from RiakFactory (config object, map?) +* TODO moar unit tests +* TODO detailed JavaDoc throughout +* TODO Code audit for safety/oddness +EG Builders for use from single thread so remove sync from builder collections +* TODO Look at client id in a more thorough and logical way +What does it mean when a client is shared accross threads? Really an +operation is done by a client? or the connection has an ID? And we +match the connection to the client? Or we encourage lots of clients +and drop this one client per application thing? +* TODO consider a type for value + content-type since they are inextricably linked in every way +* TODO XML converter +* TODO consider modeling RiakOperation as Callable and RiakClient as executor +* TODO make default resolver a strategy added on client or bucket +* TODO make default mutator a strategy +* TODO RawClient - anything missing (Stream in, Stream out) +* TODO A PUMP (a super fast way to pump data into Riak) +* TODO Move pbc stuff into client.pbc +** TODO deprecate old pbc stuff in favour of new stuff +* TODO Class whittle down +* TODO RiakObject creation factory methods on RiakDomain Bucket +* TODO per op CAP quroa on RiakDomain bucket +* TODO per op CAP quora params on domain buckets +* TODO Links +** TODO Links should return +- Siblings +- Domain objects +** TODO Mapping links +*** TODO What does this mean? +If you create a domain class you can annotate an field on it to +denote a link walk spec that will lead to the object(s) to populate +that field. (Transparent proxy? (only for collections right?)) +** TODO Mapping user meta? (IE User Meta in domain object conversion) +** TODO proto client connection pool +* TODO periodic failing ITest PB Bucket on sibling test +* TODO Load balancing retrier +Cluster aware (uses stats call to learn about ring, or configured with +multlple hosts?) +* TODO Bucket properties +** TODO Rest interface is capable of more than the REST client abstraction exposes +expose all properties +** TODO PB interface for bucket props From 7eebb987d0f985e30177c3dbe662bfa00eb126f8 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 10:15:26 +0100 Subject: [PATCH 035/764] Rename TODO to TODO.org --- TODO => TODO.org | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename TODO => TODO.org (100%) diff --git a/TODO b/TODO.org similarity index 100% rename from TODO rename to TODO.org From 3d6b3c80d1587f35e0bffdba48effc0dca40c897 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 10:33:11 +0100 Subject: [PATCH 036/764] Add src markup to README.org --- README.org | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index debf4a959..5d1042e69 100644 --- a/README.org +++ b/README.org @@ -20,7 +20,6 @@ objects in Riak and returning domain objects from map reduce queries. ** Including riak-java-client in your project Riak-java-client is available from maven central. Add the dependency to your pom.xml - com.basho.riak riak-client @@ -28,14 +27,13 @@ Riak-java-client is available from maven central. Add the dependency to your pom pom - To build and install from source, first install [[http://maven.apache.org/download.html][Apache Maven]]. With Maven installed, run: mvn clean install ** Quick start Assuming you're running Riak on localhost on the default ports getting started is as simple as: - +#+BEGIN_SRC Java // create a client IRiakClient riakClient = RiakFactory.pbcClient(); //or RiakFactory.httpClient(); @@ -54,7 +52,7 @@ Assuming you're running Riak on localhost on the default ports getting started i // delete myBucket.delete("key1").rw(3).execute(); - +#+END_SRC ** Some History This riak-java-client API is new. Prior to this version there were two separate clients, one for protocol buffers, one for REST, both in the same library and From 3c4dcab513e00797a292d1f6661555c142007a7d Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 10:59:15 +0100 Subject: [PATCH 037/764] Add src markup to README.org --- README.org | 250 ++++++++++++++++++++++++++--------------------------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/README.org b/README.org index 5d1042e69..2f51f3a8a 100644 --- a/README.org +++ b/README.org @@ -19,39 +19,39 @@ objects in Riak and returning domain objects from map reduce queries. * Using riak-java-client ** Including riak-java-client in your project Riak-java-client is available from maven central. Add the dependency to your pom.xml - +#+BEGIN_SRC xml com.basho.riak riak-client 0.15.0 pom - +#+END_SRC To build and install from source, first install [[http://maven.apache.org/download.html][Apache Maven]]. With Maven installed, run: - - mvn clean install - +#+BEGIN_SRC shell +mvn clean install +#+END_SRC ** Quick start Assuming you're running Riak on localhost on the default ports getting started is as simple as: -#+BEGIN_SRC Java - // create a client - IRiakClient riakClient = RiakFactory.pbcClient(); //or RiakFactory.httpClient(); +#+BEGIN_SRC java +// create a client +IRiakClient riakClient = RiakFactory.pbcClient(); //or RiakFactory.httpClient(); - // create a new bucket - Bucket myBucket = riakClient.createBucket("myBucket").execute(); +// create a new bucket +Bucket myBucket = riakClient.createBucket("myBucket").execute(); - // add data to the bucket - myBucket.store("key1", "value1").execute(); +// add data to the bucket +myBucket.store("key1", "value1").execute(); - //fetch it back - IRiakObject myData = myBucket.fetch("key1").execute(); +//fetch it back +IRiakObject myData = myBucket.fetch("key1").execute(); - // you can specify extra parameters to the store operation using the - // fluid builder style API - myData = myBucket.store("key1", "value2").returnBody(true).execute(); +// you can specify extra parameters to the store operation using the +// fluid builder style API +myData = myBucket.store("key1", "value2").returnBody(true).execute(); - // delete - myBucket.delete("key1").rw(3).execute(); +// delete +myBucket.delete("key1").rw(3).execute(); #+END_SRC ** Some History This riak-java-client API is new. Prior to this version there were two separate @@ -60,18 +60,18 @@ both with quite different APIs. *** Deprecated The REST client (which you can still use directly) has been moved to - - com.basho.riak.client.http.RiakClient - +#+BEGIN_SRC java +com.basho.riak.client.http.RiakClient +#+END_SRC Though a deprecated RiakClient still exists at - - com.basho.riak.client.RiakClient - +#+BEGIN_SRC java +com.basho.riak.client.RiakClient +#+END_SRC for another release or two to ease transition. All the REST client's HTTP specific classes have been moved to - - com.basho.riak.client.http.* - +#+BEGIN_SRC java +com.basho.riak.client.http.* +#+END_SRC and the originals retained *but deprecated*. If you want to use the legacy, low-level client directly please use the newly packaged version. The deprecated classes will be deleted in the next or following release to @@ -84,9 +84,9 @@ conventions in the short term. ** What's new? *** Builders To avoid the profusion of constructors and setters there is a builder - - com.basho.riak.client.builders.RiakObjectBuilder - +#+BEGIN_SRC java +com.basho.riak.client.builders.RiakObjectBuilder +#+END_SRC to simplify creating and updating IRiakObjects. In fact most classes are as immutable as possible and are created @@ -96,9 +96,9 @@ across multiple threads but the immutable value objects they create are. *** Layers **** Low There is a low-level interface, RawClient - - com.basho.riak.client.raw.RawClient - +#+BEGIN_SRC java +com.basho.riak.client.raw.RawClient +#+END_SRC and two adapters that adapt the legacy protocol buffers and REST clients to the RawClient interface. RawClient provides access to Riak's APIs. If you don't want any of the higher level features to deal with domain objects, eventual @@ -106,53 +106,53 @@ consistency and fault tolerance (see below) then at least use RawClient over the underlying legacy clients so your code will not need to change if you decide to move from REST to protocol buffers or back. For example: - - RiakClient pbcClient = new RiakClient("127.0.0.1"); - // OR - // com.basho.riak.client.http.RiakClient httpClient = new - // com.basho.riak.client.http.RiakClient("http://127.0.0.1:8098/riak"); - RawClient rawClient = new PBClientAdapter(pbcClient); - // OR new HTTPClientAdapter(httpClient); - - IRiakObject riakObject = RiakObjectBuilder.newBuilder(bucketName, "key1").withValue("value1").build(); - rawClient.store(riakObject, new StoreMeta(2, 1, false)); - RiakResponse fetched = rawClient.fetch(bucketName, "key1"); - IRiakObject result = null; - - if(fetched.hasValue()) { - if(fetched.hasSiblings()) { - //do what you must to resolve conflicts - } else { - result = fetched.getRiakObjects()[0]; - } - } - - result.addLink(new RiakLink("otherBucket", "otherKey", "tag")); - result.setValue("newValue"); - - RiakResponse stored = rawClient.store(result, new StoreMeta(2, 1, true)); - - IRiakObject updated = null; - - if(stored.hasValue()) { - if(stored.hasSiblings()) { - //do what you must to resolve conflicts - } else { - updated = stored.getRiakObjects()[0]; - } - } - - rawClient.delete(bucketName, "key1"); - +#+BEGIN_SRC java +RiakClient pbcClient = new RiakClient("127.0.0.1"); +// OR +// com.basho.riak.client.http.RiakClient httpClient = new +// com.basho.riak.client.http.RiakClient("http://127.0.0.1:8098/riak"); +RawClient rawClient = new PBClientAdapter(pbcClient); +// OR new HTTPClientAdapter(httpClient); + +IRiakObject riakObject = RiakObjectBuilder.newBuilder(bucketName, "key1").withValue("value1").build(); +rawClient.store(riakObject, new StoreMeta(2, 1, false)); +RiakResponse fetched = rawClient.fetch(bucketName, "key1"); +IRiakObject result = null; + +if(fetched.hasValue()) { +if(fetched.hasSiblings()) { +//do what you must to resolve conflicts +} else { +result = fetched.getRiakObjects()[0]; +} +} + +result.addLink(new RiakLink("otherBucket", "otherKey", "tag")); +result.setValue("newValue"); + +RiakResponse stored = rawClient.store(result, new StoreMeta(2, 1, true)); + +IRiakObject updated = null; + +if(stored.hasValue()) { +if(stored.hasSiblings()) { +//do what you must to resolve conflicts +} else { +updated = stored.getRiakObjects()[0]; +} +} + +rawClient.delete(bucketName, "key1"); +#+END_SRC If *you* want to add a client transport to Riak (say you hate Apache HTTP client but love Netty) implementing RawClient is the way to do it. **** High All the code so far elides somes rather important details: - - // handle conflict here - +#+BEGIN_SRC java +// handle conflict here +#+END_SRC If your bucket allows siblings at some point you may have to deal with conflict. Likewise, if you are running in the real world you may have to deal with temporary failure. @@ -164,39 +164,39 @@ you some tools to deal with eventual consistency and temporary failure. Talking to Riak is modelled as a set of operations. An operation is a fluid builder for setting operation parameters (like the tunable CAP quorum for a read) and an execute method to carry out the operation. EG - +#+BEGIN_SRC java Bucket b = client.createBucket(bucketName) .nVal(1) .allowSiblings(true) .execute(); - +#+END_SRC or - +#+BEGIN_SRC java b.store("k", "v").w(2).dw(1).returnBody(false).execute(); - +#+END_SRC All the operations implement RiakOperation, which has a single method: - +#+BEGIN_SRC java T execute() throws RiakException; - +#+END_SRC ***** Retry Each operation needs a Retrier. You can specify a default retrier implementation when you create an IRiakClient or you can provide one to each operation when you build it. There is a simple retrier provided with this library that retries the given operation *n* times before throwing an exception. - +#+BEGIN_SRC java b.store("k", "v").retrier(DefaultRetrier.attempts(3)).execute(); - +#+END_SRC The DefaultRiakClient implementation provides a 3 times retrier to all it's operations. You can override this from the constructor or provide your own per operation (or per bucket, see below). The Retrier interface accepts Callable for its "attempt" method. Internally, operations are built around that interface. - +#+BEGIN_SRC java public interface Retrier { T attempt(Callable command) throws RiakRetryFailedException; } - +#+END_SRC ***** Buckets To simplify the Riak client all value related operations are performed via the Bucket interface. The Bucket also provides access to the set of bucket @@ -213,11 +213,11 @@ objects in Riak. Please see Conversion below for details. Although it is expensive and somewhat ill advised, you may list a bucket's keys with: - +#+BEGIN_SRC java for(String k : bucket.keys()) { // do your key thing } - +#+END_SRC The keys are streamed, and the stream closed by a reaper thread when the iterator is weakly reachable. @@ -249,9 +249,9 @@ throws an exception of conflict cannot be resolved. UnresolvedConflictException contains all the siblings. In cases were logic fails to resolve the conflict you can push the decision to a user: - +#+BEGIN_SRC java T resolve(final Collection siblings) throws UnresolvedConflictException; - +#+END_SRC Since conflict resolution requires domain knowledge it makes sense to convert riak data into domain objects. @@ -266,35 +266,35 @@ easier to reason about siblings and conflict with the domain knowledge of your application, and easier still with the actual domain objects. Each operation provided by Bucket can accept an implementation of - +#+BEGIN_SRC java com.basho.riak.client.convert.Converter - +#+END_SRC Converter has two methods - +#+BEGIN_SRC java IRiakObject fromDomain(T domainObject, VClock vclock) T toDomain(IRiakObject riakObject) - +#+END_SRC Implement these and pass to a bucket operation to convert riak data into POJOs and back. This library currently provides a JSONConverter that uses the [[http://wiki.fasterxml.com/JacksonHome][Jackson]] JSON library. Jackson requires your classes to be either simple Java Bean types (getter, setter, no arg constructor) or annotated. Please see - +#+BEGIN_SRC java com.megacorp.commerce.ShoppingCart - +#+END_SRC for an example of Jackson annotated domain class and LegacyCart in the same package for an unannotated class. You can annotate a field of your class with - +#+BEGIN_SRC java @RiakKey - +#+END_SRC and the client will use the value of that field as the key for fetch and store operations. If you do not or cannot annotate a key field then you must use the - +#+BEGIN_SRC java bucket.store("key", myObject); - +#+END_SRC Implementing your own converter is pretty simple, so if you want to store XML, go ahead. Be aware that the converter should write the content-type when serializing and also check the content-type when deserializing. @@ -311,17 +311,17 @@ creating a new key/value but you may well be updating an existing value and *you don't know in advance*. If you model your data to be logically monotonic then you can provide a Mutation that accepts the old value and returns the new value based on some logic. - +#+BEGIN_SRC java b.store("k", myObject).withMutation(new Mutation() { MyClass apply(MyClass original) { myObject.setCounter(orignal.getCounter() +1 ); return myObject; }).execute(); - +#+END_SRC The Mutation interface has a single method: - +#+BEGIN_SRC java T apply(T original); - +#+END_SRC Which accepts the conflict resolved value from a fetch and returns it updated. @@ -358,7 +358,7 @@ a few types and a few buckets, so you ShoppingCarts will always require that you use you MergedCartResolver and your CartConverter and your CartMutation. Creating a DomainBucket is easy: - +#+BEGIN_SRC java final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class) .withResolver(new MergeCartResolver()) .returnBody(true) @@ -369,9 +369,9 @@ Creating a DomainBucket is easy: .rw(1) .mutationProducer(new CartMutator()) .build(); - +#+END_SRC Thereafter there is less noise when working with your ShoppingCart data: - +#+BEGIN_SRC java final ShoppingCart cart = new ShoppingCart(userId); cart.addItem("coffee"); cart.addItem("fixie"); @@ -382,7 +382,7 @@ Thereafter there is less noise when working with your ShoppingCart data: cart.addItem("bowtie"); cart.addItem("nail gun"); carts.delete(cart); - +#+END_SRC (NOTE: by default a DomainBucket is configured with the DefaultResolver, ClobberMutation and JSONConverter) @@ -395,31 +395,31 @@ Performing map reduce is very much as it was for the legacy RiakClient: Refer to the [[http://wiki.basho.com/MapReduce.html][Riak Map/Reduce documentation ]]for a detailed explanation of how map/reduce works in Riak. Map/Reduce is just another RiakOperation and so a fluid builder: - +#+BEGIN_SRC java MapReduceResult result = client.mapReduce("myBucket") .addLinkPhase("bucketX", "test", false) .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), false) .addReducePhase(new NamedErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) .execute(); - +#+END_SRC The Map reduce operation lets you build up a number of phases. The MapReduceResult uses Jackson (again) to provide you query results as either Java Collection types, a raw JSON string or (again) as a Java Bean type that you provide to the getResult method: - +#+BEGIN_SRC java Collection stockItems = result.getResult(GoogleStockDataItem.class); - +#+END_SRC The inputs to a Map/Reduce are either a bucket, or bucket/key pairs. ******* Bucket Map Reduce A BucketMapReduce extends MapReduce. To create a BucketMapReduce operation call - +#+BEGIN_SRC java client.mapReduce("myBucket"); - +#+END_SRC BucketMapReduce also allows the addition of Key Filters to limit the results. Adding Key Filters is just like adding phases: - +#+BEGIN_SRC java MapReduceResult result = client.mapReduce("myBucket") .addKeyFilter(new TokenizeFilter("_", 2)) .addKeyFilter(new StringToIntFilter()) @@ -429,18 +429,18 @@ Adding Key Filters is just like adding phases: .execute(); Collection items = result.getResult(Integer.class); - +#+END_SRC Please see the [[http://wiki.basho.com/Key-Filters.html][Key Filters documentation]] for more details about key filters and the - +#+BEGIN_SRC java com.basho.riak.client.query.filters.* - +#+END_SRC package for the available filters. ******* BucketKeyMapReduce A BucketKeyMapReduce can be built with many inputs, they're added just like phases. - +#+BEGIN_SRC java MapReduceResult result = client.mapReduce() .addInput("goog","2010-01-04") .addInput("goog","2010-01-05") @@ -449,16 +449,16 @@ phases. .addInput("goog","2010-01-08") .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true) .execute(); - +#+END_SRC ****** Link Walking Links provide a light weight graph database-like feature to Riak. See the [[http://wiki.basho.com/Links-and-Link-Walking.html][Link Walking documentation]] for full details. Adding links to an IRiakObject is done via the builder - +#+BEGIN_SRC java IRiakObject o = RiakObjectBuilder.newBuilder("myBucket", "myKey").withValue("value").addLink("bucketX", "keyY", "tagZ").build(); - +#+END_SRC Link Walking is just another RiakOperation. You start at a IRiakObject and add steps to walk and call execute. Adding a step is matter of specifying the bucket, tag and whether to keep the output for the step. A null, empty string or @@ -467,12 +467,12 @@ either a boolean or the Accumulate enum. Not specifying keep will result in the default for that step being used. An example link walk: - +#+BEGIN_SRC java WalkResult result = client.walk(riakObject) .addStep(bucketName, fooTag, true) .addStep(bucketName, fooTag) .execute(); - +#+END_SRC The result is always a Collection of IRiakObjects. In the next version conversion and conflict resolution will also be available to link @@ -489,9 +489,9 @@ REST link walking interface. ** Next Steps Have a look at the - +#+BEGIN_SRC java com.basho.riak.client.itest - +#+END_SRC package for examples of all the features described above. Start storing data in Riak using IRiakObject and anonymous inner From 4273f42839644f958f88399e0cfe2520a2bfc929 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 11:03:28 +0100 Subject: [PATCH 038/764] Update heading levels for readability --- README.org | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.org b/README.org index 2f51f3a8a..036e9418a 100644 --- a/README.org +++ b/README.org @@ -94,7 +94,7 @@ using fluid builders. The builders are *not* designed to be used across multiple threads but the immutable value objects they create are. *** Layers -**** Low +*** Low There is a low-level interface, RawClient #+BEGIN_SRC java com.basho.riak.client.raw.RawClient @@ -148,7 +148,7 @@ rawClient.delete(bucketName, "key1"); If *you* want to add a client transport to Riak (say you hate Apache HTTP client but love Netty) implementing RawClient is the way to do it. -**** High +*** High All the code so far elides somes rather important details: #+BEGIN_SRC java // handle conflict here @@ -160,7 +160,7 @@ with temporary failure. The higher level API (built on top of RawClient) gives you some tools to deal with eventual consistency and temporary failure. -***** Operations +*** Operations Talking to Riak is modelled as a set of operations. An operation is a fluid builder for setting operation parameters (like the tunable CAP quorum for a read) and an execute method to carry out the operation. EG @@ -178,7 +178,7 @@ All the operations implement RiakOperation, which has a single method: #+BEGIN_SRC java T execute() throws RiakException; #+END_SRC -***** Retry +**** Retry Each operation needs a Retrier. You can specify a default retrier implementation when you create an IRiakClient or you can provide one to each operation when you build it. There is a simple retrier @@ -197,7 +197,7 @@ built around that interface. T attempt(Callable command) throws RiakRetryFailedException; } #+END_SRC -***** Buckets +*** Buckets To simplify the Riak client all value related operations are performed via the Bucket interface. The Bucket also provides access to the set of bucket properties (nval, allow_mult etc). @@ -224,7 +224,7 @@ iterator is weakly reachable. There is a further wrapper to bucket (see DomainBucket below) that simplifies calling operations further. -***** Conflict Resolution +*** Conflict Resolution Conflict happens in Dynamo style systems. It is best to have a strategy in mind to deal with it. The strategy you employ is highly dependant on your domain. One example is a shopping cart. Conflicting shopping carts should be merged by a @@ -255,7 +255,7 @@ decision to a user: Since conflict resolution requires domain knowledge it makes sense to convert riak data into domain objects. -***** Conversion +*** Conversion Data in riak is made up of the value, its content-type, links and user meta data. There is then some riak meta data along with that (for example, the VClock, last update time etc.) @@ -305,7 +305,7 @@ You may also use the JSONConverter to store Java Collection types (like Map, List or Map and List>>) as JSON in Riak. Which is pretty cool. -***** Mutation +*** Mutation With conflict resolution comes Mutation. When you perform a store you might be creating a new key/value but you may well be updating an existing value and *you don't know in advance*. If you model your data to be @@ -328,7 +328,7 @@ updated. The default mutation replaces the old value with the new value. (See ClobberMutation.) -***** The order of events +*** The order of events When a fetch operation is executed the order of execution is as follows: 1. RawClient fetch @@ -345,7 +345,7 @@ For a store operation 5. if returnBody is true the siblings are iterated, converted and conflict resolved and the value is returned -***** Domain Buckets +*** Domain Buckets A domain bucket is a wrapper around a bucket that simplifies the amount of typing and repetition required to work with that bucket. A DomainBucket is an abstraction that allows you to store and fetch specific types in Riak. @@ -386,10 +386,10 @@ Thereafter there is less noise when working with your ShoppingCart data: (NOTE: by default a DomainBucket is configured with the DefaultResolver, ClobberMutation and JSONConverter) -***** Queries +*** Queries The Riak-java-client currently supports map reduce and link walking. -****** Map reduce +**** Map reduce Performing map reduce is very much as it was for the legacy RiakClient: Refer to the [[http://wiki.basho.com/MapReduce.html][Riak Map/Reduce documentation ]]for a detailed explanation of how @@ -412,7 +412,7 @@ provide to the getResult method: #+END_SRC The inputs to a Map/Reduce are either a bucket, or bucket/key pairs. -******* Bucket Map Reduce +**** Bucket Map Reduce A BucketMapReduce extends MapReduce. To create a BucketMapReduce operation call #+BEGIN_SRC java client.mapReduce("myBucket"); @@ -437,7 +437,7 @@ the #+END_SRC package for the available filters. -******* BucketKeyMapReduce +**** BucketKeyMapReduce A BucketKeyMapReduce can be built with many inputs, they're added just like phases. #+BEGIN_SRC java @@ -450,7 +450,7 @@ phases. .addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true) .execute(); #+END_SRC -****** Link Walking +*** Link Walking Links provide a light weight graph database-like feature to Riak. See the [[http://wiki.basho.com/Links-and-Link-Walking.html][Link Walking documentation]] for full details. From e6439295eb23bc67ee77ceebb149d0039480e272 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Tue, 10 May 2011 14:29:28 +0100 Subject: [PATCH 039/764] Add Link Walking tests for both http and pb clients --- .../riak/client/itest/ITestHTTPLinkWalk.java | 34 +++++++++++++++++++ .../riak/client/itest/ITestLinkWalk.java | 11 ++++-- .../riak/client/itest/ITestPBLinkWalk.java | 34 +++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/basho/riak/client/itest/ITestHTTPLinkWalk.java create mode 100644 src/test/java/com/basho/riak/client/itest/ITestPBLinkWalk.java diff --git a/src/test/java/com/basho/riak/client/itest/ITestHTTPLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestHTTPLinkWalk.java new file mode 100644 index 000000000..3271e5f72 --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestHTTPLinkWalk.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; + +/** + * @author russell + * + */ +public class ITestHTTPLinkWalk extends ITestLinkWalk { + + /* (non-Javadoc) + * @see com.basho.riak.client.itest.ITestLinkWalk#getClient() + */ + @Override protected IRiakClient getClient() throws RiakException { + return RiakFactory.httpClient(); + } + + +} diff --git a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java index 44d440106..07afa4fd1 100644 --- a/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java +++ b/src/test/java/com/basho/riak/client/itest/ITestLinkWalk.java @@ -27,7 +27,6 @@ import com.basho.riak.client.IRiakClient; import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakException; -import com.basho.riak.client.RiakFactory; import com.basho.riak.client.bucket.Bucket; import com.basho.riak.client.bucket.RiakBucket; import com.basho.riak.client.builders.RiakObjectBuilder; @@ -38,10 +37,10 @@ * @author russell * */ -public class ITestLinkWalk { +public abstract class ITestLinkWalk { @Test public void test_walk() throws RiakException { - final IRiakClient client = RiakFactory.pbcClient(); + final IRiakClient client = getClient(); final String fooVal = "fooer"; final String barVal = "barrer"; @@ -108,4 +107,10 @@ public class ITestLinkWalk { assertTrue(keys.contains("second")); assertTrue(keys.contains("fourth")); } + + /** + * @return + * @throws RiakException + */ + protected abstract IRiakClient getClient() throws RiakException; } diff --git a/src/test/java/com/basho/riak/client/itest/ITestPBLinkWalk.java b/src/test/java/com/basho/riak/client/itest/ITestPBLinkWalk.java new file mode 100644 index 000000000..192465e5e --- /dev/null +++ b/src/test/java/com/basho/riak/client/itest/ITestPBLinkWalk.java @@ -0,0 +1,34 @@ +/* + * This file is provided 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.basho.riak.client.itest; + +import com.basho.riak.client.IRiakClient; +import com.basho.riak.client.RiakException; +import com.basho.riak.client.RiakFactory; + +/** + * @author russell + * + */ +public class ITestPBLinkWalk extends ITestLinkWalk { + + /* (non-Javadoc) + * @see com.basho.riak.client.itest.ITestLinkWalk#getClient() + */ + @Override protected IRiakClient getClient() throws RiakException { + return RiakFactory.pbcClient(); + } + + +} From 52cf38bc0fc941e1ac4a35b0291d342cf287ae34 Mon Sep 17 00:00:00 2001 From: Russell Brown Date: Mon, 16 May 2011 08:09:53 -0400 Subject: [PATCH 040/764] Document new API packages, classes and methods Update TODO.org with tasks picked up from documenting code --- TODO.org | 14 + .../basho/riak/client/DefaultRiakClient.java | 29 +- .../basho/riak/client/DefaultRiakObject.java | 167 +++++----- .../com/basho/riak/client/IRiakClient.java | 106 ++++++- .../com/basho/riak/client/IRiakObject.java | 174 +++++++++-- .../com/basho/riak/client/RiakException.java | 8 + .../com/basho/riak/client/RiakFactory.java | 26 +- .../java/com/basho/riak/client/RiakLink.java | 23 +- .../com/basho/riak/client/bucket/Bucket.java | 132 +++++++- .../riak/client/bucket/BucketProperties.java | 58 +++- .../riak/client/bucket/DefaultBucket.java | 289 +++++++++++++----- .../bucket/DefaultBucketProperties.java | 116 ++++--- .../riak/client/bucket/DomainBucket.java | 148 ++++++++- .../basho/riak/client/bucket/FetchBucket.java | 33 +- .../basho/riak/client/bucket/RiakBucket.java | 11 +- .../basho/riak/client/bucket/WriteBucket.java | 159 +++++++++- .../riak/client/bucket/package-info.java | 64 ++++ .../builders/BucketPropertiesBuilder.java | 6 +- .../client/builders/DomainBucketBuilder.java | 58 +++- .../client/builders/RiakObjectBuilder.java | 102 ++++++- .../riak/client/builders/package-info.java | 23 ++ .../basho/riak/client/cap/BasicVClock.java | 12 + .../com/basho/riak/client/cap/ClientId.java | 1 + .../riak/client/cap/ClobberMutation.java | 11 +- .../riak/client/cap/ConflictResolver.java | 9 +- .../riak/client/cap/DefaultResolver.java | 9 +- .../basho/riak/client/cap/DefaultRetrier.java | 12 +- .../com/basho/riak/client/cap/Mutation.java | 14 +- .../riak/client/cap/MutationProducer.java | 7 +- .../java/com/basho/riak/client/cap/Quora.java | 2 + .../com/basho/riak/client/cap/Quorum.java | 14 +- .../com/basho/riak/client/cap/Retrier.java | 12 +- .../cap/UnresolvedConflictException.java | 35 ++- .../com/basho/riak/client/cap/VClock.java | 2 + .../basho/riak/client/cap/package-info.java | 27 ++ .../client/convert/ConversionException.java | 15 +- .../basho/riak/client/convert/Converter.java | 4 +- .../riak/client/convert/JSONConverter.java | 57 +++- .../basho/riak/client/convert/KeyUtil.java | 64 +++- .../convert/NoKeySpecifedException.java | 18 +- .../client/convert/PassThroughConverter.java | 39 +++ .../basho/riak/client/convert/RiakKey.java | 5 +- .../riak/client/convert/package-info.java | 33 ++ .../http/mapreduce/filter/package-info.java | 20 ++ .../client/http/mapreduce/package-info.java | 20 ++ .../basho/riak/client/http/package-info.java | 21 ++ .../riak/client/http/plain/package-info.java | 19 ++ .../client/http/request/package-info.java | 19 ++ .../client/http/response/package-info.java | 19 ++ .../riak/client/http/util/Multipart.java | 2 - .../riak/client/http/util/package-info.java | 19 ++ .../client/mapreduce/filter/package-info.java | 17 ++ .../riak/client/mapreduce/package-info.java | 17 ++ .../riak/client/operations/DeleteObject.java | 43 ++- .../riak/client/operations/FetchObject.java | 58 +++- .../riak/client/operations/RiakOperation.java | 3 + .../riak/client/operations/StoreObject.java | 94 +++++- .../riak/client/operations/package-info.java | 21 ++ .../com/basho/riak/client/package-info.java | 51 ++++ .../basho/riak/client/plain/package-info.java | 17 ++ .../riak/client/query/BucketKeyMapReduce.java | 19 +- .../riak/client/query/BucketMapReduce.java | 50 +-- .../basho/riak/client/query/LinkPhase.java | 20 ++ .../com/basho/riak/client/query/LinkWalk.java | 15 +- .../basho/riak/client/query/LinkWalkStep.java | 60 +++- .../com/basho/riak/client/query/MapPhase.java | 30 +- .../basho/riak/client/query/MapReduce.java | 140 ++++++++- .../riak/client/query/MapReducePhase.java | 15 + .../riak/client/query/MapReduceResult.java | 13 +- .../basho/riak/client/query/ReducePhase.java | 1 + .../basho/riak/client/query/WalkResult.java | 6 + .../query/filter/AbstractKeyFilter.java | 1 + .../query/filter/AbstractLogicalFilter.java | 1 + .../client/query/filter/BetweenFilter.java | 31 +- .../client/query/filter/EndsWithFilter.java | 12 + .../client/query/filter/EqualToFilter.java | 22 ++ .../query/filter/FloatToStringFilter.java | 5 + .../query/filter/GreaterThanFilter.java | 17 ++ .../filter/GreaterThanOrEqualFilter.java | 18 +- .../query/filter/IntToStringFilter.java | 5 + .../riak/client/query/filter/KeyFilter.java | 6 + .../query/filter/KeyTransformFilter.java | 1 + .../client/query/filter/LessThanFilter.java | 17 ++ .../query/filter/LessThanOrEqualFilter.java | 18 ++ .../client/query/filter/LogicalAndFilter.java | 5 + .../client/query/filter/LogicalFilter.java | 1 + .../query/filter/LogicalFilterGroup.java | 5 + .../client/query/filter/LogicalNotFilter.java | 5 + .../client/query/filter/LogicalOrFilter.java | 5 + .../riak/client/query/filter/MatchFilter.java | 8 + .../client/query/filter/NotEqualToFilter.java | 17 ++ .../client/query/filter/SetMemberFilter.java | 24 ++ .../client/query/filter/SimilarToFilter.java | 13 + .../client/query/filter/StartsWithFilter.java | 8 + .../query/filter/StringToFloatFilter.java | 5 + .../query/filter/StringToIntFilter.java | 5 + .../client/query/filter/ToLowerFilter.java | 5 + .../client/query/filter/ToUpperFilter.java | 5 + .../client/query/filter/TokenizeFilter.java | 9 + .../client/query/filter/UrlDecodeFilter.java | 5 + .../client/query/filter/package-info.java | 27 ++ .../query/functions/AnonymousFunction.java | 2 +- .../riak/client/query/functions/Function.java | 1 + .../query/functions/JSBucketKeyFunction.java | 1 + .../client/query/functions/NamedFunction.java | 2 +- .../client/query/functions/package-info.java | 21 ++ .../basho/riak/client/query/package-info.java | 37 +++ .../query/serialize/FunctionWriter.java | 1 + .../serialize/JSBucketKeyFunctionWriter.java | 1 + .../serialize/JSSourceFunctionWriter.java | 1 + .../serialize/NamedErlangFunctionWriter.java | 1 + .../serialize/NamedJSFunctionWriter.java | 1 + .../client/query/serialize/package-info.java | 18 ++ .../com/basho/riak/client/raw/RawClient.java | 130 +++++++- .../basho/riak/client/raw/RiakResponse.java | 42 ++- .../com/basho/riak/client/raw/StoreMeta.java | 32 +- .../riak/client/raw/http/ConversionUtil.java | 122 ++++++-- .../client/raw/http/HTTPClientAdapter.java | 22 +- .../basho/riak/client/raw/http/KeySource.java | 14 +- .../riak/client/raw/http/package-info.java | 19 ++ .../basho/riak/client/raw/package-info.java | 18 ++ .../riak/client/raw/pbc/ConversionUtil.java | 9 +- .../riak/client/raw/pbc/PBClientAdapter.java | 39 ++- .../riak/client/raw/pbc/package-info.java | 19 ++ .../riak/client/raw/query/LinkWalkSpec.java | 25 +- .../riak/client/raw/query/MapReduceSpec.java | 28 +- .../raw/query/MapReduceTimeoutException.java | 7 + .../riak/client/raw/query/package-info.java | 19 ++ .../riak/client/request/package-info.java | 17 ++ .../riak/client/response/package-info.java | 17 ++ .../basho/riak/client/util/CharsetUtils.java | 49 ++- .../com/basho/riak/client/util/Multipart.java | 10 + .../client/util/UnmodifiableIterator.java | 7 +- .../basho/riak/client/util/package-info.java | 22 ++ .../com/basho/riak/pbc/BucketProperties.java | 3 + .../java/com/basho/riak/pbc/IRequestMeta.java | 3 + .../java/com/basho/riak/pbc/KeySource.java | 3 + .../riak/pbc/MapReduceResponseSource.java | 3 + .../java/com/basho/riak/pbc/RequestMeta.java | 3 + .../java/com/basho/riak/pbc/RiakClient.java | 3 + .../com/basho/riak/pbc/RiakConnection.java | 5 + .../java/com/basho/riak/pbc/RiakError.java | 3 + .../java/com/basho/riak/pbc/RiakLink.java | 3 + .../com/basho/riak/pbc/RiakMessageCodes.java | 3 + .../java/com/basho/riak/pbc/RiakObject.java | 3 + .../com/basho/riak/pbc/RiakStreamClient.java | 4 + .../riak/pbc/mapreduce/LinkFunction.java | 3 + .../riak/pbc/mapreduce/MapReduceResponse.java | 3 + .../riak/pbc/mapreduce/package-info.java | 21 ++ .../java/com/basho/riak/pbc/package-info.java | 21 ++ src/main/java/org/json/package-info.java | 18 ++ 151 files changed, 3613 insertions(+), 529 deletions(-) create mode 100644 src/main/java/com/basho/riak/client/bucket/package-info.java create mode 100644 src/main/java/com/basho/riak/client/builders/package-info.java create mode 100644 src/main/java/com/basho/riak/client/cap/package-info.java create mode 100644 src/main/java/com/basho/riak/client/convert/PassThroughConverter.java create mode 100644 src/main/java/com/basho/riak/client/convert/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/filter/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/mapreduce/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/plain/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/request/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/response/package-info.java create mode 100644 src/main/java/com/basho/riak/client/http/util/package-info.java create mode 100644 src/main/java/com/basho/riak/client/mapreduce/filter/package-info.java create mode 100644 src/main/java/com/basho/riak/client/mapreduce/package-info.java create mode 100644 src/main/java/com/basho/riak/client/operations/package-info.java create mode 100644 src/main/java/com/basho/riak/client/package-info.java create mode 100644 src/main/java/com/basho/riak/client/plain/package-info.java create mode 100644 src/main/java/com/basho/riak/client/query/filter/package-info.java create mode 100644 src/main/java/com/basho/riak/client/query/functions/package-info.java create mode 100644 src/main/java/com/basho/riak/client/query/package-info.java create mode 100644 src/main/java/com/basho/riak/client/query/serialize/package-info.java create mode 100644 src/main/java/com/basho/riak/client/raw/http/package-info.java create mode 100644 src/main/java/com/basho/riak/client/raw/package-info.java create mode 100644 src/main/java/com/basho/riak/client/raw/pbc/package-info.java create mode 100644 src/main/java/com/basho/riak/client/raw/query/package-info.java create mode 100644 src/main/java/com/basho/riak/client/request/package-info.java create mode 100644 src/main/java/com/basho/riak/client/response/package-info.java create mode 100644 src/main/java/com/basho/riak/client/util/package-info.java create mode 100644 src/main/java/com/basho/riak/pbc/mapreduce/package-info.java create mode 100644 src/main/java/com/basho/riak/pbc/package-info.java create mode 100644 src/main/java/org/json/package-info.java diff --git a/TODO.org b/TODO.org index 16b64a56e..9250e4928 100644 --- a/TODO.org +++ b/TODO.org @@ -1,6 +1,20 @@ +* TODO Check MapReduceTimeException is actually thrown when a time out occurs +Write a timing out test * TODO Configure a RawClient from RiakFactory (config object, map?) +Include things like TCP_NODELAY etc +* TODO Conversion needs more thought, especially around the key +* TODO Have store/fetch/delete Object operations use the pass through non converter if the type they are working with is IRiakObject +* DONE Set the *key* on the converted domain object if RiakKey annotation present +* TODO Have key as a parameter to convert? +* TODO remove vclock as param to convert? +* TODO reimplement JSONConverter as less of an example and more for production +* TODO key discovery from domain objects needs to be a strategy * TODO moar unit tests * TODO detailed JavaDoc throughout +* TODO Add a DomainBucket.store(String key, T o) method +* TODO per op. cap on RiakBucket +* TODO Retrier, Mutator, Conflict resolver on RiakBucket +* TODO some sort of registry/lookup based on type/content type for Converters * TODO Code audit for safety/oddness EG Builders for use from single thread so remove sync from builder collections * TODO Look at client id in a more thorough and logical way diff --git a/src/main/java/com/basho/riak/client/DefaultRiakClient.java b/src/main/java/com/basho/riak/client/DefaultRiakClient.java index 26fa8d417..59a7c748a 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakClient.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakClient.java @@ -7,19 +7,36 @@ import com.basho.riak.client.bucket.WriteBucket; import com.basho.riak.client.cap.DefaultRetrier; import com.basho.riak.client.cap.Retrier; +import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.query.BucketKeyMapReduce; import com.basho.riak.client.query.BucketMapReduce; import com.basho.riak.client.query.LinkWalk; import com.basho.riak.client.raw.RawClient; +import com.basho.riak.client.raw.http.HTTPClientAdapter; +import com.basho.riak.client.raw.pbc.PBClientAdapter; /** - * A default implementation of IRiakClient. + * The default implementation of IRiakClient. * * Provides convenient, transport agnostic ways to perform * bucket and query operations on Riak. + * + *

+ * This class is a wrapper around a {@link RawClient} of your choice. The {@link RawClient} wrapped is passed to all + * {@link RiakOperation}s created by this class, so it really needs to be Thread Safe and reusable. + *
+ * This class provides a {@link Retrier} to each {@link RiakOperation} it creates. If you provide one please make sure it is + * Thread safe and reusable. + *
+ * If you do not provide a {@link Retrier} a {@link DefaultRetrier} configured for 3 attempts is created. + *

* * @author russell * + * @see RawClient + * @see PBClientAdapter + * @see HTTPClientAdapter + * @see DefaultRetrier */ public final class DefaultRiakClient implements IRiakClient { @@ -27,8 +44,11 @@ public final class DefaultRiakClient implements IRiakClient { private final Retrier retrier; /** - * @param rawClient - * @param defaultRetrier + * Create an instance that wraps the provided {@link RawClient} and passes it and the {@link Retrier} + * to created operations. + * + * @param rawClient the {@link RawClient} to wrap. + * @param defaultRetrier the {@link Retrier} that will be set as the default on all {@link RiakOperation}s created by this instance. */ DefaultRiakClient(final RawClient rawClient, final Retrier defaultRetrier) { this.rawClient = rawClient; @@ -36,7 +56,8 @@ public final class DefaultRiakClient implements IRiakClient { } /** - * @param client + * Create an instance that wraps the provided {@link RawClient}. A {@link DefaultRetrier} configured for 3 attempts is also created. + * @param rawClient the {@link RawClient} to wrap. */ DefaultRiakClient(final RawClient rawClient) { this(rawClient, DefaultRetrier.attempts(3)); diff --git a/src/main/java/com/basho/riak/client/DefaultRiakObject.java b/src/main/java/com/basho/riak/client/DefaultRiakObject.java index a7ea1f049..8706139fb 100644 --- a/src/main/java/com/basho/riak/client/DefaultRiakObject.java +++ b/src/main/java/com/basho/riak/client/DefaultRiakObject.java @@ -22,21 +22,29 @@ import java.util.List; import java.util.Map; +import com.basho.riak.client.builders.RiakObjectBuilder; import com.basho.riak.client.cap.VClock; import com.basho.riak.client.convert.RiakKey; import com.basho.riak.client.util.CharsetUtils; import com.basho.riak.client.util.UnmodifiableIterator; /** - * An implementation of {@link IRiakObject} - * - * Models the meta data and data stored at a bucket/key location in - * Riak. + * The default implementation of {@link IRiakObject} + *

+ * Is as immutable as possible. Value, content-type, links and user meta data are all mutable. + * It is safe to use the instances of this class from multiple threads. + *

+ *

+ * Due to the large number of arguments to the constructor the *best* way to create instances is with a {@link RiakObjectBuilder}. + *

* * @author russell */ public class DefaultRiakObject implements IRiakObject { + /** + * The default content type assigned when persisted in Riak if non is provided. + */ public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; private final String bucket; @@ -54,19 +62,17 @@ public class DefaultRiakObject implements IRiakObject { private volatile byte[] value; /** - * Use the builder. - * - * @param bucket - * @param key - * @param vclock - * @param conflict - * @param vtag - * @param lastModified - * @param contentType - * @param value - * @param siblings - * @param links - * @param userMeta + * Large number of arguments due to largely immutable nature. Use {@link RiakObjectBuilder} to create instances. + * + * @param bucket the bucket the object is stored in + * @param key the key it is stored under + * @param vclock the vclock, if available + * @param vtag the version tag, if relevant + * @param lastModified the last modified date from Riak (if relevant) + * @param contentType the content-type of the value + * @param value a byte[] of the data payload to store in Riak. Note: this is cloned on construction of this instance. + * @param links the List of {@link RiakLink}s from this object. Note: this is copied. + * @param userMeta the {@link Map} of user meta data to store/stored with this object. Note: this is copied. */ public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified, String contentType, byte[] value, final Collection links, final Map userMeta) { @@ -91,8 +97,9 @@ public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, } /** + * Copy the value array. * @param value - * @return + * @return a clone of value or null (if value was null) */ private byte[] copy(byte[] value) { if (value == null) { @@ -102,6 +109,11 @@ private byte[] copy(byte[] value) { } } + /** + * Copy the user meta data + * @param userMeta + * @return a copy of user meta data or any empty map + */ private Map copy(Map userMeta) { Map copy; @@ -114,6 +126,11 @@ private Map copy(Map userMeta) { return copy; } + /** + * Copy the {@link RiakLink} + * @param links + * @return a copy of links or an empty {@link ArrayList} + */ private Collection copy(Collection links) { Collection copy; if (links == null) { @@ -124,6 +141,10 @@ private Collection copy(Collection links) { return copy; } + /** + * If content-type is null set the content-type to DEFAULT_CONTENT_TYPE + * @param contentType + */ private void safeSetContentType(String contentType) { if (contentType == null) { this.contentType = DEFAULT_CONTENT_TYPE; @@ -132,22 +153,37 @@ private void safeSetContentType(String contentType) { } } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getBucket() + */ public String getBucket() { return bucket; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getVClock() + */ public VClock getVClock() { return vclock; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getKey() + */ public String getKey() { return key; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getVtag() + */ public String getVtag() { return vtag; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getLastModified() + */ public Date getLastModified() { Date lastModified = null; @@ -158,20 +194,35 @@ public Date getLastModified() { return lastModified; } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getContentType() + */ public String getContentType() { return contentType; } + /** + * NOTE: a copy is returned. Mutating the return value will not effect the state of this instance. + * @see com.basho.riak.client.IRiakObject#getMeta() + */ public Map getMeta() { return new HashMap(userMeta); } + /** + * @return a *cop* of this object's data payload. + * @see com.basho.riak.client.IRiakObject#getValue() + */ public byte[] getValue() { - return value; + return copy(value); } // mutate - + /** + * Note: Copies the value. + * + * @param a byte[] to store in Riak. + */ public void setValue(byte[] value) { this.value = copy(value); } @@ -184,24 +235,22 @@ public void setValue(String value) { this.contentType = CharsetUtils.addUtf8Charset(contentType); } + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#setContentType(java.lang.String) + */ public void setContentType(String contentType) { this.contentType = contentType; } /** - * an UnmodifiableIterator view on the RiakLinks + * an {@link UnmodifiableIterator} view on the RiakLinks */ public Iterator iterator() { return new UnmodifiableIterator(getLinks().iterator()); } - - /** - * Add link to this RiakObject's links. - * - * @param link - * a {@link RiakLink} to add. - * @return this RiakObject. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#addLink(com.basho.riak.client.RiakLink) */ public IRiakObject addLink(RiakLink link) { if (link != null) { @@ -212,12 +261,8 @@ public IRiakObject addLink(RiakLink link) { return this; } - /** - * Remove a {@link RiakLink} from this RiakObject. - * - * @param link - * the {@link RiakLink} to remove - * @return this RiakObject + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#removeLink(com.basho.riak.client.RiakLink) */ public IRiakObject removeLink(final RiakLink link) { synchronized (linksLock) { @@ -226,10 +271,8 @@ public IRiakObject removeLink(final RiakLink link) { return this; } - /** - * Does this RiakObject have any {@link RiakLink}s? - * - * @return true if there are links, false otherwise + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#hasLinks() */ public boolean hasLinks() { synchronized (linksLock) { @@ -237,10 +280,8 @@ public boolean hasLinks() { } } - /** - * How many {@link RiakLink}s does this RiakObject have? - * - * @return the number of {@link RiakLink}s this object has. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#numLinks() */ public int numLinks() { synchronized (linksLock) { @@ -248,8 +289,8 @@ public int numLinks() { } } - /** - * Return a copy of the links. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getLinks() */ public List getLinks() { synchronized (linksLock) { @@ -257,12 +298,8 @@ public List getLinks() { } } - /** - * Checks if the collection of RiakLinks contains the one passed in. - * - * @param riakLink - * a RiakLink - * @return true if the RiakObject's link collection contains riakLink. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#hasLink(com.basho.riak.client.RiakLink) */ public boolean hasLink(final RiakLink riakLink) { synchronized (linksLock) { @@ -270,12 +307,8 @@ public boolean hasLink(final RiakLink riakLink) { } } - /** - * Adds the key, value to the collection of user meta for this object. - * - * @param key - * @param value - * @return this RiakObject. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#addUsermeta(java.lang.String, java.lang.String) */ public IRiakObject addUsermeta(String key, String value) { synchronized (userMetaLock) { @@ -284,8 +317,8 @@ public IRiakObject addUsermeta(String key, String value) { return this; } - /** - * @return true if there are any user meta data set on this RiakObject. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#hasUsermeta() */ public boolean hasUsermeta() { synchronized (userMetaLock) { @@ -293,9 +326,8 @@ public boolean hasUsermeta() { } } - /** - * @param key - * @return + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#hasUsermeta(java.lang.String) */ public boolean hasUsermeta(String key) { synchronized (userMetaLock) { @@ -303,12 +335,8 @@ public boolean hasUsermeta(String key) { } } - /** - * Get an item of user meta data. - * - * @param key - * the user meta data item key - * @return The value for the given key or null. + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#getUsermeta(java.lang.String) */ public String getUsermeta(String key) { synchronized (userMetaLock) { @@ -317,9 +345,8 @@ public String getUsermeta(String key) { } - /** - * @param key - * the key of the item to remove + /* (non-Javadoc) + * @see com.basho.riak.client.IRiakObject#removeUsermeta(java.lang.String) */ public IRiakObject removeUsermeta(String key) { synchronized (userMetaLock) { diff --git a/src/main/java/com/basho/riak/client/IRiakClient.java b/src/main/java/com/basho/riak/client/IRiakClient.java index 3ce01694a..b47f609c3 100644 --- a/src/main/java/com/basho/riak/client/IRiakClient.java +++ b/src/main/java/com/basho/riak/client/IRiakClient.java @@ -16,42 +16,130 @@ import com.basho.riak.client.bucket.Bucket; import com.basho.riak.client.bucket.FetchBucket; import com.basho.riak.client.bucket.WriteBucket; +import com.basho.riak.client.cap.ClientId; import com.basho.riak.client.query.BucketKeyMapReduce; import com.basho.riak.client.query.BucketMapReduce; import com.basho.riak.client.query.LinkWalk; +import com.basho.riak.client.query.MapReduce; /** + * Primary high-level interface for accessing Riak. + *

+ * Used to create/fetch/update {@link Bucket}s and to + * perform Map/Reduce query operations. + *

+ *

For example: + *

+ * IRiakClient client = RiakFactory.pbcClient();
+ * final byte[] id = client.generateAndSetClientId()
+ * Bucket b = client.createBucket("myNewBucket")
+ *                      .nVal(3)
+ *                      .allowSiblings(true)
+ *                  .execute();
+ *                  
+ * // do things with the bucket
+ * 
+ * + * @see Bucket + * @see MapReduce + * * @author russell * */ public interface IRiakClient { + /** + * Set an ID for this client. + * All requests should include a client id, + * which can be any 4 bytes that uniquely identify the client, + * for purposes of tracing object modifications in the vclock. + * + * Note: this is 2 calls to Riak. + * @param clientId byte[4] that uniquely identify the client + * @return this + * @throws RiakException if operation fails + * @throws IllegalArgumentException if clientId is null or not byte[4] + */ IRiakClient setClientId(byte[] clientId) throws RiakException; + /** + * Generate, set and return "random" byte[4] id for the client. + * + * Note: this is a call to Riak. + * @see ClientId + * @return a byte[4] id for this client. + * @throws RiakException + */ byte[] generateAndSetClientId() throws RiakException; + /** + * Retrieve the client id from Riak that this client is using. + * + * Note: this is a call to Riak. + * @return a byte[4] that Riak uses to identify this client. + * @throws RiakException + */ byte[] getClientId() throws RiakException; + /** + * Create a new {@link FetchBucket} operation, and return it. + * + * @param bucketName + * @return a {@link FetchBucket} configured to return the {@link Bucket} called bucketName + * for further configuration and execution. + * @see FetchBucket + */ FetchBucket fetchBucket(String bucketName); - WriteBucket updateBucket(Bucket b); + /** + * Create a new {@link WriteBucket} operation to update passed bucket. + * @param bucket the name of the {@link Bucket}. + * @return a {@link WriteBucket} configured to update the supplied bucket + * for further configuration and execution. + * @see WriteBucket + */ + WriteBucket updateBucket(Bucket bucket); - WriteBucket createBucket(String string); + /** + * Create a new {@link WriteBucket} operation + * to create a {@link Bucket} named for the passed String. + * + * @param bucketName the name of the new bucket. + * @return a {@link WriteBucket} configured to create the new bucket + * for further configuration and execution. + * @see WriteBucket + */ + WriteBucket createBucket(String bucketName); - // query - links + /** + * Create a {@link LinkWalk} operation that starts at startObject. + * + * See also
Link Walking on the basho site. + * + * @param startObject the IRiakObject to start the Link walk from. + * @return a {@link LinkWalk} operation for further configuration and execution. + * @see LinkWalk + */ LinkWalk walk(final IRiakObject startObject); - // query - m/r - /** - * Map reduce over a set of bucket, key inputs + * Create {@link MapReduce} operation for a set of + * bucket/key inputs. + * + * See also Map Reduce on the basho site. + * @return a {@link BucketKeyMapReduce} for configuration and execution. + * @see MapReduce + * @see BucketKeyMapReduce */ BucketKeyMapReduce mapReduce(); /** - * Map reduce over a bucket - * @param bucket - * @return + * Create {@link MapReduce} operation that has the supplied bucket as its input. + * + * @param bucket the String name of the imput bucket to the M/R job. + * @return a {@link BucketMapReduce} for further configuration and execution. + * @see MapReduce + * @see BucketMapReduce */ BucketMapReduce mapReduce(String bucket); } diff --git a/src/main/java/com/basho/riak/client/IRiakObject.java b/src/main/java/com/basho/riak/client/IRiakObject.java index 34a411bc4..396fec9af 100644 --- a/src/main/java/com/basho/riak/client/IRiakObject.java +++ b/src/main/java/com/basho/riak/client/IRiakObject.java @@ -19,69 +19,207 @@ import java.util.Map.Entry; import com.basho.riak.client.cap.VClock; +import com.basho.riak.client.query.LinkWalk; /** - * Represents the data and meta data stored in Riak for bucket/key. + * Represents the data and meta data stored in Riak at a bucket/key. * - * NOTE: The name will be changing soon. The initial Java client release - * laid claim to the best name real estate. - * This class will be named RiakObject in subsequent releases. + *

+ * Although you can store your own Java Beans in Riak, this interface represents + * the core data type that is passed between the low and high level APIs and + * that all POJOs are converted to and from when stored or fetched. + *

+ * + *

+ * Extends {@link Iterable} to provide a simple way to iterate over the + * collection of {@link RiakLink}s. + *

+ * + *

+ * NOTE: The name will be changing soon. The initial Java client release laid + * claim to the best name real estate. This class will be named RiakObject in + * subsequent releases. + *

* - * @see DefaultRiakObject in the legacy project * @author russell * */ public interface IRiakObject extends Iterable { + /** + * The name of this objects bucket + * + * @return the bucket name. + */ String getBucket(); + /** + * The value. + * + * @return byte[] of this object value. + */ byte[] getValue(); + /** + * Convenience method. Will use the content-type to figure out the charset. + * + * @return the byte[] coerced to a String using the object's content-type + */ String getValueAsString(); + /** + * This objects Vector Clock. + * + * See the basho wiki + * for more on vector clocks + * + * @return the {@link VClock} for this object. + */ VClock getVClock(); + /** + * String copy of this object's vector clock. + * + * @return A String of this objects Vector Clock + */ + String getVClockAsString(); + + /** + * The object's key. + * + * @return The objects key. + */ String getKey(); + /** + * If this object has a version tag (if it is one of a set of siblings) + * + * @return the vtag, if present. + */ String getVtag(); + /** + * The last modified date as held by Riak. + * + * @return the last modified date as returned from Riak. + */ Date getLastModified(); + /** + * The content-type of this object's value. + * + * @return the Objects Content-Type. If you don't set this it defaults to + * {@link DefaultRiakObject#DEFAULT_CONTENT_TYPE} + */ String getContentType(); - // links + /** + * A List of {@link RiakLink}s from this object. See also Link Walking on the basho + * site. + * + * @return The List of RiakLinks from this object + * @see RiakLink + * @see LinkWalk + */ List getLinks(); + /** + * Does this object link to any others? + * + * @return true if this object has any links, false otherwise. + */ boolean hasLinks(); + /** + * How many {@link RiakLink}s does this object have. + * + * @return the number of links from this object. + */ int numLinks(); + /** + * Does this object have that link? + * + * @param riakLink + * a {@link RiakLink} + * @return true if this object's link collection contains the passed + * {@link RiakLink}, false otherwise. + */ boolean hasLink(final RiakLink riakLink); - // user meta + /** + * User meta data can be added to any Riak object. They are a String + * key/value pairs that are stored with the IRiakObject riak. + * + * See basho + * wiki for more details. + * + * @return the {@link Map} of meta data for this object. + */ Map getMeta(); + /** + * Does this object have any user meta data? + * + * @return if this IRiakObject has any user meta data items. + */ boolean hasUsermeta(); + /** + * Does this object have a meta data item for that key? + * + * @param key + * @return true if this IRiakObject's user meta data contains the supplied + * key + */ boolean hasUsermeta(String key); + /** + * Get the user meta data item for that key. + * + * @param key + * the name of the user meta data item + * @return a String of the user meta data item or null if no item present + * for the supplied key + */ String getUsermeta(String key); + /** + * An iterable view on the user meta entries. + * + * @return an iterable view of the set of user meta data. + * @see Entry + */ Iterable> userMetaEntries(); // Mutate - + /** + * Set this IRiakObject's value. + * + * @param value + * the byte[] to set. + */ void setValue(byte[] value); /** - * Convenience method that basically will result in - * value being turned into a byte[] array using charset utf-8 and also - * will result in charset=utf-8 being appended to the content-type for this object - * - * @param value the String value + * Convenience method that will result in value being turned into a byte[] + * array using charset utf-8 and also will result in charset=utf-8 being + * appended to the content-type for this object + * + * @param value + * the String value */ void setValue(String value); + /** + * Set the content-type of this object's payload. + * + * @param contentType + * the content-type of this object's value (EG + * text/plain;charset=utf-8) + */ void setContentType(String contentType); /** @@ -103,7 +241,7 @@ public interface IRiakObject extends Iterable { IRiakObject removeLink(final RiakLink link); /** - * Adds the key, value to the collection of user meta for this object. + * Adds the key, value to the collection of user meta data for this object. * * @param key * @param value @@ -112,14 +250,10 @@ public interface IRiakObject extends Iterable { IRiakObject addUsermeta(String key, String value); /** + * Remove that item of user meta data. + * * @param key * the key of the item to remove */ IRiakObject removeUsermeta(String key); - - /** - * @return A String of the VClock - */ - String getVClockAsString(); - } diff --git a/src/main/java/com/basho/riak/client/RiakException.java b/src/main/java/com/basho/riak/client/RiakException.java index 185f2fbb5..1fa28808a 100644 --- a/src/main/java/com/basho/riak/client/RiakException.java +++ b/src/main/java/com/basho/riak/client/RiakException.java @@ -38,4 +38,12 @@ public RiakException() { public RiakException(String message) { super(message); } + + /** + * @param message String + * @param cause + */ + public RiakException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/com/basho/riak/client/RiakFactory.java b/src/main/java/com/basho/riak/client/RiakFactory.java index 59dea5543..f7467c386 100644 --- a/src/main/java/com/basho/riak/client/RiakFactory.java +++ b/src/main/java/com/basho/riak/client/RiakFactory.java @@ -18,11 +18,18 @@ import com.basho.riak.client.raw.RawClient; import com.basho.riak.client.raw.http.HTTPClientAdapter; import com.basho.riak.client.raw.pbc.PBClientAdapter; +import com.basho.riak.pbc.RiakClient; /** - * A very basic factory for getting an IRiakClient implementation wrapping + * A *very* basic factory for getting an IRiakClient implementation wrapping * the {@link RawClient} of your choice. - * + *

+ * Also provides convenience methods for grabbing a default configuration pb or http client. + *

+ *

+ * NOTE: This class is under change, a single factory method that accepts a Configuration object will + * be available soon + *

* @author russell */ public class RiakFactory { @@ -30,7 +37,7 @@ public class RiakFactory { private static final String DEFAULT_RIAK_URL = "http://127.0.0.1:8098/riak"; /** - * + * Wraps a {@link PBClientAdapter} connected to 127.0.0.1:8087 in a {@link DefaultRiakClient}. * @return a default configuration PBC client * @throws RiakException */ @@ -46,9 +53,9 @@ public static IRiakClient pbcClient() throws RiakException { } /** - * Wraps the given pb client in IRiakFactory clothes. - * @param delegate - * @return a wrapped pb client + * Wraps the given {@link RiakClient} client in a {@link DefaultRiakClient}. + * @param delegate the pbc.{@link RiakClient} to wrap. + * @return a {@link DefaultRiakClient} that delegates to delegate */ public static IRiakClient pbcClient(com.basho.riak.pbc.RiakClient delegate) { final RawClient client = new PBClientAdapter(delegate); @@ -56,7 +63,8 @@ public static IRiakClient pbcClient(com.basho.riak.pbc.RiakClient delegate) { } /** - * @return a default configuration HTTP client + * Wraps a {@link HTTPClientAdapter} connecting to 127.0.0.1:8098/riak in a {@link DefaultRiakClient} + * @return a default configuration {@link DefaultRiakClient} delegating to the HTTP client */ public static IRiakClient httpClient() throws RiakException { final RawClient client = new HTTPClientAdapter(DEFAULT_RIAK_URL); @@ -64,7 +72,9 @@ public static IRiakClient httpClient() throws RiakException { } /** - * @return a wrapped http RiakClient + * Wraps the given {@link com.basho.riak.client.http.RiakClient} in a {@link DefaultRiakClient} + * @param delegate the http.{@link com.basho.riak.client.http.RiakClient} to wrap. + * @return a {@link DefaultRiakClient} that delegates to delegate */ public static IRiakClient httpClient(com.basho.riak.client.http.RiakClient delegate) throws RiakException { final RawClient client = new HTTPClientAdapter(delegate); diff --git a/src/main/java/com/basho/riak/client/RiakLink.java b/src/main/java/com/basho/riak/client/RiakLink.java index e61ecf034..ab214b7f7 100644 --- a/src/main/java/com/basho/riak/client/RiakLink.java +++ b/src/main/java/com/basho/riak/client/RiakLink.java @@ -14,8 +14,14 @@ package com.basho.riak.client; /** - * Immutable RiakLink - * + * Models a link from one object to another in Riak. + *

+ * Links are unidirectional and enable lightweight graph semantics in Riak. + * See the basho wiki for more details on links. + *

+ *

+ * Immutable. + *

* @author russell * */ @@ -29,9 +35,9 @@ public class RiakLink { * Create a RiakLink from the specified parameters. * * @param bucket - * the name of the bucket + * the bucket * @param key - * the key name + * the key * @param tag * the link tag */ @@ -53,14 +59,23 @@ public RiakLink(final RiakLink riakLink) { this.tag = riakLink.getTag(); } + /** + * @return the bucket + */ public String getBucket() { return bucket; } + /** + * @return the key + */ public String getKey() { return key; } + /** + * @return the tag + */ public String getTag() { return tag; } diff --git a/src/main/java/com/basho/riak/client/bucket/Bucket.java b/src/main/java/com/basho/riak/client/bucket/Bucket.java index 5f8f6b5a9..8ed557d0e 100644 --- a/src/main/java/com/basho/riak/client/bucket/Bucket.java +++ b/src/main/java/com/basho/riak/client/bucket/Bucket.java @@ -15,47 +15,161 @@ import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakException; +import com.basho.riak.client.convert.RiakKey; import com.basho.riak.client.operations.DeleteObject; import com.basho.riak.client.operations.FetchObject; +import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.operations.StoreObject; /** - * @author russell + * The primary interface for working with Key/Value data in Riak, a factory for key/value {@link RiakOperation}s. + *

+ * Provides convenience methods for creating {@link RiakOperation}s for storing + * byte[] and String data in Riak. Also provides + * methods for creating {@link RiakOperation}s for storing Java Bean style POJOs + * in Riak. A Bucket is a factory for {@link RiakOperation}s on Key/Value + * data. + *

+ *

+ * Gives access to all the {@link BucketProperties} that the underlying API + * transport exposes. NOTE: soon this will be *all* the {@link BucketProperties} + *

+ *

+ * Provides access to an {@link Iterable} for the keys in the bucket. + *

+ * + * @see StoreObject + * @see FetchObject + * @see DeleteObject * + * @author russell */ public interface Bucket extends BucketProperties { + /** + * Get this Buckets name. + * @return the name of the bucket + */ String getName(); /** - * Convenience method to create a RiakObject with a payload of application/octect-stream - * @param key - * @param value - * @return + * Creates a {@link StoreObject} that will store a new {@link IRiakObject}. + * + * @param key the key to store the data under. + * @param value the data as a byte[] + * @return a {@link StoreObject} + * @see StoreObject */ StoreObject store(String key, byte[] value); /** - * Convenience methods will assume payload is taxt/plain:charset=utf-8 - * @param key - * @param value - * @return + * Creates a {@link StoreObject} that will store a new {@link IRiakObject}. + * + * @param key the key to store the data under. + * @param value the data as a string + * @return a {@link StoreObject} + * @see StoreObject */ StoreObject store(String key, String value); + /** + * Creates a {@link StoreObject} for storing o of type + * T on execute(). T must have + * a field annotated with {@link RiakKey}. + * + * @param the Type of o + * @param o the data to store + * @return a {@link StoreObject} + * @see StoreObject + */ StoreObject store(T o); + /** + * Creates a {@link StoreObject} for storing o of type + * T at key on execute(). + * + * @param the Type of o + * @param o the data to store + * @param key the key + * @return a {@link StoreObject} + * @see StoreObject + */ StoreObject store(String key, T o); + /** + * Creates a {@link FetchObject} that returns the data at key + * as an {@link IRiakObject} on execute(). + * + * @param key the key + * @return a {@link FetchObject} + * @see FetchObject + */ FetchObject fetch(String key); + /** + * Creates a {@link FetchObject} operation that returns the data at + * key as an instance of type T on + * execute(). + * + * @param + * the Type to return + * @param key + * the key under which the data is stored + * @param type + * the Class of the type to return + * @return a {@link FetchObject} + * @see FetchObject + */ FetchObject fetch(String key, Class type); + /** + * Creates a {@link FetchObject} operation that returns the data at + * o's annotated {@link RiakKey} field as an instance of type + * T on execute(). + * + * @param + * the Type to return + * @param o + * an instance ot T that has the key annotated with + * {@link RiakKey} + * @return a {@link FetchObject} + * @see FetchObject + */ FetchObject fetch(T o); + /** + * Creates a {@link DeleteObject} operation that will delete the data at + * o's {@link RiakKey} annotated field value on + * execute(). + * + * @param + * the Type of o + * @param o + * an instance of T with a value for the key in the + * field annotated by {@link RiakKey} + * @return a {@link DeleteObject} + * @see DeleteObject + */ DeleteObject delete(T o); + /** + * Creates a {@link DeleteObject} operation that will delete the data at + * key on execute(). + * + * @param + * the Type of o + * @param o + * an instance of T with a value for the key in the + * field annotated by {@link RiakKey} + * @return a {@link DeleteObject} + * @see DeleteObject + */ DeleteObject delete(String key); + /** + * An {@link Iterable} view of the keys stored in this bucket. + * @return an {@link Iterable} of Strings. + * @throws RiakException + */ Iterable keys() throws RiakException; } diff --git a/src/main/java/com/basho/riak/client/bucket/BucketProperties.java b/src/main/java/com/basho/riak/client/bucket/BucketProperties.java index 8ae2b4d44..dcadebfce 100644 --- a/src/main/java/com/basho/riak/client/bucket/BucketProperties.java +++ b/src/main/java/com/basho/riak/client/bucket/BucketProperties.java @@ -20,95 +20,141 @@ import com.basho.riak.client.query.functions.NamedFunction; /** + * The set of properties for a bucket, things like n_val, allow_mult, default + * read quorum. + * + *

+ * Depending on what the underlying transport exposes some of these values will + * be null. I'm working on (a) updating the low-level clients to return all + * available values and (b) updating Riak's protocol buffers interface to return + * all the bucket properties. + *

+ * * @author russell * */ public interface BucketProperties { /** + * The allow_mult value for the bucket. + * * @return the allowSiblings if set, or null if not */ Boolean getAllowSiblings(); /** + * The last_write_wins value for the bucket. + * * @return the lastWriteWins if set or null if not */ Boolean getLastWriteWins(); /** + * This bucket's n_val. + * * @return the nVal if set or null if not */ Integer getNVal(); /** + * The backend used by this bucket. + * * @return the backend if set, or null. */ String getBackend(); /** + * the small_vclock property for this bucket. See controlling vector clock growth for details. * - * @return the small vclock pruning property if set, or null. + * @return the small vector clock pruning property if set, or null. */ - int getSmallVClock(); + Integer getSmallVClock(); /** + * the big_vclock property for this bucket. See controlling vector clock growth for details. * * @return the big vclock pruning size property if set, or null. */ - int getBigVClock(); + Integer getBigVClock(); /** + * The young_vclcok property for this bucket. See controlling vector clock growth for details. * * @return the young vclock prune property if set, or null. */ - long getYoungVClock(); + Long getYoungVClock(); /** + * the old_vclock property for this bucket. See controlling vector clock growth for details. * * @return the old vclock prune property if set, or null */ - long getOldVClock(); + Long getOldVClock(); /** - * @return the pre commit hooks, if any, or an empty collection. + * The set of precommit_hooks for this bucket. See pre and post + * commit hooks for more details. + * + * @return the precommit hooks, if any, or an empty collection. */ Collection getPrecommitHooks(); /** + * The set of postcommit hooks for this bucket. See pre and post + * commit hooks for more details. + * * @return the post commit hooks, if ant, or an empty collection. */ Collection getPostcommitHooks(); /** + * The default r quorum for this bucket. * * @return the default CAP read quorum for this bucket, or null. */ Quorum getR(); /** + * The default w quorum for this bucket. * * @return the default CAP write quorum for this bucket, or null. */ Quorum getW(); /** + * The default rw quorum for this bucket. * * @return the default CAP RW (delete) quorum for this bucket, or null. */ Quorum getRW(); /** + * The default dw quorum for this bucket. * * @return the default CAP durable write quorum for this bucket, or null. */ Quorum getDW(); /** + * The chash_keyfun for this bucket. + * * @return the key hashing function for the bucket, or null. */ NamedErlangFunction getChashKeyFunction(); /** + * The linkwalk_fun for this bucket. + * * @return the link walking function for the bucket, or null. */ NamedErlangFunction getLinkWalkFunction(); diff --git a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java index cada5e307..8f2fd59fa 100644 --- a/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucket.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.util.Collection; +import com.basho.riak.client.DefaultRiakClient; +import com.basho.riak.client.DefaultRiakObject; import com.basho.riak.client.IRiakObject; import com.basho.riak.client.RiakException; import com.basho.riak.client.builders.RiakObjectBuilder; @@ -26,14 +28,16 @@ import com.basho.riak.client.cap.Mutation; import com.basho.riak.client.cap.Quorum; import com.basho.riak.client.cap.Retrier; -import com.basho.riak.client.cap.VClock; -import com.basho.riak.client.convert.ConversionException; +import com.basho.riak.client.cap.UnresolvedConflictException; import com.basho.riak.client.convert.Converter; import com.basho.riak.client.convert.JSONConverter; import com.basho.riak.client.convert.NoKeySpecifedException; +import com.basho.riak.client.convert.PassThroughConverter; +import com.basho.riak.client.convert.RiakKey; import com.basho.riak.client.http.util.Constants; import com.basho.riak.client.operations.DeleteObject; import com.basho.riak.client.operations.FetchObject; +import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.operations.StoreObject; import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.query.functions.NamedFunction; @@ -41,8 +45,39 @@ import com.basho.riak.client.util.CharsetUtils; /** - * @author russell + * Default implementation of {@link Bucket} for creating {@link RiakOperation}s + * on k/v data and accessing {@link BucketProperties}. + * + *

+ * Obtain a {@link DefaultBucket} from {@link FetchBucket} or + * {@link WriteBucket} operations from + * {@link DefaultRiakClient#fetchBucket(String)}, + * {@link DefaultRiakClient#createBucket(String)} + *

+ *

+ *

+ *   final String bucketName = UUID.randomUUID().toString();
+ *   
+ *   Bucket b = client.createBucket(bucketName).execute();
+ *   //store something
+ *   IRiakObject o = b.store("k", "v").execute();
+ *   //fetch it back
+ *   IRiakObject fetched = b.fetch("k").execute();
+ *   // now update that riak object
+ *   b.store("k", "my new value").execute();
+ *   //fetch it back again
+ *   fetched = b.fetch("k").execute();
+ *   //delete it
+ *   b.delete("k").execute();
+ * 
+ *

+ * All operations created by instances of this class are configured with the + * {@link Retrier} and {@link RawClient} passed at construction. + *

* + * @author russell + * @see DomainBucket + * @see RiakBucket */ public class DefaultBucket implements Bucket { @@ -52,17 +87,22 @@ public class DefaultBucket implements Bucket { private final Retrier retrier; /** - * @param properties - * @param client + * All {@link RiakOperation}s created by this instance will use the + * {@link RawClient} and {@link Retrier} provided here. + * + * @param name this bucket's name + * @param properties the {@link BucketProperties} for this bucket + * @param client a {@link RawClient} to use for all {@link RiakOperation}s + * @param retrier a {@link Retrier} to use for all {@link RiakOperation}s */ - protected DefaultBucket(String name, BucketProperties properties, RawClient client, final Retrier retrier) { + protected DefaultBucket(String name, final BucketProperties properties, final RawClient client, final Retrier retrier) { this.name = name; this.properties = properties; this.client = client; this.retrier = retrier; } - // / BUCKET PROPS + // BUCKET PROPS /* * (non-Javadoc) @@ -114,7 +154,7 @@ public String getBackend() { * * @see com.basho.riak.newapi.bucket.BucketProperties#getSmallVClock() */ - public int getSmallVClock() { + public Integer getSmallVClock() { return properties.getSmallVClock(); } @@ -123,7 +163,7 @@ public int getSmallVClock() { * * @see com.basho.riak.newapi.bucket.BucketProperties#getBigVClock() */ - public int getBigVClock() { + public Integer getBigVClock() { return properties.getBigVClock(); } @@ -132,7 +172,7 @@ public int getBigVClock() { * * @see com.basho.riak.newapi.bucket.BucketProperties#getYoungVClock() */ - public long getYoungVClock() { + public Long getYoungVClock() { return properties.getYoungVClock(); } @@ -141,7 +181,7 @@ public long getYoungVClock() { * * @see com.basho.riak.newapi.bucket.BucketProperties#getOldVClock() */ - public long getOldVClock() { + public Long getOldVClock() { return properties.getOldVClock(); } @@ -217,10 +257,16 @@ public NamedErlangFunction getLinkWalkFunction() { return properties.getLinkWalkFunction(); } - // / BUCKET + // BUCKET /** - * Iterate over the keys for this bucket (Expensive, are you sure?) + * Iterate over the keys for this bucket (Expensive, are you sure?) Beware: + * at present all {@link RawClient#listKeys(String)} operations return a + * stream of keys. The stream is closed automatically when the iteratore is + * weakly reachable. Do not retain a reference to this {@link Iterable} + * after you have used it. + * + * @see RawClient#listKeys(String) */ public Iterable keys() throws RiakException { try { @@ -230,11 +276,41 @@ public Iterable keys() throws RiakException { } } - /* - * (non-Javadoc) + /** + * Convenience method to create a RiakObject with a payload of + * application/octect-stream + *

+ * For example, to get a new {@link IRiakObject} into Riak.

+     * IRiakObject myNewObject = bucket.store("k", myByteArray)
+     *                              .w(2)  // tunable CAP write quorum
+     *                              .returnBody(true) // return the IRiakObject from the store
+     *                              .execute(); // perform the operation.
+     * 
+ *

+ *

+ * Creates a {@link StoreObject} operation configured with a + * {@link Mutation} that copies value and + * {@link DefaultRiakObject#DEFAULT_CONTENT_TYPE} over the any existing + * value at key or creates a new {@link DefaultRiakObject} with + * value and {@link DefaultRiakObject#DEFAULT_CONTENT_TYPE}. + *

+ *

+ * The {@link StoreObject} is configured with the {@link DefaultResolver} + * which means the presence of siblings triggers a + * {@link UnresolvedConflictException} + *

+ *

+ * The {@link StoreObject} is configured with a {@link Converter} that + * simply returns what it is given (IE does no conversion). + *

* - * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, - * java.lang.String) + * @param key + * the key to store the object under. + * @param value + * a byte[] of the objects value. + * @return a {@link StoreObject} configured to store value at + * key on execute(). + * @see StoreObject */ public StoreObject store(final String key, final byte[] value) { @@ -247,23 +323,48 @@ public IRiakObject apply(IRiakObject original) { return original; } } - }).withResolver(new DefaultResolver()).withConverter(new Converter() { - - public IRiakObject toDomain(IRiakObject riakObject) { - return riakObject; - } - - public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { - return domainObject; - } - }); + }).withResolver(new DefaultResolver()).withConverter(new PassThroughConverter()); } - /* (non-Javadoc) - * @see com.basho.riak.client.bucket.Bucket#store(java.lang.String, java.lang.String) + /** + * Convenience methods will create an {@link IRiakObject} with + * value as the data payload and + * text/plain:charset=utf-8 as the contentType + *

+ * For example, to get a new {@link IRiakObject} into Riak.

+     * IRiakObject myNewObject = bucket.store("k", "myValue")
+     *                              .w(2)  // tunable CAP write quorum
+     *                              .returnBody(true) // return the IRiakObject from the store
+     *                              .execute(); // perform the operation.
+     * 
+ *

+ *

+ * Creates a {@link StoreObject} operation configured with a + * {@link Mutation} that copies value and + * {@link Constants#CTYPE_TEXT_UTF8} over the any existing + * value at key or creates a new {@link DefaultRiakObject} with + * value and {@link Constants#CTYPE_TEXT_UTF8}. + *

+ *

+ * The {@link StoreObject} is configured with the {@link DefaultResolver} + * which means the presence of siblings triggers a + * {@link UnresolvedConflictException} + *

+ *

+ * The {@link StoreObject} is configured with a {@link Converter} that + * simply returns what it is given (IE does no conversion). + *

+ * + * @param key + * the key to store the object under. + * @param value + * a String of the data to store + * @return a {@link StoreObject} configured to store value at + * key on execute(). + * @see StoreObject */ public StoreObject store(final String key, final String value) { - return new StoreObject(client, name, key, retrier).withMutator(new Mutation() { + final Mutation m = new Mutation() { public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(name, key).withValue(value).withContentType(Constants.CTYPE_TEXT_UTF8).build(); @@ -273,22 +374,35 @@ public IRiakObject apply(IRiakObject original) { return original; } } - }).withResolver(new DefaultResolver()).withConverter(new Converter() { - - public IRiakObject toDomain(IRiakObject riakObject) { - return riakObject; - } + }; - public IRiakObject fromDomain(IRiakObject domainObject, VClock vclock) throws ConversionException { - return domainObject; - } - }); + return store(key, CharsetUtils.utf8StringToBytes(value)).withMutator(m); } - /* - * (non-Javadoc) + /** + * Store an instance of T in Riak. Depends on the + * {@link Converter} provided to {@link StoreObject} to convert + * o from T to {@link IRiakObject}. + *

+ * T must have a field annotated with {@link RiakKey} as the + * Key to store this data under. + *

* - * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.Object) + *

+ * Creates a {@link StoreObject} operation configured with the + * {@link JSONConverter} the {@link ClobberMutation} and + * {@link DefaultResolver}. + *

+ * + * @param + * the Type of o + * @param o + * the data to store + * @return a {@link StoreObject} configured to store o at the + * {@link RiakKey} annotated key on + * execute(). + * @see StoreObject + * @see DomainBucket */ public StoreObject store(final T o) { @SuppressWarnings("unchecked") Class clazz = (Class) o.getClass(); @@ -302,11 +416,26 @@ public StoreObject store(final T o) { .withResolver(new DefaultResolver()); } - /* - * (non-Javadoc) + /** + * Store an instance of T in Riak. Depends on the + * {@link Converter} provided to {@link StoreObject} to convert + * o from T to {@link IRiakObject}. + * + *

+ * Creates a {@link StoreObject} operation configured with the + * {@link JSONConverter} the {@link ClobberMutation} and + * {@link DefaultResolver}. + *

* - * @see com.basho.riak.newapi.bucket.Bucket#store(java.lang.String, - * java.lang.Object) + * @param + * the Type of o + * @param o + * the data to store + * @return a {@link StoreObject} configured to store o at the + * {@link RiakKey} annotated key on + * execute(). + * @see StoreObject + * @see DomainBucket */ public StoreObject store(final String key, final T o) { @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); @@ -316,10 +445,23 @@ public StoreObject store(final String key, final T o) { .withMutator(new ClobberMutation(o)).withResolver(new DefaultResolver()); } - /* - * (non-Javadoc) + /** + * Creates a {@link FetchObject} operation that returns the data at + * o's annotated {@link RiakKey} field as an instance of type + * T on execute(). + *

+ * Creates a {@link FetchObject} operation configured with the + * {@link JSONConverter} and + * {@link DefaultResolver}. + *

* - * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.Object) + * @param + * the Type to return + * @param o + * an instance ot T that has the key annotated with + * {@link RiakKey} + * @return a {@link FetchObject} + * @see FetchObject */ public FetchObject fetch(T o) { @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); @@ -332,11 +474,25 @@ public FetchObject fetch(T o) { .withResolver(new DefaultResolver()); } - /* - * (non-Javadoc) + /** + * Creates a {@link FetchObject} operation that returns the data at + * key as an instance of type T on + * execute(). + * + *

+ * Creates a {@link FetchObject} operation configured with the + * {@link JSONConverter} and + * {@link DefaultResolver}. + *

* - * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String, - * java.lang.Class) + * @param + * the Type to return + * @param key + * the key under which the data is stored + * @param type + * the Class of the type to return + * @return a {@link FetchObject} + * @see FetchObject */ public FetchObject fetch(final String key, final Class type) { return new FetchObject(client, name, key, retrier) @@ -344,26 +500,23 @@ public FetchObject fetch(final String key, final Class type) { .withResolver(new DefaultResolver()); } - /* - * (non-Javadoc) + /** + * Creates a {@link FetchObject} that returns the data at key + * as an {@link IRiakObject} on execute(). * - * @see com.basho.riak.newapi.bucket.Bucket#fetch(java.lang.String) + *

+ * Creates a {@link FetchObject} with the {@link DefaultResolver} and a {@link Converter} + * that does nothing to the {@link IRiakObject}. + *

+ * + * @param key the key + * @return a {@link FetchObject} + * @see FetchObject */ public FetchObject fetch(String key) { return new FetchObject(client, name, key, retrier) .withResolver(new DefaultResolver()) - .withConverter(new Converter() { - - public IRiakObject toDomain(IRiakObject riakObject) { - return riakObject; - } - - public IRiakObject fromDomain(IRiakObject domainObject, - VClock vclock) - throws ConversionException { - return RiakObjectBuilder.from(domainObject).withVClock(vclock).build(); - } - }); + .withConverter(new PassThroughConverter()); } /* diff --git a/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java index 4119a0e14..b43e09406 100644 --- a/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java +++ b/src/main/java/com/basho/riak/client/bucket/DefaultBucketProperties.java @@ -15,17 +15,25 @@ import java.util.Collection; +import com.basho.riak.client.IRiakClient; import com.basho.riak.client.builders.BucketPropertiesBuilder; import com.basho.riak.client.cap.Quorum; import com.basho.riak.client.query.functions.NamedErlangFunction; import com.basho.riak.client.query.functions.NamedFunction; /** - * Since not all interfaces to Riak are equal in terms of what they provide not - * all RawClients can be expected to set all values. Which means that *any* of - * the getters may return null. + * An immutable implementation of {@link BucketProperties}. * + *

+ * Use {@link BucketPropertiesBuilder} if you really have to make one, but your + * better to fetch one like with {@link IRiakClient#fetchBucket(String)} or create one with + * {@link IRiakClient#createBucket(String)} + *

* @author russell + * + * @see IRiakClient + * @see WriteBucket + * @see FetchBucket */ public class DefaultBucketProperties implements BucketProperties { @@ -47,22 +55,8 @@ public class DefaultBucketProperties implements BucketProperties { private final NamedErlangFunction linkWalkFunction; /** - * @param allowSiblings - * @param lastWriteWins - * @param nVal - * @param backend - * @param smallVClock - * @param bigVClock - * @param youngVClock - * @param oldVClock - * @param precommitHooks - * @param postcommitHooks - * @param r - * @param w - * @param dw - * @param rw - * @param chashKeyFunction - * @param linkWalkFunction + * Construct from the given {@link BucketPropertiesBuilder} + * @param builder */ public DefaultBucketProperties(final BucketPropertiesBuilder builder) { this.allowSiblings = builder.allowSiblings; @@ -83,128 +77,120 @@ public DefaultBucketProperties(final BucketPropertiesBuilder builder) { this.linkWalkFunction = builder.linkWalkFunction; } - /** - * @return the allowSiblings if set, or null if not + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getAllowSiblings() */ public Boolean getAllowSiblings() { return allowSiblings; } - /** - * @return the lastWriteWins if set or null if not + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getLastWriteWins() */ public Boolean getLastWriteWins() { return lastWriteWins; } - /** - * @return the nVal if set or null if not + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getNVal() */ public Integer getNVal() { return nVal; } - /** - * @return the backend if set, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getBackend() */ public String getBackend() { return backend; } - /** - * - * @return the small vclock pruning property if set, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getSmallVClock() */ - public int getSmallVClock() { + public Integer getSmallVClock() { return smallVClock; } - /** - * - * @return the big vclock pruning size property if set, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getBigVClock() */ - public int getBigVClock() { + public Integer getBigVClock() { return bigVClock; } - /** - * - * @return the young vclock prune property if set, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getYoungVClock() */ - public long getYoungVClock() { + public Long getYoungVClock() { return youngVClock; } - /** - * - * @return the old vclock prune property if set, or null + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getOldVClock() */ - public long getOldVClock() { + public Long getOldVClock() { return oldVClock; } - /** - * @return the pre commit hooks, if any, or an empty collection. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getPrecommitHooks() */ public Collection getPrecommitHooks() { return precommitHooks; } - /** - * @return the post commit hooks, if ant, or an empty collection. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getPostcommitHooks() */ public Collection getPostcommitHooks() { return postcommitHooks; } - /** - * - * @return the default CAP read quorum for this bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getR() */ public Quorum getR() { return r; } - /** - * - * @return the default CAP write quorum for this bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getW() */ public Quorum getW() { return w; } - /** - * - * @return the default CAP RW (delete) quorum for this bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getRW() */ public Quorum getRW() { return rw; } - /** - * - * @return the default CAP durable write quorum for this bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getDW() */ public Quorum getDW() { return dw; } - /** - * @return the key hashing function for the bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getChashKeyFunction() */ public NamedErlangFunction getChashKeyFunction() { return chashKeyFunction; } - /** - * @return the link walking function for the bucket, or null. + /* (non-Javadoc) + * @see com.basho.riak.client.bucket.BucketProperties#getLinkWalkFunction() */ public NamedErlangFunction getLinkWalkFunction() { return linkWalkFunction; } /** - * + * Create a {@link BucketPropertiesBuilder} populated with my values. * @return a Builder populated from this BucketProperties' values. */ public BucketPropertiesBuilder fromMe() { @@ -212,6 +198,8 @@ public BucketPropertiesBuilder fromMe() { } /** + * Create a {@link BucketPropertiesBuilder} populated from the given + * {@link DefaultBucketProperties}. * * @param properties * @return a Builder populated with properties values. diff --git a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java index acca8e41b..f869bb77e 100644 --- a/src/main/java/com/basho/riak/client/bucket/DomainBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/DomainBucket.java @@ -21,13 +21,54 @@ import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.convert.Converter; import com.basho.riak.client.convert.KeyUtil; +import com.basho.riak.client.convert.RiakKey; +import com.basho.riak.client.operations.DeleteObject; +import com.basho.riak.client.operations.FetchObject; +import com.basho.riak.client.operations.StoreObject; /** - * A domain bucket is a wrapper around a bucket that is strongly typed uses a - * preset resolver, mutation producer, converter, r, w, dw, rw, retrier, + * A domain bucket is a wrapper around a {@link Bucket} that is strongly typed and uses + * a preset {@link ConflictResolver}, {@link MutationProducer}, {@link Converter}, r, w, dw, rw, {@link Retrier}, * returnBody etc * + *

+ * If you are working with one specific type of data only it can be simpler to + * create a {@link DomainBucket} around your bucket. It reduces the amount of + * code since the {@link Converter}, {@link Mutation}, {@link Retrier} and + * {@link ConflictResolver} are likely to be the same for each operation. + *

+ *

+ * Example: + *

+ * final Bucket b = client.createBucket(bucketName).allowSiblings(true).nVal(3).execute();
+ * 
+ * final DomainBucket carts = DomainBucket.builder(b, ShoppingCart.class)
+ *          .withResolver(new MergeCartResolver())
+ *          .returnBody(true)
+ *          .retrier(DefaultRetrier.attempts(3))
+ *          .w(1)
+ *          .dw(1)
+ *          .r(1)
+ *          .rw(1)
+ *          .build();
+ * 
+ *  final ShoppingCart cart = new ShoppingCart(userId);
+ * 
+ *  cart.addItem("coffee");
+ *  cart.addItem("fixie");
+ *  cart.addItem("moleskine");
+ * 
+ *  final ShoppingCart storedCart = carts.store(cart);
+ *  ShoppinCart cart2 = carts.fetch("userX");
+ *  cart.addItem("toaster");
+ *  carts.store(cart2);
+ *  //etc
+ * 
+ *

+ * * @author russell + * @see RiakBucket + * @see DomainBucketBuilder * */ public class DomainBucket { @@ -44,18 +85,21 @@ public class DomainBucket { private final Class clazz; private final Retrier retrier; + /** - * @param bucket - * @param resolver - * @param converter - * @param mutation - * @param w - * @param dw - * @param r - * @param rw - * @param returnBody - * @param retries - * @param clazz + * Create a new {@link DomainBucket} for clazz Class objects wrapped around bucket + * + * @param bucket The bucket to wrap. + * @param resolver the {@link ConflictResolver} + * @param converter the {@link Converter} to use + * @param mutationProducer the {@link MutationProducer} to use + * @param w the write quorum for store operations. + * @param dw the durable_write quorum for store operations + * @param r the read quorum for fetch (and store) operations + * @param rw the read_write quorum for delete operations + * @param returnBody boolean for wether to return body on store operations + * @param clazz the Class type of the DomainBucket + * @param retrier the {@link Retrier} to use for each operation */ public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter converter, MutationProducer mutationProducer, Integer w, Integer dw, Integer r, Integer rw, boolean returnBody, @@ -73,6 +117,23 @@ public DomainBucket(Bucket bucket, ConflictResolver resolver, Converter co this.retrier = retrier; } + /** + * Store o in Riak. + * T must have a field annotated with {@link RiakKey}. + * + *

+ * This is equivalent to creating and executing a {@link StoreObject} + * operation with the {@link Converter}, {@link ConflictResolver}, + * {@link Retrier}, and a {@link Mutation} (from calling + * {@link MutationProducer#produce(Object)} on o), r, w, dw + * etc. passed when the DomainBucket was constructed. + *

+ * + * @param o + * instance of to store. + * @return stored instance of T + * @throws RiakException + */ public T store(T o) throws RiakException { final Mutation mutation = mutationProducer.produce(o); return bucket.store(o) @@ -87,27 +148,84 @@ public T store(T o) throws RiakException { .execute(); } + /** + * Fetch data stored at key in this bucket as an instance of + * T. + * + *

+ * This is equivalent to creating and executing a {@link FetchObject} + * configured with the {@link Converter}, {@link ConflictResolver}, + * {@link Retrier} and r value specified in the constructor. + *

+ * + * @param key + * @return + * @throws RiakException + */ public T fetch(String key) throws RiakException { return bucket.fetch(key, clazz).withConverter(converter).withResolver(resolver).r(r).retrier(retrier).execute(); } + /** + * Fetch data stored at the key extracted from o's + * {@link RiakKey} annotated field as an instance of + * T. + * + *

+ * This is equivalent to creating and executing a {@link FetchObject} + * configured with the {@link Converter}, {@link ConflictResolver}, + * {@link Retrier} and r value specified in the constructor. + *

+ * + * @param key + * @return + * @throws RiakException + */ public T fetch(T o) throws RiakException { return bucket.fetch(o).withConverter(converter).withResolver(resolver).r(r).retrier(retrier).execute(); } + /** + * Delete the key/value stored at the key extracted from o's + * {@link RiakKey} annotated field. + * + *

+ * This is equivalent to creating and executing a {@link DeleteObject} + * configured with the {@link Retrier} and r value specified in the + * constructor. + *

+ * + * @param key + * @return + * @throws RiakException + */ public void delete(T o) throws RiakException { final String key = KeyUtil.getKey(o); delete(key); } + /** + * Delete the key/value stored at the key + * + *

+ * This is equivalent to creating and executing a {@link DeleteObject} + * configured with the {@link Retrier} and r value specified in the + * constructor. + *

+ * + * @param key + * @return + * @throws RiakException + */ public void delete(String key) throws RiakException { - bucket.delete(key).rw(rw).execute(); + bucket.delete(key).retrier(retrier).rw(rw).execute(); } /** + * Factory method to create a new {@link DomainBucketBuilder} for the given {@link Bucket} and Class. * @param b * the Bucket to wrap - * @param clazz + * @param clazz the type of object to store/fetch with the new {@link DomainBucket} * @return a DomainBucketBuilder for the wrapped bucket */ public static DomainBucketBuilder builder(Bucket b, Class clazz) { diff --git a/src/main/java/com/basho/riak/client/bucket/FetchBucket.java b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java index 4617601fe..95303ffec 100644 --- a/src/main/java/com/basho/riak/client/bucket/FetchBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/FetchBucket.java @@ -17,12 +17,28 @@ import com.basho.riak.client.RiakRetryFailedException; import com.basho.riak.client.cap.Retrier; +import com.basho.riak.client.http.RiakClient; import com.basho.riak.client.operations.RiakOperation; import com.basho.riak.client.raw.RawClient; /** - * @author russell + * A {@link RiakOperation} that gets a {@link Bucket} from Riak. * + *

+ * Calls the underlying {@link RiakClient}s fetch method via the {@link Retrier} + * attempt method, builds a {@link Bucket} from the response. + *

+ *

+ * Example: + *

+ *   final String bucketName = "userAccounts";
+ *   // fetch a bucket
+ *   Bucket b = client.fetchBucket(bucketName).execute();
+ *   // use the bucket
+ *   IRiakObject o = b.store("k", "v").execute();
+ * 
+ *

+ * @author russell */ public class FetchBucket implements RiakOperation { @@ -32,10 +48,13 @@ public class FetchBucket implements RiakOperation { private Retrier retrier; /** - * @param client - * @param bucket + * Create a FetchBucket that delegates to the provided {@link RawClient}. + * + * @param client the {@link RawClient} to use when fetching the bucket data. + * @param bucket the name of the bucket to fetch. + * @param retrier the {@link Retrier} to use when fetching bucket data. */ - public FetchBucket(RawClient client, String bucket, final Retrier retrier) { + public FetchBucket(final RawClient client, String bucket, final Retrier retrier) { this.client = client; this.bucket = bucket; this.retrier = retrier; @@ -43,6 +62,8 @@ public FetchBucket(RawClient client, String bucket, final Retrier retrier) { /** * Execute the fetch operation using the RawClient + * @return a {@link Bucket} configured to use this instances {@link RawClient} and {@link Retrier} for its operations + * @throws RiakRetryFailedException if the {@link Retrier} throws {@link RiakRetryFailedException} */ public Bucket execute() throws RiakRetryFailedException { BucketProperties properties = retrier.attempt(new Callable() { @@ -55,9 +76,9 @@ public BucketProperties call() throws Exception { } /** - * Provide a retrier to use for the fetch operation. + * Provide a {@link Retrier} to use for the fetch operation. * - * @param retrier the Retrier to use + * @param retrier the {@link Retrier} to use * @return this */ public FetchBucket retrier(final Retrier retrier) { diff --git a/src/main/java/com/basho/riak/client/bucket/RiakBucket.java b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java index 3b0ffeb46..d6c98c600 100644 --- a/src/main/java/com/basho/riak/client/bucket/RiakBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/RiakBucket.java @@ -17,12 +17,21 @@ import com.basho.riak.client.RiakException; import com.basho.riak.client.builders.DomainBucketBuilder; import com.basho.riak.client.builders.RiakObjectBuilder; +import com.basho.riak.client.cap.ConflictResolver; +import com.basho.riak.client.cap.Retrier; import com.basho.riak.client.cap.VClock; import com.basho.riak.client.convert.ConversionException; import com.basho.riak.client.convert.Converter; /** - * A DomainBucket for convenience. + * Wraps a {@link DomainBucket} strongly typed for IRiakObject. + * + *

+ * A convenience class stroring , retrieving {@link IRiakObject} from Riak + * without specifying a pass through {@link Converter} for each operation. + *

+ * + * TODO add per operation CAP properties. Add {@link Retrier} and {@link ConflictResolver}. * @author russell * */ diff --git a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java index 64baabb76..47251ef4d 100644 --- a/src/main/java/com/basho/riak/client/bucket/WriteBucket.java +++ b/src/main/java/com/basho/riak/client/bucket/WriteBucket.java @@ -26,6 +26,22 @@ import com.basho.riak.client.raw.RawClient; /** + * A {@link RiakOperation} for creating/updating a {@link Bucket}. + * + *

+ * This class is a fluid builder for creating a {@link RiakOperation} that sets + * bucket properties on a bucket in Riak. It delegates to a + * {@link BucketPropertiesBuilder} then uses its {@link RawClient} and + * {@link Retrier} to set the bucket properties in Riak. + *

+ *

+ * NOTE: all the parameters on the builder are optional. If omitted then the + * Riak defaults will be used. Also, very few of these properties are supported + * by either underlying API at present. They are here for completeness sake. + * Changes are underway to support all the properties. Check the docs for the + * individual parameters to see what is supported. + *

+ * * @author russell * */ @@ -37,16 +53,21 @@ public class WriteBucket implements RiakOperation { private BucketPropertiesBuilder builder = new BucketPropertiesBuilder(); + /** + * Create WriteBucket operation that delegates to the given {@link RawClient} via the give {@link Retrier}. + * @param client the {@link RawClient} to delegate to + * @param name the name of the bucket to create/update + * @param retrier the {@link Retrier} to use + */ public WriteBucket(final RawClient client, String name, final Retrier retrier) { this.name = name; this.client = client; this.retrier = retrier; } - /* - * (non-Javadoc) - * - * @see com.basho.riak.client.RiakOperation#execute() + /** + * Creates/updates a Bucket in Riak with the set of properties configured. + * @return the {@link Bucket} */ public Bucket execute() throws RiakRetryFailedException { final BucketProperties propsToStore = builder.build(); @@ -67,111 +88,241 @@ public BucketProperties call() throws Exception { return new DefaultBucket(name, properties, client, retrier); } + /** + * Should the bucket have allow_mult set to true? + * @param allowSiblings + * @return this + */ public WriteBucket allowSiblings(boolean allowSiblings) { builder.allowSiblings(allowSiblings); return this; } + /** + * Is this bucket last_write_wins? + * NOTE: at present this is not supported so has no effect. + * @param lastWriteWins + * @return this + */ public WriteBucket lastWriteWins(boolean lastWriteWins) { builder.lastWriteWins(lastWriteWins); return this; } + /** + * The n_val for this bucket + * @param nVal + * @return this + */ public WriteBucket nVal(int nVal) { builder.nVal(nVal); return this; } + /** + * Which backend this bucket uses. + * NOTE: at present this is not supported so has no effect. + * @param backend + * @return this + */ public WriteBucket backend(String backend) { builder.backend(backend); return this; } + /** + * A Collection of precommit hooks for this bucket + * NOTE: at present this is not supported so has no effect. + * @param precommitHooks + * @return + */ public WriteBucket precommitHooks(Collection precommitHooks) { builder.precommitHooks(precommitHooks); return this; } + /** + * Add a precommit hook to the Collection of hooks to be written. + * NOTE: at present this is not supported so has no effect. + * @param preCommitHook + * @return this + */ public WriteBucket addPrecommitHook(NamedFunction preCommitHook) { builder.addPrecommitHook(preCommitHook); return this; } + /** + * Add a collection of postcommit hooks to the bucket to be written. + * NOTE: at present this is not supported so has no effect. + * @param postCommitHooks + * @return + */ public WriteBucket postcommitHooks(Collection postCommitHooks) { builder.postcommitHooks(postCommitHooks); return this; } + /** + * Add a postcommit hook to the Collection of post commit hooks for the bucket to written. + * NOTE: at present this is not supported so has no effect. + * @param postcommitHook + * @return + */ public WriteBucket addPostcommitHook(NamedErlangFunction postcommitHook) { builder.addPostcommitHook(postcommitHook); return this; } + /** + * Set the chash_key_fun on the bucket to be written + * NOTE: at present this is not supported by the PB API and has no effect for that client. + * @param chashKeyFunction + * @return + */ public WriteBucket chashKeyFunction(NamedErlangFunction chashKeyFunction) { builder.chashKeyFunction(chashKeyFunction); return this; } + /** + * Set the link_walk_fun used by Riak on the bucket to be written. + * NOTE: at present this is not supported by the PB API and has no effect for that client. + * @param linkWalkFunction + * @return + */ public WriteBucket linkWalkFunction(NamedErlangFunction linkWalkFunction) { builder.linkWalkFunction(linkWalkFunction); return this; } + /** + * set the small vclock prune size + * NOTE: at present this is not supported so has no effect. + * @param smallVClock + * @return + */ public WriteBucket smallVClock(int smallVClock) { builder.smallVClock(smallVClock); return this; } + /** + * set the big_vclock prune size + * NOTE: at present this is not supported so has no effect. + * @param bigVClock + * @return + */ public WriteBucket bigVClock(int bigVClock) { builder.bigVClock(bigVClock); return this; } + /** + * set the young_vclock prune age + * NOTE: at present this is not supported so has no effect. + * @param youngVClock + * @return + */ public WriteBucket youngVClock(long youngVClock) { builder.youngVClock(youngVClock); return this; } + /** + * set the old_vclock prune age + * NOTE: at present this is not supported so has no effect. + * @param oldVClock + * @return + */ public WriteBucket oldVClock(long oldVClock) { builder.oldVClock(oldVClock); return this; } + /** + * The default r Quorom for the bucket + * NOTE: at present this is not supported so has no effect. + * @param r + * @return + */ public WriteBucket r(Quora r) { builder.r(r); return this; } + /** + * The default r quorom as an int + * NOTE: at present this is not supported so has no effect. + * @param r + * @return + */ public WriteBucket r(int r) { builder.r(r); return this; } + /** + * The default w quorom + * NOTE: at present this is not supported so has no effect. + * @param w + * @return + */ public WriteBucket w(Quora w) { builder.w(w); return this; } + /** + * The default w quorom as an int + * NOTE: at present this is not supported so has no effect. + * @param w + * @return + */ public WriteBucket w(int w) { builder.w(w); return this; } + /** + * The default rw quorom + * NOTE: at present this is not supported so has no effect. + * @param rw + * @return + */ public WriteBucket rw(Quora rw) { builder.rw(rw); return this; } + /** + * The default rw quorom as an int + * NOTE: at present this is not supported so has no effect. + * @param rw + * @return + */ public WriteBucket rw(int rw) { builder.rw(rw); return this; } + /** + * The default dw quorom + * NOTE: at present this is not supported so has no effect. + * @param dw + * @return + */ public WriteBucket dw(Quora dw) { builder.dw(dw); return this; } + /** + * The default dw quorom as an int + * NOTE: at present this is not supported so has no effect. + * @param dw + * @return + */ public WriteBucket dw(int dw) { builder.dw(dw); return this; diff --git a/src/main/java/com/basho/riak/client/bucket/package-info.java b/src/main/java/com/basho/riak/client/bucket/package-info.java new file mode 100644 index 000000000..134ad1976 --- /dev/null +++ b/src/main/java/com/basho/riak/client/bucket/package-info.java @@ -0,0 +1,64 @@ +/* + * This file is provided 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. + */ +/** + * A bucket is a namespace abstraction provided by Riak, the API uses + * {@link com.basho.riak.client.bucket.Bucket} as the primary way to interact + * with data stored in Riak. + *

+ * All data in Riak is stored under a bucket/key namespace. After you have + * obtained a {@link com.basho.riak.client.bucket.Bucket} from the + * {@link com.basho.riak.client.IRiakClient}, use it to fetch, store and delete + * data. + *

+ *

+ * For example + * + * + *

+ * 
+ *   final String bucketName = UUID.randomUUID().toString();
+ *   
+ *   Bucket b = client.fetchBucket(bucketName).execute();
+ *   //store something
+ *   IRiakObject o = b.store("k", "v").execute();
+ *   //fetch it back
+ *   IRiakObject fetched = b.fetch("k").execute();
+ *   // now update that riak object
+ *   b.store("k", "my new value").execute();
+ *   //fetch it back again
+ *   fetched = b.fetch("k").execute();
+ *   //delete it
+ *   b.delete("k").execute();
+ * 
+ *

+ *

+ * {@link com.basho.riak.client.bucket.Bucket} extends the + * {@link com.basho.riak.client.bucket.BucketProperties} interface for access to + * bucket schema information (like n_val, allow_mult, + * default r quorum etc.) + *

+ *

+ * This package also provides a {@link com.basho.riak.client.bucket.DomainBucket} for + * wrapping a {@link com.basho.riak.client.bucket.Bucket}. A + * {@link com.basho.riak.client.bucket.DomainBucket} simplifies working with a + * bucket that only has one type of data in it. + * {@link com.basho.riak.client.bucket.RiakBucket} is a + * {@link com.basho.riak.client.bucket.DomainBucket} for working with + * {@link com.basho.riak.client.IRiakObject}s. + * + * @see com.basho.riak.client.bucket.Bucket + * @see com.basho.riak.client.bucket.DomainBucket + * @see com.basho.riak.client.bucket.RiakBucket + */ +package com.basho.riak.client.bucket; \ No newline at end of file diff --git a/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java b/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java index cde3a10e2..910b00765 100644 --- a/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/BucketPropertiesBuilder.java @@ -11,7 +11,11 @@ import com.basho.riak.client.query.functions.NamedFunction; /** - * Use to create instances of BucketProperties. + * Used to create instances of {@link BucketProperties}. + * + *

+ * All parameters are optional, only nVal has a default value (3) + *

* * @author russell * diff --git a/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java index a1b1fb6aa..fca66b3e0 100644 --- a/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java +++ b/src/main/java/com/basho/riak/client/builders/DomainBucketBuilder.java @@ -26,6 +26,16 @@ import com.basho.riak.client.convert.JSONConverter; /** + * For creating a {@link DomainBucket} + * + *

+ * Defaults are as follows: + *