package org.jolokia.converter.json;
/*
* Copyright 2009-2013 Roland Huss
*
* 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.
*/
/**
* Options object influencing the serializing of JSON objects.
* E.g. the max serialization depth when serializing a complex object.
*
* JsonConvertOptions are create via a Builder. This Builder can get hard limits
* during construction time and can be reused. After each "build()" the
* Builder is reset (except for the hard limits). Hard limits can be exceeded
* when setting the actual values and can be used to ensure, that serialization
* does not goe crazy.
*
* A limit of 0 means, that there is no limit set at all for this value.
*
* @author roland
* @since 15.01.13
*/
public final class JsonConvertOptions {
/**
* Default JsonConvertOptions filled with the default values as defined in ConfigKey
*/
public static final JsonConvertOptions DEFAULT = new Builder().build();
// Maximum depth used for serialization
private int maxDepth;
// Maximal size of collections returned
private int maxCollectionSize;
// Maximum number of objects to return
private int maxObjects;
// Handler which determines what should be done when
// extracting of an value fails
private ValueFaultHandler faultHandler;
// Use a builder to construct this object
private JsonConvertOptions(int pMaxDepth, int pMaxCollectionSize, int pMaxObjects,
ValueFaultHandler pFaultHandler) {
maxDepth = pMaxDepth;
maxCollectionSize = pMaxCollectionSize;
maxObjects = pMaxObjects;
faultHandler = pFaultHandler;
}
/**
* Check whether the maximum depth has been reached
* @param pDepth current depth to check
* @return true if the maximum depth has been exceeded, false otherwise
*/
public boolean maxDepthReached(int pDepth) {
return maxDepth != 0 && pDepth >= maxDepth;
}
/**
* Check whether the maximum number of objects has been exceeded
*
* @param pObjectCount count to check
* @return true if the maximum number of objects has been exceeded, false otherwise
*/
public boolean maxObjectExceeded(int pObjectCount) {
return maxObjects != 0 && pObjectCount > maxObjects;
}
/**
* Get the size of the collection taking into account the maximum size of a collection allowed.
*
* @param pCollectionSize collection size to check
* @return the original collection size if is smalled than the maximum collections, the maximum itself otherwise.
*/
public int getCollectionSizeTruncated(int pCollectionSize) {
return maxCollectionSize != 0 && pCollectionSize > maxCollectionSize ?
maxCollectionSize :
pCollectionSize;
}
/**
* Get the configure fault handler which determines, how extractions fault are dealt with
*
* @return the configured fault handler
*/
public ValueFaultHandler getValueFaultHandler() {
return faultHandler;
}
// ===================================================================================
/**
* Builder for constructing a convert options objects
*/
public static class Builder {
private int hardMaxDepth;
private int hardMaxCollectionSize;
private int hardMaxObjects;
private int maxDepth;
private int maxCollectionSize;
private int maxObjects;
private ValueFaultHandler faultHandler;
private boolean useAttributeFilter;
/**
* Default constructor using default hard limits
*/
public Builder() {
this(0,0,0);
}
/**
* Constructor with hard limits. No value set later on this builder can be larger
* than these limits.
*
* @param pHardMaxDepth hard limit for maxDepth
* @param pHardMaxCollectionSize hard limit for maxCollectionSize
* @param pHardMaxObjects hard limit for maxObjects.
*/
public Builder(int pHardMaxDepth,int pHardMaxCollectionSize,int pHardMaxObjects) {
// Default values
hardMaxDepth = pHardMaxDepth;
hardMaxCollectionSize = pHardMaxCollectionSize;
hardMaxObjects = pHardMaxObjects;
faultHandler = ValueFaultHandler.THROWING_VALUE_FAULT_HANDLER;
}
/**
* Set the maximum depth for how deep serialization should go. The number cannot
* be set larger than the hard limit given in the constructor
*
* @param pMaxDepth maximal depth when traversing an object tree during serialization.
* @return this builder
*/
public Builder maxDepth(int pMaxDepth) {
maxDepth = checkWithHardLimit(pMaxDepth,hardMaxDepth);
return this;
}
/**
* Set the maximal size of collections when serializing collections. The number cannot
* be set larger than the hard limit given in the constructor.
*
* @param pMaxCollectionSize maximum size of objects returned in a serialized collection
* @return this builder
*/
public Builder maxCollectionSize(int pMaxCollectionSize) {
maxCollectionSize = checkWithHardLimit(pMaxCollectionSize,hardMaxCollectionSize);
return this;
}
/**
* Set the maximum number of objects to serialize. The number cannot be set larger than the
* hard limit given in the constructor.
*
* @param pMaxObjects maximum number of objects
* @return this builder
*/
public Builder maxObjects(int pMaxObjects) {
maxObjects = checkWithHardLimit(pMaxObjects,hardMaxObjects);
return this;
}
/**
* Set the handler which determines what should be done when
* extracting of an value fails.
*
* @param pFaultHandler handler to use which can be either {@link ValueFaultHandler#THROWING_VALUE_FAULT_HANDLER}
* or {@link ValueFaultHandler#THROWING_VALUE_FAULT_HANDLER}.
* If argument is null, it is ignored
* @return this builder
*/
public Builder faultHandler(ValueFaultHandler pFaultHandler) {
if (pFaultHandler != null) {
faultHandler = pFaultHandler;
}
return this;
}
/**
* Whether an attribute filter should be used to ignore missing attributes when a path is
* applied
*
* @param pUseFilter if a filter should be used or not
* @return this builder
*/
public Builder useAttributeFilter(boolean pUseFilter) {
useAttributeFilter = pUseFilter;
return this;
}
/**
* Build the convert options and reset this builder
*
* @return the options created.
*/
public JsonConvertOptions build() {
ValueFaultHandler handler = useAttributeFilter ?
new PathAttributeFilterValueFaultHandler(faultHandler) :
faultHandler;
JsonConvertOptions opts = new JsonConvertOptions(maxDepth,maxCollectionSize,maxObjects,handler);
maxDepth = 0;
maxCollectionSize = 0;
maxObjects = 0;
return opts;
}
// =================================================================================================
// Check with the given hard limit
private int checkWithHardLimit(int pLimit, int pHardLimit) {
return pLimit < pHardLimit || pHardLimit == 0 ? pLimit : pHardLimit;
}
}
}