/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.test.rest;
import com.google.common.collect.Maps;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Allows to cache the last obtained test response and or part of it within variables
* that can be used as input values in following requests and assertions.
*/
public class Stash implements ToXContent {
private static final ESLogger logger = Loggers.getLogger(Stash.class);
public static final Stash EMPTY = new Stash();
private final Map<String, Object> stash = Maps.newHashMap();
/**
* Allows to saved a specific field in the stash as key-value pair
*/
public void stashValue(String key, Object value) {
logger.trace("stashing [{}]=[{}]", key, value);
Object old = stash.put(key, value);
if (old != null && old != value) {
logger.trace("replaced stashed value [{}] with same key [{}]", old, key);
}
}
/**
* Clears the previously stashed values
*/
public void clear() {
stash.clear();
}
/**
* Tells whether a particular value needs to be looked up in the stash
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
public boolean isStashedValue(Object key) {
if (key == null) {
return false;
}
String stashKey = key.toString();
return Strings.hasLength(stashKey) && stashKey.startsWith("$");
}
/**
* Extracts a value from the current stash
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
public Object unstashValue(String value) {
Object stashedValue = stash.get(value.substring(1));
if (stashedValue == null) {
throw new IllegalArgumentException("stashed value not found for key [" + value + "]");
}
return stashedValue;
}
/**
* Recursively unstashes map values if needed
*/
public Map<String, Object> unstashMap(Map<String, Object> map) {
Map<String, Object> copy = Maps.newHashMap(map);
unstashObject(copy);
return copy;
}
@SuppressWarnings("unchecked")
private void unstashObject(Object obj) {
if (obj instanceof List) {
List list = (List) obj;
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
if (isStashedValue(o)) {
list.set(i, unstashValue(o.toString()));
} else {
unstashObject(o);
}
}
}
if (obj instanceof Map) {
Map<String, Object> map = (Map) obj;
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (isStashedValue(entry.getValue())) {
entry.setValue(unstashValue(entry.getValue().toString()));
} else {
unstashObject(entry.getValue());
}
}
}
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.field("stash", stash);
return builder;
}
}