net.ripe.db.whois.common.rpsl.RpslObject Maven / Gradle / Ivy
package net.ripe.db.whois.common.rpsl;
import com.google.common.base.Charsets;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.ripe.db.whois.common.domain.CIString;
import net.ripe.db.whois.common.domain.Identifiable;
import net.ripe.db.whois.common.domain.ResponseObject;
import net.ripe.db.whois.common.io.ByteArrayOutput;
import org.apache.commons.lang.Validate;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Immutable
public class RpslObject implements Identifiable, ResponseObject {
private final ObjectType type;
private final RpslAttribute typeAttribute;
private final CIString key;
private Integer objectId;
private List attributes;
private Map> typeCache;
private int hash;
public RpslObject(final RpslObject oldObject, final List attributes) {
this(oldObject.objectId, attributes);
}
public RpslObject(final Integer objectId, final List attributes) {
this(attributes);
this.objectId = objectId;
}
public RpslObject(final Integer objectId, final RpslObject rpslObject) {
this.objectId = objectId;
this.attributes = rpslObject.attributes;
this.type = rpslObject.type;
this.typeAttribute = rpslObject.typeAttribute;
this.key = rpslObject.key;
this.typeCache = rpslObject.typeCache;
this.hash = rpslObject.hash;
}
public RpslObject(final List attributes) {
Validate.notEmpty(attributes);
this.typeAttribute = attributes.get(0);
this.type = ObjectType.getByName(typeAttribute.getKey());
this.attributes = Collections.unmodifiableList(attributes);
final Set keyAttributes = ObjectTemplate.getTemplate(type).getKeyAttributes();
if (keyAttributes.size() == 1) {
this.key = getValueForAttribute(keyAttributes.iterator().next());
Validate.notEmpty(this.key.toString(), "key attributes must have value");
} else {
final StringBuilder keyBuilder = new StringBuilder(32);
for (AttributeType keyAttribute : keyAttributes) {
String key = getValueForAttribute(keyAttribute).toString();
Validate.notEmpty(key, "key attributes must have value");
keyBuilder.append(key);
}
this.key = CIString.ciString(keyBuilder.toString());
}
}
public static RpslObject parse(final String input) {
return new RpslObject(RpslObjectBuilder.getAttributes(input));
}
public static RpslObject parse(final byte[] input) {
return new RpslObject(RpslObjectBuilder.getAttributes(input));
}
public static RpslObject parse(final Integer objectId, final String input) {
return new RpslObject(objectId, RpslObjectBuilder.getAttributes(input));
}
public static RpslObject parse(final Integer objectId, final byte[] input) {
return new RpslObject(objectId, RpslObjectBuilder.getAttributes(input));
}
@Override
public int getObjectId() {
return objectId;
}
public ObjectType getType() {
return type;
}
public List getAttributes() {
return attributes;
}
public int size() {
return attributes.size();
}
public final CIString getKey() {
return key;
}
public String getFormattedKey() {
switch (type) {
case PERSON:
case ROLE:
return String.format("[%s] %s %s", type.getName(), getKey(), getAttributes().get(0).getCleanValue());
default:
return String.format("[%s] %s", type.getName(), getKey());
}
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof RpslObject)) {
return false;
}
final RpslObject other = (RpslObject) obj;
return Iterables.elementsEqual(getAttributes(), other.getAttributes());
}
@Override
public int hashCode() {
if (hash == 0) {
int result = getAttributes().hashCode();
if (result == 0) {
result--;
}
hash = result;
}
return hash;
}
public RpslAttribute getTypeAttribute() {
return getAttributes().get(0);
}
Map> getOrCreateCache() {
if (typeCache == null) {
final EnumMap> map = Maps.newEnumMap(AttributeType.class);
for (final RpslAttribute attribute : getAttributes()) {
final AttributeType attributeType = attribute.getType();
if (attributeType == null) {
continue;
}
List list = map.get(attributeType);
if (list == null) {
list = Lists.newArrayList();
map.put(attributeType, list);
}
list.add(attribute);
}
typeCache = map;
}
return typeCache;
}
public RpslAttribute findAttribute(final AttributeType attributeType) {
final List foundAttributes = findAttributes(attributeType);
switch (foundAttributes.size()) {
case 0:
throw new IllegalArgumentException("No " + attributeType + ": found in " + key);
case 1:
return foundAttributes.get(0);
default:
throw new IllegalArgumentException("Multiple " + attributeType + ": found in " + key);
}
}
public List findAttributes(final AttributeType attributeType) {
final List list = getOrCreateCache().get(attributeType);
return list == null ? Collections.emptyList() : Collections.unmodifiableList(list);
}
public List findAttributes(final Iterable attributeTypes) {
final List result = Lists.newArrayList();
for (final AttributeType attributeType : attributeTypes) {
findCachedAttributes(result, attributeType);
}
return result;
}
public List findAttributes(final AttributeType... attributeTypes) {
return findAttributes(Arrays.asList(attributeTypes));
}
private void findCachedAttributes(final List result, final AttributeType attributeType) {
final List list = getOrCreateCache().get(attributeType);
if (list != null) {
result.addAll(list);
}
}
public boolean containsAttributes(final Collection attributeTypes) {
for (AttributeType attributeType : attributeTypes) {
if (containsAttribute(attributeType)) {
return true;
}
}
return false;
}
public boolean containsAttribute(final AttributeType attributeType) {
return getOrCreateCache().containsKey(attributeType);
}
@Override
public void writeTo(final OutputStream out) throws IOException {
writeTo(new OutputStreamWriter(out, Charsets.ISO_8859_1));
}
public void writeTo(final Writer writer) throws IOException {
for (final RpslAttribute attribute : getAttributes()) {
attribute.writeTo(writer);
}
writer.flush();
}
@Override
public byte[] toByteArray() {
try {
final ByteArrayOutput baos = new ByteArrayOutput();
writeTo(baos);
return baos.toByteArray();
} catch (IOException e) {
throw new IllegalStateException("Should never occur", e);
}
}
@Override
public String toString() {
try {
final StringWriter writer = new StringWriter();
for (final RpslAttribute attribute : getAttributes()) {
attribute.writeTo(writer);
}
return writer.toString();
} catch (IOException e) {
throw new IllegalStateException("Should never occur", e);
}
}
public CIString getValueForAttribute(final AttributeType attributeType) {
return findAttribute(attributeType).getCleanValue();
}
@Nullable
public CIString getValueOrNullForAttribute(final AttributeType attributeType) {
List attributes = findAttributes(attributeType);
if (attributes.isEmpty()) {
return null;
}
return attributes.get(0).getCleanValue();
}
public Set getValuesForAttribute(final AttributeType... attributeType) {
final Set values = Sets.newLinkedHashSet();
for (AttributeType attrType : attributeType) {
final List rpslAttributes = getOrCreateCache().get(attrType);
if (rpslAttributes != null && !rpslAttributes.isEmpty()) {
for (RpslAttribute rpslAttribute : rpslAttributes) {
values.addAll(rpslAttribute.getCleanValues());
}
}
}
return values;
}
}