Skip to content

Commit fe8d1da

Browse files
author
Luis Sanchez
committed
[FAB-3311] java cc get history for key
- new KeyModification type - QueryResultsIterator<KeyModification> ChaincodeStub.getHistoryForKey(key) - QueryResultsIterator<KeyModification> Handler.handleGetHistoryForKey(key) Change-Id: I3d4e8014d3c2dfa210483350968e439edbe756c7 Signed-off-by: Luis Sanchez <[email protected]>
1 parent 6ad95f6 commit fe8d1da

File tree

6 files changed

+279
-0
lines changed

6 files changed

+279
-0
lines changed

core/chaincode/shim/java/src/main/java/org/hyperledger/fabric/shim/ChaincodeStub.java

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage.ChaincodeEvent;
2525
import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;
2626
import org.hyperledger.fabric.shim.ledger.CompositeKey;
27+
import org.hyperledger.fabric.shim.ledger.KeyModification;
2728
import org.hyperledger.fabric.shim.ledger.KeyValue;
2829
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;
2930

@@ -175,6 +176,14 @@ public interface ChaincodeStub {
175176
*/
176177
QueryResultsIterator<KeyValue> getQueryResult(String query);
177178

179+
/**
180+
* Returns the history of the specified key's values across time.
181+
*
182+
* @param key
183+
* @return an {@link Iterable} of {@link KeyModification}
184+
*/
185+
QueryResultsIterator<KeyModification> getHistoryForKey(String key);
186+
178187
/**
179188
* Defines the CHAINCODE type event that will be posted to interested
180189
* clients when the chaincode's result is committed to the ledger.

core/chaincode/shim/java/src/main/java/org/hyperledger/fabric/shim/impl/ChaincodeStubImpl.java

+20
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525

2626
import org.apache.commons.logging.Log;
2727
import org.apache.commons.logging.LogFactory;
28+
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
2829
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult.KV;
2930
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage.ChaincodeEvent;
3031
import org.hyperledger.fabric.protos.peer.ChaincodeShim.QueryResultBytes;
3132
import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;
3233
import org.hyperledger.fabric.shim.ChaincodeStub;
3334
import org.hyperledger.fabric.shim.ledger.CompositeKey;
35+
import org.hyperledger.fabric.shim.ledger.KeyModification;
3436
import org.hyperledger.fabric.shim.ledger.KeyValue;
3537
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;
3638

@@ -198,6 +200,24 @@ public QueryResultsIterator<KeyValue> getQueryResult(String query) {
198200
);
199201
}
200202

203+
@Override
204+
public QueryResultsIterator<KeyModification> getHistoryForKey(String key) {
205+
return new QueryResultsIteratorImpl<KeyModification>(this.handler, getTxId(),
206+
handler.handleGetHistoryForKey(getTxId(), key),
207+
queryResultBytesToKeyModification.andThen(KeyModificationImpl::new)
208+
);
209+
}
210+
211+
private Function<QueryResultBytes, KvQueryResult.KeyModification> queryResultBytesToKeyModification = new Function<QueryResultBytes, KvQueryResult.KeyModification>() {
212+
public KvQueryResult.KeyModification apply(QueryResultBytes queryResultBytes) {
213+
try {
214+
return KvQueryResult.KeyModification.parseFrom(queryResultBytes.getResultBytes());
215+
} catch (InvalidProtocolBufferException e) {
216+
throw new RuntimeException(e);
217+
}
218+
};
219+
};
220+
201221
/* (non-Javadoc)
202222
* @see org.hyperledger.fabric.shim.ChaincodeStub#invokeChaincode(java.lang.String, java.util.List, java.lang.String)
203223
*/

core/chaincode/shim/java/src/main/java/org/hyperledger/fabric/shim/impl/Handler.java

+6
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ QueryResponse handleGetQueryResult(String txId, String query) {
599599
.build().toByteString());
600600
}
601601

602+
QueryResponse handleGetHistoryForKey(String txId, String key) {
603+
return invokeQueryResponseMessage(txId, Type.GET_HISTORY_FOR_KEY, GetQueryResult.newBuilder()
604+
.setQuery(key)
605+
.build().toByteString());
606+
}
607+
602608
private QueryResponse invokeQueryResponseMessage(String txId, ChaincodeMessage.Type type, ByteString payload) {
603609
try {
604610
return QueryResponse.parseFrom(invokeChaincodeSupport(txId, type, payload)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright IBM 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package org.hyperledger.fabric.shim.impl;
17+
18+
import java.time.Instant;
19+
20+
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
21+
import org.hyperledger.fabric.shim.ledger.KeyModification;
22+
23+
import com.google.protobuf.ByteString;
24+
25+
public class KeyModificationImpl implements KeyModification {
26+
27+
private final String txId;
28+
private final ByteString value;
29+
private final java.time.Instant timestamp;
30+
private final boolean deleted;
31+
32+
KeyModificationImpl(KvQueryResult.KeyModification km) {
33+
this.txId = km.getTxId();
34+
this.value = km.getValue();
35+
this.timestamp = Instant.ofEpochSecond(km.getTimestamp().getSeconds(), km.getTimestamp().getNanos());
36+
this.deleted = km.getIsDelete();
37+
}
38+
39+
/*
40+
* (non-Javadoc)
41+
*
42+
* @see org.hyperledger.fabric.shim.impl.KeyModification#getTxId()
43+
*/
44+
@Override
45+
public String getTxId() {
46+
return txId;
47+
}
48+
49+
/*
50+
* (non-Javadoc)
51+
*
52+
* @see org.hyperledger.fabric.shim.impl.KeyModification#getValue()
53+
*/
54+
@Override
55+
public byte[] getValue() {
56+
return value.toByteArray();
57+
}
58+
59+
/*
60+
* (non-Javadoc)
61+
*
62+
* @see org.hyperledger.fabric.shim.impl.KeyModification#getStringValue()
63+
*/
64+
@Override
65+
public String getStringValue() {
66+
return value.toStringUtf8();
67+
}
68+
69+
/*
70+
* (non-Javadoc)
71+
*
72+
* @see org.hyperledger.fabric.shim.impl.KeyModification#getTimestamp()
73+
*/
74+
@Override
75+
public java.time.Instant getTimestamp() {
76+
return timestamp;
77+
}
78+
79+
/*
80+
* (non-Javadoc)
81+
*
82+
* @see org.hyperledger.fabric.shim.impl.KeyModification#isDeleted()
83+
*/
84+
@Override
85+
public boolean isDeleted() {
86+
return deleted;
87+
}
88+
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright IBM 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package org.hyperledger.fabric.shim.ledger;
17+
18+
public interface KeyModification {
19+
20+
/**
21+
* Returns the transaction id.
22+
*
23+
* @return
24+
*/
25+
String getTxId();
26+
27+
/**
28+
* Returns the key's value at the time returned by {@link #getTimestamp()}.
29+
*
30+
* @return
31+
*/
32+
byte[] getValue();
33+
34+
/**
35+
* Returns the key's value at the time returned by {@link #getTimestamp()},
36+
* decoded as a UTF-8 string.
37+
*
38+
* @return
39+
*/
40+
String getStringValue();
41+
42+
/**
43+
* Returns the timestamp of the key modification entry.
44+
*
45+
* @return
46+
*/
47+
java.time.Instant getTimestamp();
48+
49+
/**
50+
* Returns the deletion marker.
51+
*
52+
* @return
53+
*/
54+
boolean isDeleted();
55+
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Copyright IBM 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package org.hyperledger.fabric.shim.impl;
17+
18+
import static java.nio.charset.StandardCharsets.UTF_8;
19+
import static org.hamcrest.Matchers.equalTo;
20+
import static org.hamcrest.Matchers.hasProperty;
21+
import static org.hamcrest.Matchers.is;
22+
import static org.junit.Assert.assertThat;
23+
24+
import java.util.stream.Stream;
25+
26+
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
27+
import org.hyperledger.fabric.shim.ledger.KeyModification;
28+
import org.junit.Test;
29+
30+
import com.google.protobuf.ByteString;
31+
import com.google.protobuf.Timestamp;
32+
33+
public class KeyModificationImplTest {
34+
35+
@Test
36+
public void testKeyModificationImpl() {
37+
new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
38+
.setTxId("txid")
39+
.setValue(ByteString.copyFromUtf8("value"))
40+
.setTimestamp(Timestamp.newBuilder()
41+
.setSeconds(1234567890)
42+
.setNanos(123456789))
43+
.setIsDelete(true)
44+
.build()
45+
);
46+
}
47+
48+
@Test
49+
public void testGetTxId() {
50+
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
51+
.setTxId("txid")
52+
.build()
53+
);
54+
assertThat(km.getTxId(), is(equalTo("txid")));
55+
}
56+
57+
@Test
58+
public void testGetValue() {
59+
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
60+
.setValue(ByteString.copyFromUtf8("value"))
61+
.build()
62+
);
63+
assertThat(km.getValue(), is(equalTo("value".getBytes(UTF_8))));
64+
}
65+
66+
@Test
67+
public void testGetStringValue() {
68+
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
69+
.setValue(ByteString.copyFromUtf8("value"))
70+
.build()
71+
);
72+
assertThat(km.getStringValue(), is(equalTo("value")));
73+
}
74+
75+
@Test
76+
public void testGetTimestamp() {
77+
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
78+
.setTimestamp(Timestamp.newBuilder()
79+
.setSeconds(1234567890L)
80+
.setNanos(123456789))
81+
.build()
82+
);
83+
assertThat(km.getTimestamp(), hasProperty("epochSecond", equalTo(1234567890L)));
84+
assertThat(km.getTimestamp(), hasProperty("nano", equalTo(123456789)));
85+
}
86+
87+
@Test
88+
public void testIsDeleted() {
89+
Stream.of(true, false)
90+
.forEach(b -> {
91+
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
92+
.setIsDelete(b)
93+
.build()
94+
);
95+
assertThat(km.isDeleted(), is(b));
96+
});
97+
}
98+
99+
}

0 commit comments

Comments
 (0)