/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.asn1;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.ldaptive.LdapUtils;
/**
* An OID representing the type of attribute and its value.
*
* @author Middleware Services
*/
public class AttributeValueAssertion extends AbstractDERType implements DEREncoder
{
/** hash code seed. */
private static final int HASH_CODE_SEED = 613;
/** OID of the attribute. */
private final String attributeOid;
/** Tag and value of the attribute. */
private final Value attributeValue;
/**
* Creates a new attribute value assertion.
*
* @param oid describing the attribute value
* @param value of the attribute
*/
public AttributeValueAssertion(final String oid, final Value value)
{
super(value.getTag());
attributeOid = oid;
attributeValue = value;
}
/**
* Returns the OID.
*
* @return oid
*/
public String getOid()
{
return attributeOid;
}
/**
* Returns the tag and value of the attribute.
*
* @return attribute value
*/
public Value getValue()
{
return attributeValue;
}
@Override
public byte[] encode()
{
final ConstructedDEREncoder se = new ConstructedDEREncoder(
UniversalDERTag.SEQ,
() -> {
final OidType type = new OidType(attributeOid);
return type.encode();
},
() -> AttributeValueAssertion.this.encode(attributeValue.getBytes()));
return se.encode();
}
/**
* Converts bytes in the buffer to attribute value assertions by reading from the current position to the limit.
*
* @param encoded buffer containing DER-encoded data where the buffer is positioned at the tag of the oid and the
* limit is set beyond the last byte of attribute value data.
*
* @return decoded bytes as attribute value assertions
*/
public static AttributeValueAssertion[] decode(final ByteBuffer encoded)
{
final List<AttributeValueAssertion> assertions = new ArrayList<>();
final DERParser parser = new DERParser();
parser.registerHandler(
"/SEQ",
(parser1, encoded1) -> {
if (UniversalDERTag.OID.getTagNo() != parser1.readTag(encoded1).getTagNo()) {
throw new IllegalArgumentException("Expected OID tag");
}
final int seqLimit = encoded1.limit();
final int oidLength = parser1.readLength(encoded1);
encoded1.limit(encoded1.position() + oidLength);
final String oid = OidType.decode(encoded1);
encoded1.limit(seqLimit);
final DERTag tag = parser1.readTag(encoded1);
parser1.readLength(encoded1);
assertions.add(new AttributeValueAssertion(oid, new Value(tag, readBuffer(encoded1))));
});
parser.parse(encoded);
return assertions.toArray(new AttributeValueAssertion[assertions.size()]);
}
@Override
public boolean equals(final Object o)
{
if (o == this) {
return true;
}
if (o instanceof AttributeValueAssertion) {
final AttributeValueAssertion v = (AttributeValueAssertion) o;
return LdapUtils.areEqual(attributeOid, v.attributeOid) &&
LdapUtils.areEqual(attributeValue, v.attributeValue);
}
return false;
}
@Override
public int hashCode()
{
return LdapUtils.computeHashCode(HASH_CODE_SEED, attributeOid, attributeValue);
}
@Override
public String toString()
{
return
String.format(
"[%s@%d::attributeOid=%s, attributeValue=%s]",
getClass().getName(),
hashCode(),
attributeOid,
attributeValue);
}
/** Class to represent the tag and value. */
public static class Value
{
/** hash code seed. */
private static final int HASH_CODE_SEED = 617;
/** attribute value tag. */
private final DERTag attributeValueTag;
/** attribute value bytes. */
private final byte[] attributeValueBytes;
/**
* Creates a new value.
*
* @param tag type of the attribute value
* @param bytes of the attribute
*/
public Value(final DERTag tag, final byte[] bytes)
{
attributeValueTag = tag;
attributeValueBytes = bytes;
}
/**
* Returns the attribute value tag.
*
* @return attribute value tag
*/
public DERTag getTag()
{
return attributeValueTag;
}
/**
* Returns the attribute value bytes.
*
* @return attribute value bytes
*/
public byte[] getBytes()
{
return attributeValueBytes;
}
@Override
public boolean equals(final Object o)
{
if (o == this) {
return true;
}
if (o instanceof Value) {
final Value v = (Value) o;
return LdapUtils.areEqual(attributeValueTag, v.attributeValueTag) &&
LdapUtils.areEqual(attributeValueBytes, v.attributeValueBytes);
}
return false;
}
@Override
public int hashCode()
{
return LdapUtils.computeHashCode(HASH_CODE_SEED, attributeValueTag, attributeValueBytes);
}
@Override
public String toString()
{
return
String.format(
"[%s@%d::attributeValueTag=%s, attributeValueBytes=%s]",
getClass().getName(),
hashCode(),
attributeValueTag,
LdapUtils.utf8Encode(attributeValueBytes));
}
}
}