package com.evolveum.midpoint.prism.lex.json.yaml;

import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.events.DocumentEndEvent;
import org.yaml.snakeyaml.events.DocumentStartEvent;
import org.yaml.snakeyaml.events.ImplicitTuple;
import org.yaml.snakeyaml.events.ScalarEvent;

import java.io.IOException;
import java.io.Writer;
import java.util.Collections;

public class MidpointYAMLGenerator extends YAMLGenerator {

	private DumperOptions.Version version;

	public MidpointYAMLGenerator(IOContext ctxt, int jsonFeatures, int yamlFeatures, ObjectCodec codec,
			Writer out, DumperOptions.Version version) throws IOException {
		super(ctxt, jsonFeatures, yamlFeatures, codec, out, version);
		this.version = version;
	}

	/**
	 * Brutal hack, as default behavior has lead to the following:
     * {@code
	 *  - !<http://midpoint.evolveum.com/xml/ns/public/model/scripting-3/SearchExpressionType>
	 *    !<http://midpoint.evolveum.com/xml/ns/public/model/scripting-3/SearchExpressionType> '@element': "http://midpoint.evolveum.com/xml/ns/public/model/scripting-3#search"
     * }
	 *
	 * (so we need to explicitly reset typeId after writing it)
	 */
	public void resetTypeId() {
		_typeId = null;
	}

	@Override
	protected ScalarEvent _scalarEvent(String value, Character style) {
		if (value.indexOf('\n') != -1) {
			style = Character.valueOf('|');
		}

		ImplicitTuple implicit;
		String yamlTag = _typeId;
		if (yamlTag != null) {
			_typeId = null;
			implicit = new ImplicitTuple(false, false);			// we want to always preserve the tags (if they are present)
		} else {
			implicit = new ImplicitTuple(true, true);
		}
		String anchor = _objectId;
		if (anchor != null) {
			_objectId = null;
		}
		return new ScalarEvent(anchor, yamlTag, implicit, value, null, null, style);
	}

	public void newDocument() throws IOException {
		_emitter.emit(new DocumentEndEvent(null, null, false));
		_emitter.emit(new DocumentStartEvent(null, null, true, version, Collections.emptyMap()));
	}

}

@@ -45,16 +45,65 @@
 .yaml;%0A%0A
+import com.fasterxml.jackson.core.Base64Variant;%0A
 import c
@@ -141,16 +141,16 @@
 tCodec;%0A
-
 import c
@@ -540,16 +540,41 @@
 Writer;%0A
+import java.util.Arrays;%0A
 import j
@@ -2224,10 +2224,1237 @@
 ));%0A%09%7D%0A%0A
+%09/*%0A%09 * UGLY HACK - working around YAML serialization problem%0A%09 * (https://github.com/FasterXML/jackson-dataformats-text/issues/90)%0A%09 *%0A%09 * TODO - after YAML problem is fixed, remove this code block (MID-4974)%0A%09 * TODO - if upgrading YAML library before that, make sure everything works (because this code is almost literally copied from YAMLGenerator class)%0A%09 */%0A%0A%09@Override%0A%09public void writeBinary(Base64Variant b64variant, byte%5B%5D data, int offset, int len) throws IOException%0A%09%7B%0A%09%09if (data == null) %7B%0A%09%09%09writeNull();%0A%09%09%09return;%0A%09%09%7D%0A%09%09_verifyValueWrite(%22write Binary value%22);%0A%09%09if (offset %3E 0 %7C%7C (offset+len) != data.length) %7B%0A%09%09%09data = Arrays.copyOfRange(data, offset, offset+len);%0A%09%09%7D%0A%09%09_writeScalarBinaryPatched(b64variant, data);%0A%09%7D%0A%0A%09private final static ImplicitTuple EXPLICIT_TAGS = new ImplicitTuple(false, false);%0A%09private final static Character STYLE_LITERAL = '%7C';%0A%09private final static Character STYLE_BASE64 = STYLE_LITERAL;%0A%09private void _writeScalarBinaryPatched(Base64Variant b64variant, byte%5B%5D data) throws IOException%0A%09%7B%0A%09%09String encoded = b64variant.encode(data);%0A%09%09_emitter.emit(new ScalarEvent(null, TAG_BINARY, EXPLICIT_TAGS, encoded,%0A%09%09%09%09null, null, STYLE_BASE64));%0A%09%7D%0A%0A%09/*%0A%09 *  END OF UGLY HACK%0A%09 */%0A
 %7D%0A

Fix Base64 YAML encoding