/*
* Copyright 2011 the original author or authors.
* 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.
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.Collection;
import java.util.LinkedList;
/**
* @author Kalle Stenflo
*/
public class FieldFilter extends PathTokenFilter {
private final String[] split;
private final PathToken pathToken;
public FieldFilter(PathToken pathToken) {
super(pathToken.getFragment());
this.pathToken = pathToken;
this.split = condition.split("','");
}
@Override
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
if (!inArrayContext) {
throw new PathNotFoundException("Path '" + condition + "' is being applied to an array. Arrays can not have attributes.");
} else {
Object result = jsonProvider.createArray();
for (Object current : jsonProvider.toIterable(obj)) {
if (jsonProvider.isMap(current)) {
Collection<String> keys = jsonProvider.getPropertyKeys(current);
if(split.length == 1){
if (keys.contains(condition)) {
Object o = jsonProvider.getProperty(current, condition);
boolean isArr = jsonProvider.isArray(o);
boolean isEnd = pathToken.isEndToken();
if (isArr && !isEnd) {
for(Object item : jsonProvider.toIterable(o)){
jsonProvider.setProperty(result, jsonProvider.length(result), item);
}
} else {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(current, condition));
}
}
} else {
Object res = jsonProvider.createMap();
for (String prop : split) {
if (keys.contains(prop)) {
jsonProvider.setProperty(res, prop, jsonProvider.getProperty(current, prop));
}
}
jsonProvider.setProperty(result, jsonProvider.length(result), res);
}
}
}
return result;
}
} else if (jsonProvider.isMap(obj)){
Collection<String> keys = jsonProvider.getPropertyKeys(obj);
if(!keys.contains(condition) && split.length == 1){
if(configuration.getOptions().contains(Option.THROW_ON_MISSING_PROPERTY)){
throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
}
if(pathToken.isEndToken()){
return null;
} else {
throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
}
} else {
if(split.length == 1){
return jsonProvider.getProperty(obj, condition);
} else {
Object res = jsonProvider.createMap();
for (String prop : split) {
if(keys.contains(prop)){
jsonProvider.setProperty(res, prop, jsonProvider.getProperty(obj, prop));
}
}
return res;
}
}
} else {
throw new PathNotFoundException("Failed to access property: '" + condition + "' on object " + obj);
}
}
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
return obj;
} else {
return jsonProvider.getProperty(obj, condition);
}
}
@Override
public Object getRef(Object obj, Configuration configuration) {
return filter(obj, configuration);
}
@Override
public boolean isArrayFilter() {
return false;
}
}