HBASE-3921 Allow adding arbitrary blobs to Put
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1127782 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1a628ccd42
commit
03f55a3e89
|
@ -232,6 +232,7 @@ Release 0.91.0 - Unreleased
|
||||||
HBASE-3841 HTable and HTableInterface docs are inconsistent with
|
HBASE-3841 HTable and HTableInterface docs are inconsistent with
|
||||||
one another (Harsh J Chouraria)
|
one another (Harsh J Chouraria)
|
||||||
HBASE-2937 Facilitate Timeouts In HBase Client (Karthick Sankarachary)
|
HBASE-2937 Facilitate Timeouts In HBase Client (Karthick Sankarachary)
|
||||||
|
HBASE-3921 Allow adding arbitrary blobs to Put (dhruba borthakur)
|
||||||
|
|
||||||
TASKS
|
TASKS
|
||||||
HBASE-3559 Move report of split to master OFF the heartbeat channel
|
HBASE-3559 Move report of split to master OFF the heartbeat channel
|
||||||
|
|
|
@ -24,11 +24,14 @@ import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.KeyValue;
|
import org.apache.hadoop.hbase.KeyValue;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.io.Writable;
|
import org.apache.hadoop.io.Writable;
|
||||||
|
import org.apache.hadoop.io.WritableUtils;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
@ -66,7 +69,7 @@ import java.util.TreeMap;
|
||||||
* timestamp. The constructor timestamp is not referenced.
|
* timestamp. The constructor timestamp is not referenced.
|
||||||
*/
|
*/
|
||||||
public class Delete implements Writable, Row, Comparable<Row> {
|
public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
private static final byte DELETE_VERSION = (byte)1;
|
private static final byte DELETE_VERSION = (byte)2;
|
||||||
|
|
||||||
private byte [] row = null;
|
private byte [] row = null;
|
||||||
// This ts is only used when doing a deleteRow. Anything less,
|
// This ts is only used when doing a deleteRow. Anything less,
|
||||||
|
@ -75,6 +78,9 @@ public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
private final Map<byte [], List<KeyValue>> familyMap =
|
private final Map<byte [], List<KeyValue>> familyMap =
|
||||||
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
|
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
|
||||||
|
|
||||||
|
// a opaque blob that can be passed into a Delete.
|
||||||
|
private Map<String, byte[]> attributes;
|
||||||
|
|
||||||
/** Constructor for Writable. DO NOT USE */
|
/** Constructor for Writable. DO NOT USE */
|
||||||
public Delete() {
|
public Delete() {
|
||||||
this((byte [])null);
|
this((byte [])null);
|
||||||
|
@ -283,6 +289,54 @@ public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
this.ts = timestamp;
|
this.ts = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets arbitrary delete's attribute.
|
||||||
|
* In case value = null attribute is removed from the attributes map.
|
||||||
|
* @param name attribute name
|
||||||
|
* @param value attribute value
|
||||||
|
*/
|
||||||
|
public void setAttribute(String name, byte[] value) {
|
||||||
|
if (attributes == null && value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes == null) {
|
||||||
|
attributes = new HashMap<String, byte[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
attributes.remove(name);
|
||||||
|
if (attributes.isEmpty()) {
|
||||||
|
this.attributes = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attributes.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets put's attribute
|
||||||
|
* @param name attribute name
|
||||||
|
* @return attribute value if attribute is set, <tt>null</tt> otherwise
|
||||||
|
*/
|
||||||
|
public byte[] getAttribute(String name) {
|
||||||
|
if (attributes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return attributes.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all scan's attributes
|
||||||
|
* @return unmodifiable map of all attributes
|
||||||
|
*/
|
||||||
|
public Map<String, byte[]> getAttributesMap() {
|
||||||
|
if (attributes == null) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -341,6 +395,17 @@ public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
}
|
}
|
||||||
this.familyMap.put(family, list);
|
this.familyMap.put(family, list);
|
||||||
}
|
}
|
||||||
|
if (version > 1) {
|
||||||
|
int numAttributes = in.readInt();
|
||||||
|
if (numAttributes > 0) {
|
||||||
|
this.attributes = new HashMap<String, byte[]>();
|
||||||
|
for(int i=0; i<numAttributes; i++) {
|
||||||
|
String name = WritableUtils.readString(in);
|
||||||
|
byte[] value = Bytes.readByteArray(in);
|
||||||
|
this.attributes.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(final DataOutput out) throws IOException {
|
public void write(final DataOutput out) throws IOException {
|
||||||
|
@ -357,6 +422,15 @@ public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
kv.write(out);
|
kv.write(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.attributes == null) {
|
||||||
|
out.writeInt(0);
|
||||||
|
} else {
|
||||||
|
out.writeInt(this.attributes.size());
|
||||||
|
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
|
||||||
|
WritableUtils.writeString(out, attr.getKey());
|
||||||
|
Bytes.writeByteArray(out, attr.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -386,6 +460,4 @@ public class Delete implements Writable, Row, Comparable<Row> {
|
||||||
this.deleteColumn(parts[0], parts[1], HConstants.LATEST_TIMESTAMP);
|
this.deleteColumn(parts[0], parts[1], HConstants.LATEST_TIMESTAMP);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,15 @@ import org.apache.hadoop.hbase.io.HeapSize;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.ClassSize;
|
import org.apache.hadoop.hbase.util.ClassSize;
|
||||||
import org.apache.hadoop.io.Writable;
|
import org.apache.hadoop.io.Writable;
|
||||||
|
import org.apache.hadoop.io.WritableUtils;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
@ -45,7 +48,7 @@ import java.util.TreeMap;
|
||||||
* {@link #add(byte[], byte[], long, byte[]) add} if setting the timestamp.
|
* {@link #add(byte[], byte[], long, byte[]) add} if setting the timestamp.
|
||||||
*/
|
*/
|
||||||
public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
||||||
private static final byte PUT_VERSION = (byte)1;
|
private static final byte PUT_VERSION = (byte)2;
|
||||||
|
|
||||||
private byte [] row = null;
|
private byte [] row = null;
|
||||||
private long timestamp = HConstants.LATEST_TIMESTAMP;
|
private long timestamp = HConstants.LATEST_TIMESTAMP;
|
||||||
|
@ -55,6 +58,9 @@ public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
||||||
private Map<byte [], List<KeyValue>> familyMap =
|
private Map<byte [], List<KeyValue>> familyMap =
|
||||||
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
|
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
|
||||||
|
|
||||||
|
// a opaque blob that can be passed into a Put.
|
||||||
|
private Map<String, byte[]> attributes;
|
||||||
|
|
||||||
private static final long OVERHEAD = ClassSize.align(
|
private static final long OVERHEAD = ClassSize.align(
|
||||||
ClassSize.OBJECT + ClassSize.REFERENCE +
|
ClassSize.OBJECT + ClassSize.REFERENCE +
|
||||||
2 * Bytes.SIZEOF_LONG + Bytes.SIZEOF_BOOLEAN +
|
2 * Bytes.SIZEOF_LONG + Bytes.SIZEOF_BOOLEAN +
|
||||||
|
@ -407,6 +413,56 @@ public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
||||||
this.writeToWAL = write;
|
this.writeToWAL = write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets arbitrary put's attribute.
|
||||||
|
* In case value = null attribute is removed from the attributes map.
|
||||||
|
* @param name attribute name
|
||||||
|
* @param value attribute value
|
||||||
|
*/
|
||||||
|
public void setAttribute(String name, byte[] value) {
|
||||||
|
if (attributes == null && value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes == null) {
|
||||||
|
attributes = new HashMap<String, byte[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
attributes.remove(name);
|
||||||
|
if (attributes.isEmpty()) {
|
||||||
|
this.attributes = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attributes.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets put's attribute
|
||||||
|
* @param name attribute name
|
||||||
|
* @return attribute value if attribute is set, <tt>null</tt> otherwise
|
||||||
|
*/
|
||||||
|
public byte[] getAttribute(String name) {
|
||||||
|
if (attributes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all scan's attributes
|
||||||
|
* @return unmodifiable map of all attributes
|
||||||
|
*/
|
||||||
|
public Map<String, byte[]> getAttributesMap() {
|
||||||
|
if (attributes == null) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
|
@ -502,6 +558,17 @@ public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
||||||
}
|
}
|
||||||
this.familyMap.put(family, keys);
|
this.familyMap.put(family, keys);
|
||||||
}
|
}
|
||||||
|
if (version > 1) {
|
||||||
|
int numAttributes = in.readInt();
|
||||||
|
if (numAttributes > 0) {
|
||||||
|
this.attributes = new HashMap<String, byte[]>();
|
||||||
|
for(int i=0; i<numAttributes; i++) {
|
||||||
|
String name = WritableUtils.readString(in);
|
||||||
|
byte[] value = Bytes.readByteArray(in);
|
||||||
|
this.attributes.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(final DataOutput out)
|
public void write(final DataOutput out)
|
||||||
|
@ -526,6 +593,15 @@ public class Put implements HeapSize, Writable, Row, Comparable<Row> {
|
||||||
out.write(kv.getBuffer(), kv.getOffset(), kv.getLength());
|
out.write(kv.getBuffer(), kv.getOffset(), kv.getLength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.attributes == null) {
|
||||||
|
out.writeInt(0);
|
||||||
|
} else {
|
||||||
|
out.writeInt(this.attributes.size());
|
||||||
|
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
|
||||||
|
WritableUtils.writeString(out, attr.getKey());
|
||||||
|
Bytes.writeByteArray(out, attr.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2009 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestAttributes {
|
||||||
|
@Test
|
||||||
|
public void testAttributesSerialization() throws IOException {
|
||||||
|
Put put = new Put();
|
||||||
|
put.setAttribute("attribute1", Bytes.toBytes("value1"));
|
||||||
|
put.setAttribute("attribute2", Bytes.toBytes("value2"));
|
||||||
|
put.setAttribute("attribute3", Bytes.toBytes("value3"));
|
||||||
|
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
DataOutput out = new DataOutputStream(byteArrayOutputStream);
|
||||||
|
put.write(out);
|
||||||
|
|
||||||
|
Put put2 = new Put();
|
||||||
|
Assert.assertTrue(put2.getAttributesMap().isEmpty());
|
||||||
|
|
||||||
|
put2.readFields(new DataInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())));
|
||||||
|
|
||||||
|
Assert.assertNull(put2.getAttribute("absent"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value1"), put2.getAttribute("attribute1")));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value2"), put2.getAttribute("attribute2")));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value3"), put2.getAttribute("attribute3")));
|
||||||
|
Assert.assertEquals(3, put2.getAttributesMap().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutAttributes() {
|
||||||
|
Put put = new Put();
|
||||||
|
Assert.assertTrue(put.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(put.getAttribute("absent"));
|
||||||
|
|
||||||
|
put.setAttribute("absent", null);
|
||||||
|
Assert.assertTrue(put.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(put.getAttribute("absent"));
|
||||||
|
|
||||||
|
// adding attribute
|
||||||
|
put.setAttribute("attribute1", Bytes.toBytes("value1"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value1"), put.getAttribute("attribute1")));
|
||||||
|
Assert.assertEquals(1, put.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value1"), put.getAttributesMap().get("attribute1")));
|
||||||
|
|
||||||
|
// overriding attribute value
|
||||||
|
put.setAttribute("attribute1", Bytes.toBytes("value12"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value12"), put.getAttribute("attribute1")));
|
||||||
|
Assert.assertEquals(1, put.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value12"), put.getAttributesMap().get("attribute1")));
|
||||||
|
|
||||||
|
// adding another attribute
|
||||||
|
put.setAttribute("attribute2", Bytes.toBytes("value2"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value2"), put.getAttribute("attribute2")));
|
||||||
|
Assert.assertEquals(2, put.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value2"), put.getAttributesMap().get("attribute2")));
|
||||||
|
|
||||||
|
// removing attribute
|
||||||
|
put.setAttribute("attribute2", null);
|
||||||
|
Assert.assertNull(put.getAttribute("attribute2"));
|
||||||
|
Assert.assertEquals(1, put.getAttributesMap().size());
|
||||||
|
Assert.assertNull(put.getAttributesMap().get("attribute2"));
|
||||||
|
|
||||||
|
// removing non-existed attribute
|
||||||
|
put.setAttribute("attribute2", null);
|
||||||
|
Assert.assertNull(put.getAttribute("attribute2"));
|
||||||
|
Assert.assertEquals(1, put.getAttributesMap().size());
|
||||||
|
Assert.assertNull(put.getAttributesMap().get("attribute2"));
|
||||||
|
|
||||||
|
// removing another attribute
|
||||||
|
put.setAttribute("attribute1", null);
|
||||||
|
Assert.assertNull(put.getAttribute("attribute1"));
|
||||||
|
Assert.assertTrue(put.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(put.getAttributesMap().get("attribute1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteAttributes() {
|
||||||
|
Delete del = new Delete();
|
||||||
|
Assert.assertTrue(del.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(del.getAttribute("absent"));
|
||||||
|
|
||||||
|
del.setAttribute("absent", null);
|
||||||
|
Assert.assertTrue(del.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(del.getAttribute("absent"));
|
||||||
|
|
||||||
|
// adding attribute
|
||||||
|
del.setAttribute("attribute1", Bytes.toBytes("value1"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value1"), del.getAttribute("attribute1")));
|
||||||
|
Assert.assertEquals(1, del.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value1"), del.getAttributesMap().get("attribute1")));
|
||||||
|
|
||||||
|
// overriding attribute value
|
||||||
|
del.setAttribute("attribute1", Bytes.toBytes("value12"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value12"), del.getAttribute("attribute1")));
|
||||||
|
Assert.assertEquals(1, del.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value12"), del.getAttributesMap().get("attribute1")));
|
||||||
|
|
||||||
|
// adding another attribute
|
||||||
|
del.setAttribute("attribute2", Bytes.toBytes("value2"));
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value2"), del.getAttribute("attribute2")));
|
||||||
|
Assert.assertEquals(2, del.getAttributesMap().size());
|
||||||
|
Assert.assertTrue(Arrays.equals(Bytes.toBytes("value2"), del.getAttributesMap().get("attribute2")));
|
||||||
|
|
||||||
|
// removing attribute
|
||||||
|
del.setAttribute("attribute2", null);
|
||||||
|
Assert.assertNull(del.getAttribute("attribute2"));
|
||||||
|
Assert.assertEquals(1, del.getAttributesMap().size());
|
||||||
|
Assert.assertNull(del.getAttributesMap().get("attribute2"));
|
||||||
|
|
||||||
|
// removing non-existed attribute
|
||||||
|
del.setAttribute("attribute2", null);
|
||||||
|
Assert.assertNull(del.getAttribute("attribute2"));
|
||||||
|
Assert.assertEquals(1, del.getAttributesMap().size());
|
||||||
|
Assert.assertNull(del.getAttributesMap().get("attribute2"));
|
||||||
|
|
||||||
|
// removing another attribute
|
||||||
|
del.setAttribute("attribute1", null);
|
||||||
|
Assert.assertNull(del.getAttribute("attribute1"));
|
||||||
|
Assert.assertTrue(del.getAttributesMap().isEmpty());
|
||||||
|
Assert.assertNull(del.getAttributesMap().get("attribute1"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue