package ameba.message.filtering;
import jersey.repackaged.com.google.common.collect.Sets;
import org.glassfish.jersey.internal.util.Tokenizer;
import org.glassfish.jersey.message.filtering.spi.ScopeResolver;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* <p>EntityFieldsScopeResolver class.</p>
*
* @author icode
*
*/
@Singleton
public class EntityFieldsScopeResolver implements ScopeResolver {
/**
* Prefix for all fields scopes
*/
public static final String PREFIX = EntityFieldsScopeResolver.class.getName() + "_";
/**
* Scope used for selecting all fields, i.e.: when no filter is applied
*/
public static final String DEFAULT_SCOPE = PREFIX + "*";
/**
* Query parameter name for fields feature, set to default value
*/
static String FIELDS_PARAM_NAME = "fields";
@Context
private Configuration configuration;
@Context
private UriInfo uriInfo;
@PostConstruct
private void init() {
final String paramName = (String) configuration.getProperty(EntityFieldsFilteringFeature.QUERY_FIELDS_PARAM_NAME);
FIELDS_PARAM_NAME = paramName != null ? paramName : FIELDS_PARAM_NAME;
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> resolve(final Annotation[] annotations) {
final Set<String> scopes = new HashSet<>();
final List<String> fields = uriInfo.getQueryParameters().get(FIELDS_PARAM_NAME);
if (fields != null && !fields.isEmpty()) {
for (final String field : fields) {
scopes.addAll(getScopesForField(field));
}
} else {
scopes.add(DEFAULT_SCOPE);
}
return scopes;
}
private Set<String> getScopesForField(final String fieldName) {
final Set<String> scopes = Sets.newHashSet();
// add specific scope in case of specific request
final String[] fields = Tokenizer.tokenize(fieldName, ",");
for (final String field : fields) {
final String[] subfields = Tokenizer.tokenize(field, ".");
// in case of nested path, add first level as stand-alone to ensure subgraph is added
scopes.add(EntityFieldsScopeResolver.PREFIX + subfields[0]);
if (subfields.length > 1) {
scopes.add(EntityFieldsScopeResolver.PREFIX + field);
}
}
return scopes;
}
}