org.jolokia.service.serializer.object.TabularDataConverter Maven / Gradle / Ivy
package org.jolokia.service.serializer.object;
/*
* Copyright 2009-2011 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.
*/
import java.util.*;
import javax.management.openmbean.*;
import org.json.simple.*;
/**
* Converter for {@link TabularData}
*
* @author roland
* @since 28.09.11
*/
class TabularDataConverter extends OpenTypeConverter {
// Fixed key names for tabular data represention maps for MXBeans.
private static final String TD_KEY_KEY = "key";
private static final String TD_KEY_VALUE = "value";
/**
* Constructor
*
* @param pDispatcher parent converter used for recursive conversion
*/
public TabularDataConverter(OpenTypeDeserializer pDispatcher) {
super(pDispatcher);
}
/** {@inheritDoc} */
@Override
boolean canConvert(OpenType pType) {
return pType instanceof TabularType;
}
/** {@inheritDoc} */
@Override
Object convertToObject(TabularType pType, Object pFrom) {
JSONObject value = getAsJsonObject(pFrom);
// Convert simple map representation (with rowtype "key" and "value")
if (checkForMapAttributeWithSimpleKey(pType)) {
return convertToTabularTypeFromMap(pType, value);
}
// If it is given a a full representation (with "indexNames" and "values"), then parse this
// accordingly
if (checkForFullTabularDataRepresentation(value, pType)) {
return convertTabularDataFromFullRepresentation(value, pType);
}
// Its a plain TabularData, which is tried to convert rom a maps of maps
TabularDataSupport tabularData = new TabularDataSupport(pType);
// Recursively go down the map and collect the values
putRowsToTabularData(tabularData, value, pType.getIndexNames().size());
return tabularData;
}
// =========================================================================================================
private JSONObject getAsJsonObject(Object pFrom) {
JSONAware jsonVal = toJSON(pFrom);
if (!(jsonVal instanceof JSONObject)) {
throw new IllegalArgumentException("Expected JSON type for a TabularData is JSONObject, not " + jsonVal.getClass());
}
return (JSONObject) jsonVal;
}
private boolean checkForMapAttributeWithSimpleKey(TabularType pType) {
// The key and value must have a specific format
return checkForMapKey(pType) && checkForMapValue(pType);
}
// A map is translated into a TabularData with a rowtype with two entries: "value" and "key"
private boolean checkForMapValue(TabularType pType) {
CompositeType rowType = pType.getRowType();
// Two entries in the row: "key" and "value"
return rowType.containsKey(TD_KEY_VALUE) && rowType.containsKey(TD_KEY_KEY) && rowType.keySet().size() == 2;
}
// The tabular data representing a map must have a single index named "key" which must be a simple type
private boolean checkForMapKey(TabularType pType) {
List indexNames = pType.getIndexNames();
return
// Single index named "key"
indexNames.size() == 1 && indexNames.contains(TD_KEY_KEY) &&
// Only convert to map for simple types for all others use normal conversion. See #105 for details.
pType.getRowType().getType(TD_KEY_KEY) instanceof SimpleType;
}
// Check for a full table data representation and do some sanity checks
private boolean checkForFullTabularDataRepresentation(JSONObject pValue, TabularType pType) {
if (pValue.containsKey("indexNames") && pValue.containsKey("values") && pValue.size() == 2) {
Object jsonVal = pValue.get("indexNames");
if (!(jsonVal instanceof JSONArray)) {
throw new IllegalArgumentException("Index names for tabular data must given as JSON array, not " + jsonVal.getClass());
}
JSONArray indexNames = (JSONArray) jsonVal;
List tabularIndexNames = pType.getIndexNames();
if (indexNames.size() != tabularIndexNames.size()) {
throw new IllegalArgumentException("Given array with index names must have " + tabularIndexNames.size() + " entries " +
"(given: " + indexNames + ", required: " + tabularIndexNames + ")");
}
for (Object index : indexNames) {
if (!tabularIndexNames.contains(index.toString())) {
throw new IllegalArgumentException("No index with name '" + index + "' known " +
"(given: " + indexNames + ", required: " + tabularIndexNames + ")");
}
}
return true;
}
return false;
}
private TabularData convertToTabularTypeFromMap(TabularType pType, JSONObject pValue) {
CompositeType rowType = pType.getRowType();
// A TabularData is requested for mapping a map for the call to an MXBean
// as described in http://download.oracle.com/javase/6/docs/api/javax/management/MXBean.html
// This means, we will convert a JSONObject to the required format
TabularDataSupport tabularData = new TabularDataSupport(pType);
@SuppressWarnings("unchecked")
Map jsonObj = (Map) pValue;
for(Map.Entry entry : jsonObj.entrySet()) {
Map map = new HashMap();
map.put("key", getDispatcher().deserialize(rowType.getType("key"), entry.getKey()));
map.put("value", getDispatcher().deserialize(rowType.getType("value"), entry.getValue()));
try {
CompositeData compositeData = new CompositeDataSupport(rowType, map);
tabularData.put(compositeData);
} catch (OpenDataException e) {
throw new IllegalArgumentException(e.getMessage(),e);
}
}
return tabularData;
}
// Convert complex representation containing "indexNames" and "values"
private TabularData convertTabularDataFromFullRepresentation(JSONObject pValue, TabularType pType) {
JSONAware jsonVal;
jsonVal = (JSONAware) pValue.get("values");
if (!(jsonVal instanceof JSONArray)) {
throw new IllegalArgumentException("Values for tabular data of type " +
pType + " must given as JSON array, not " + jsonVal.getClass());
}
TabularDataSupport tabularData = new TabularDataSupport(pType);
for (Object val : (JSONArray) jsonVal) {
if (!(val instanceof JSONObject)) {
throw new IllegalArgumentException("Tabular-Data values must be given as JSON objects, not " + val.getClass());
}
tabularData.put((CompositeData) getDispatcher().deserialize(pType.getRowType(), val));
}
return tabularData;
}
private void putRowsToTabularData(TabularDataSupport pTabularData, JSONObject pValue, int pLevel) {
TabularType type = pTabularData.getTabularType();
for (Object value : pValue.values()) {
if (!(value instanceof JSONObject)) {
throw new IllegalArgumentException(
"Cannot convert " + pValue + " to type " +
type + " because the object values provided (" + value.getClass() + ") is not of the expected type JSONObject at level " + pLevel);
}
JSONObject jsonValue = (JSONObject) value;
if (pLevel > 1) {
putRowsToTabularData(pTabularData, jsonValue, pLevel - 1);
} else {
pTabularData.put((CompositeData) getDispatcher().deserialize(type.getRowType(), jsonValue));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy