package gov.loc.repository.bagit.domain;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* A class to represent the bag-info.txt (and package-info.txt in older versions)
*/
@SuppressWarnings({"PMD.UseLocaleWithCaseConversions"})
public class Metadata {
private static final String PAYLOAD_OXUM = "Payload-Oxum";
private Map<String, List<String>> map = new HashMap<>();
private List<SimpleImmutableEntry<String, String>> list = new ArrayList<>();
@Override
public String toString() {
return list.toString();
}
@Override
public int hashCode() {
return Objects.hash(list);
}
@Override
public boolean equals(final Object obj) {
if (this == obj){return true;}
if (obj == null){return false;}
if (!(obj instanceof Metadata)){return false;}
final Metadata other = (Metadata) obj;
return Objects.equals(this.list, other.list);
}
/**
* all the metadata
*
* @return return the order and case preserved metadata
*/
public List<SimpleImmutableEntry<String, String>> getAll(){
return list;
}
/**
* get all the values for a specific label (key)
*
* @param key the case insensitive label(key) in the metadata
*
* @return the list of values for that label
*/
public List<String> get(final String key){
return map.get(key.toUpperCase());
}
/**
* add a entry into the metadata or append a value if the label already exists
*
* @param key the label
* @param value the value of the label
*
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(final String key, final String value){
if(PAYLOAD_OXUM.equalsIgnoreCase(key)){
this.remove(PAYLOAD_OXUM);
}
final String upperCaseKey = key.toUpperCase();
if(map.get(upperCaseKey) == null){
map.put(upperCaseKey, new ArrayList<>());
}
map.get(upperCaseKey).add(value);
return list.add(new SimpleImmutableEntry<>(key, value));
}
/**
* remove the label and all its values
*
* @param key the label to remove along with its value(s)
*/
public void remove(final String key){
map.remove(key.toUpperCase());
final List<SimpleImmutableEntry<String, String>> newList = new ArrayList<>();
for(final SimpleImmutableEntry<String, String> entry : list){
if(!entry.getKey().equalsIgnoreCase(key)){
newList.add(entry);
}
}
list = newList;
}
/**
* check if the metadata contains a particular label(key)
*
* @param key the label to check
* @return if the label exists
*/
public boolean contains(final String key){
return map.keySet().contains(key.toUpperCase());
}
/**
* add multiple metadata entries
*
* @param data the metadata to add
*/
public void addAll(final List<SimpleImmutableEntry<String, String>> data){
for(final SimpleImmutableEntry<String, String> entry : data){
this.add(entry.getKey(), entry.getValue());
}
}
/**
* payload oxum is a special case where it makes no sense to have multiple values so instead of just appending we upsert (insert or update)
* @param payloadOxumValue the value payload-oxum should be set to
*
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean upsertPayloadOxum(final String payloadOxumValue){
map.remove(PAYLOAD_OXUM.toUpperCase());
SimpleImmutableEntry<String, String> entryToRemove = null;
for(final SimpleImmutableEntry<String, String> entry : list){
if(PAYLOAD_OXUM.equalsIgnoreCase(entry.getKey())){
entryToRemove = entry;
continue;
}
}
if(entryToRemove != null){
list.remove(entryToRemove);
}
return this.add(PAYLOAD_OXUM, payloadOxumValue);
}
/**
* @return true if this metadata contains no entries
*/
public boolean isEmpty(){
return list.isEmpty();
}
protected Map<String, List<String>> getMap() {
return map;
}
protected void setMap(final Map<String, List<String>> map) {
this.map = map;
}
protected List<SimpleImmutableEntry<String, String>> getList() {
return list;
}
protected void setList(final List<SimpleImmutableEntry<String, String>> list) {
this.list = list;
}
}