package com.github.devnied.emvnfccard.iso7816emv.impl;
/*
* Copyright 2010 sasc
*
* Licensed 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.
*/
import java.util.Arrays;
import com.github.devnied.emvnfccard.enums.TagTypeEnum;
import com.github.devnied.emvnfccard.enums.TagValueTypeEnum;
import com.github.devnied.emvnfccard.iso7816emv.ITag;
import fr.devnied.bitlib.BytesUtils;
/**
*
* @author sasc
*/
public final class TagImpl implements ITag {
private final byte[] idBytes;
public final String name;
private final String description;
private final TagValueTypeEnum tagValueType;
private final Class tagClass;
private final TagTypeEnum type;
public TagImpl(final String id, final TagValueTypeEnum tagValueType, final String name, final String description) {
this(BytesUtils.fromString(id), tagValueType, name, description);
}
public TagImpl(final byte[] idBytes, final TagValueTypeEnum tagValueType, final String name, final String description) {
if (idBytes == null) {
throw new IllegalArgumentException("Param id cannot be null");
}
if (idBytes.length == 0) {
throw new IllegalArgumentException("Param id cannot be empty");
}
if (tagValueType == null) {
throw new IllegalArgumentException("Param tagValueType cannot be null");
}
this.idBytes = idBytes;
this.name = name;
this.description = description;
this.tagValueType = tagValueType;
if (BytesUtils.matchBitByBitIndex(this.idBytes[0], 5)) {
type = TagTypeEnum.CONSTRUCTED;
} else {
type = TagTypeEnum.PRIMITIVE;
}
// Bits 8 and 7 of the first byte of the tag field indicate a class.
// The value 00 indicates a data object of the universal class.
// The value 01 indicates a data object of the application class.
// The value 10 indicates a data object of the context-specific class.
// The value 11 indicates a data object of the private class.
byte classValue = (byte) (this.idBytes[0] >>> 6 & 0x03);
switch (classValue) {
case (byte) 0x01:
tagClass = Class.APPLICATION;
break;
case (byte) 0x02:
tagClass = Class.CONTEXT_SPECIFIC;
break;
case (byte) 0x03:
tagClass = Class.PRIVATE;
break;
default:
tagClass = Class.UNIVERSAL;
break;
}
}
@Override
public boolean isConstructed() {
return type == TagTypeEnum.CONSTRUCTED;
}
@Override
public byte[] getTagBytes() {
return idBytes;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public TagValueTypeEnum getTagValueType() {
return tagValueType;
}
@Override
public TagTypeEnum getType() {
return type;
}
@Override
public Class getTagClass() {
return tagClass;
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof ITag)) {
return false;
}
ITag that = (ITag) other;
if (getTagBytes().length != that.getTagBytes().length) {
return false;
}
return Arrays.equals(getTagBytes(), that.getTagBytes());
}
@Override
public int hashCode() {
int hash = 3;
hash = 59 * hash + Arrays.hashCode(idBytes);
return hash;
}
@Override
public int getNumTagBytes() {
return idBytes.length;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Tag[");
sb.append(BytesUtils.bytesToString(getTagBytes()));
sb.append("] Name=");
sb.append(getName());
sb.append(", TagType=");
sb.append(getType());
sb.append(", ValueType=");
sb.append(getTagValueType());
sb.append(", Class=");
sb.append(tagClass);
return sb.toString();
}
}