/*
* Copyright (c) 2010-2016 Evolveum
*
* 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.evolveum.midpoint.prism.lex.json;
import com.evolveum.midpoint.prism.lex.json.yaml.MidpointYAMLFactory;
import com.evolveum.midpoint.prism.lex.json.yaml.MidpointYAMLGenerator;
import com.evolveum.midpoint.prism.lex.json.yaml.MidpointYAMLParser;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
//import com.fasterxml.jackson.core.YAMLGenerator;
public class YamlLexicalProcessor extends AbstractJsonLexicalProcessor {
private static final String YAML = "tag:yaml.org,2002:";
private static final String TAG_STRING = YAML + "str";
private static final String TAG_INT = YAML + "int";
private static final String TAG_BOOL = YAML + "bool";
private static final String TAG_FLOAT = YAML + "float";
private static final String TAG_NULL = YAML + "null";
//------------------------END OF METHODS FOR SERIALIZATION -------------------------------
@Override
public boolean canRead(@NotNull File file) throws IOException {
return file.getName().endsWith(".yaml");
}
@Override
public boolean canRead(@NotNull String dataString) {
return dataString.startsWith("---");
}
public YAMLGenerator createJacksonGenerator(StringWriter out) throws SchemaException{
try {
MidpointYAMLFactory factory = new MidpointYAMLFactory();
MidpointYAMLGenerator generator = (MidpointYAMLGenerator) factory.createGenerator(out);
generator.setPrettyPrinter(new DefaultPrettyPrinter());
generator.setCodec(configureMapperForSerialization());
return generator;
} catch (IOException ex){
throw new SchemaException("Schema error during serializing to JSON.", ex);
}
}
private ObjectMapper configureMapperForSerialization(){
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
// mapper.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS, As.EXISTING_PROPERTY);
// mapper.configure(SerializationFeaCture.);
// mapper.setSerializationInclusion(Include.NON_NULL);
mapper.registerModule(createSerializerModule());
mapper.disableDefaultTyping();
// mapper.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS);
// mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.EXISTING_PROPERTY);
// //mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.EXTERNAL_PROPERTY);
// mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
return mapper;
}
private Module createSerializerModule(){
SimpleModule module = new SimpleModule("MidpointModule", new Version(0, 0, 0, "aa"));
module.addSerializer(QName.class, new QNameSerializer());
module.addSerializer(PolyString.class, new PolyStringSerializer());
module.addSerializer(ItemPath.class, new ItemPathSerializer());
module.addSerializer(ItemPathType.class, new ItemPathTypeSerializer());
// module.addSerializer(JAXBElement.class, new JaxbElementSerializer());
module.addSerializer(XMLGregorianCalendar.class, new XmlGregorianCalendarSerializer());
module.addSerializer(Element.class, new DomElementSerializer());
return module;
}
@Override
protected MidpointYAMLParser createJacksonParser(InputStream stream) throws SchemaException, IOException {
MidpointYAMLFactory factory = new MidpointYAMLFactory();
try {
MidpointYAMLParser p = (MidpointYAMLParser) factory.createParser(stream);
// p.enable(Feature.BOGUS);
// String oid = p.getObjectId();
return p;
} catch (IOException e) {
throw e;
}
}
@Override
protected QName tagToTypeName(Object tag, AbstractJsonLexicalProcessor.JsonParsingContext ctx) throws IOException, SchemaException {
if (tag == null) {
return null;
} if (TAG_STRING.equals(tag)) {
return DOMUtil.XSD_STRING;
} else if (TAG_BOOL.equals(tag)) {
return DOMUtil.XSD_BOOLEAN;
} else if (TAG_NULL.equals(tag)) {
return null; // ???
} else if (TAG_INT.equals(tag)) {
QName type = determineNumberType(ctx.parser.getNumberType());
if (DOMUtil.XSD_INT.equals(type) || DOMUtil.XSD_INTEGER.equals(type)) {
return type;
} else {
return DOMUtil.XSD_INT; // suspicious
}
} else if (TAG_FLOAT.equals(tag)) {
QName type = determineNumberType(ctx.parser.getNumberType());
if (DOMUtil.XSD_FLOAT.equals(type) || DOMUtil.XSD_DOUBLE.equals(type) || DOMUtil.XSD_DECIMAL.equals(type)) {
return type;
} else {
return DOMUtil.XSD_FLOAT; // suspicious
}
} else if (tag instanceof String) {
return QNameUtil.uriToQName((String) tag, true);
} else {
// TODO issue a warning?
return null;
}
}
@Override
protected boolean supportsInlineTypes() {
return true;
}
@Override
protected void writeInlineType(QName typeName, AbstractJsonLexicalProcessor.JsonSerializationContext ctx) throws IOException {
ctx.generator.writeTypeId(QNameUtil.qNameToUri(typeName, false, '/'));
}
@Override
protected void resetInlineTypeIfPossible(JsonSerializationContext ctx) {
((MidpointYAMLGenerator) ctx.generator).resetTypeId(); // brutal hack
}
}