org.rapidoid.data.Parse Maven / Gradle / Ivy
/*-
* #%L
* rapidoid-commons
* %%
* Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors
* %%
* 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.
* #L%
*/
package org.rapidoid.data;
import org.rapidoid.RapidoidThing;
/**
* @author Nikolche Mihajlovski
* @since 4.4.0
*/
public class Parse extends RapidoidThing {
enum DataFormat {
JSON, XML, YAML
}
private static final DataFormat[] XML_FIRST = {DataFormat.XML, DataFormat.JSON, DataFormat.YAML};
private static final DataFormat[] JSON_FIRST = {DataFormat.JSON, DataFormat.XML, DataFormat.YAML};
private static final DataFormat[] YAML_FIRST = {DataFormat.YAML, DataFormat.JSON, DataFormat.XML};
public static T data(String data, Class targetType) {
return data(data.getBytes(), targetType);
}
@SuppressWarnings("unchecked")
public static T data(byte[] data, Class targetType) {
if (data == null) {
return null;
}
// don't parse if the target type is byte[]
if (targetType == byte[].class) {
return (T) data;
}
DataFormat[] formatsOrder = detectDataFormat(data);
return tryToParseData(data, formatsOrder, targetType);
}
private static T tryToParseData(byte[] data, DataFormat[] formatsOrder, Class targetType) {
Exception firstException = null;
for (DataFormat dataFormat : formatsOrder) {
switch (dataFormat) {
case JSON:
try {
return JSON.parse(data, targetType);
} catch (Exception e) {
if (firstException == null) {
firstException = e;
}
}
break;
case XML:
try {
return XML.parse(data, targetType);
} catch (Exception e) {
if (firstException == null) {
firstException = e;
}
}
break;
case YAML:
try {
return YAML.parse(data, targetType);
} catch (Exception e) {
if (firstException == null) {
firstException = e;
}
}
break;
default:
break;
}
}
throw new RuntimeException("Not a valid JSON, XML nor YAML format!", firstException);
}
static DataFormat[] detectDataFormat(byte[] data) {
if (data.length == 0) {
return YAML_FIRST;
}
byte start = findFirstNonWhitespaceByte(data);
if (start == '<') {
return XML_FIRST;
} else if (start == ' ' || (start == '-' && dataStartsWithYAMLMark(data))) {
return YAML_FIRST;
} else {
return JSON_FIRST;
}
}
private static byte findFirstNonWhitespaceByte(byte[] data) {
int i = 0;
while (Character.isWhitespace(data[i])) {
i++;
if (i >= data.length) {
return ' ';
}
}
return data[i];
}
private static boolean dataStartsWithYAMLMark(byte[] data) {
return data.length >= 3 && data[0] == '-' && data[1] == '-' && data[2] == '-';
}
}