package org.molgenis.data;
import org.molgenis.data.meta.model.Attribute;
import java.util.*;
import java.util.Map.Entry;
/**
* {@link Fetch} that defines which entity attributes to retrieve. For attributes referring to entities a Fetch can be
* supplied that defines which entity attributes to retrieve for the referred entity.
* <p>
* A null Fetch means that all attributes should be retrieved.
*/
public class Fetch implements Iterable<Entry<String, Fetch>>
{
private final Map<String, Fetch> attrFetchMap;
/**
* Creates an empty Fetch.
*/
public Fetch()
{
this.attrFetchMap = new LinkedHashMap<>();
}
/**
* Updates this Fetch, adding a single field. If the field is a reference, the reference will be fetched with a null
* Fetch, which means that all attributes will be fetched.
*
* @param field the name of the field to fetch
* @return this Fetch, updated
*/
public Fetch field(String field)
{
return field(field, null);
}
/**
* Updates this fetch, adding a single field. If the field is a reference, the reference will be fetched with the
* Fetch that is provided.
*
* @param field the name of the field to fetch
* @param fetch the fetch to use for this field, if the field is a reference
* @return this Fetch, updated
*/
public Fetch field(String field, Fetch fetch)
{
attrFetchMap.put(field, fetch);
return this;
}
/**
* Retrieves the Fetch for a particular field
*
* @param field the field for which the Fetch is retrieved
* @return the Fetch for this field, or null if none was provided
*/
public Fetch getFetch(String field)
{
return attrFetchMap.get(field);
}
/**
* Retrieves the Fetch for an attribute
*
* @param attr
*/
public Fetch getFetch(Attribute attr)
{
return getFetch(attr.getName());
}
/**
* Indicates if a field is included in this Fetch.
*
* @param field the field that is queried
* @return true if the field is included in this Fetch, otherwise false
*/
public boolean hasField(String field)
{
return attrFetchMap.containsKey(field);
}
/**
* Indicates if a field is included in this Fetch
*
* @param attr {@link Attribute} for the field
* @return true if the field is included in this Fetch, otherwise false
*/
public boolean hasField(Attribute attr)
{
return hasField(attr.getName());
}
/**
* Retrieves the fields included in this Fetch
*
* @return {@link Set} containing the names of all fields included in this Fetch
*/
public Set<String> getFields()
{
return Collections.unmodifiableMap(attrFetchMap).keySet();
}
/**
* Iterates over all fields in this fetch. The key is the field name, the value is the {@link Fetch} for that field,
* or null if no Fetch is provided for that field.
*
* @return {@link Iterator} over all {@link Entry}s in this fetch.
*/
@Override
public Iterator<Entry<String, Fetch>> iterator()
{
return Collections.unmodifiableMap(attrFetchMap).entrySet().iterator();
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((attrFetchMap == null) ? 0 : attrFetchMap.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Fetch other = (Fetch) obj;
if (attrFetchMap == null)
{
if (other.attrFetchMap != null) return false;
}
else if (!attrFetchMap.equals(other.attrFetchMap)) return false;
return true;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
toStringRec(builder, this);
return builder.toString();
}
private void toStringRec(StringBuilder builder, Fetch fetch)
{
builder.append('(');
for (Iterator<Map.Entry<String, Fetch>> it = fetch.iterator(); it.hasNext(); )
{
Entry<String, Fetch> entry = it.next();
builder.append(entry.getKey());
Fetch subFetch = entry.getValue();
if (subFetch != null)
{
toStringRec(builder, subFetch);
}
if (it.hasNext())
{
builder.append(',');
}
}
builder.append(')');
}
}