Repository: nifi
Updated Branches:
  refs/heads/master 620d44686 -> 2c8c9374a


http://git-wip-us.apache.org/repos/asf/nifi/blob/2c8c9374/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestWriteXMLResultUtils.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestWriteXMLResultUtils.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestWriteXMLResultUtils.java
new file mode 100755
index 0000000..6bc7f83
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestWriteXMLResultUtils.java
@@ -0,0 +1,490 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.xml;
+
+import org.apache.nifi.serialization.SimpleRecordSchema;
+import org.apache.nifi.serialization.record.DataType;
+import org.apache.nifi.serialization.record.ListRecordSet;
+import org.apache.nifi.serialization.record.MapRecord;
+import org.apache.nifi.serialization.record.Record;
+import org.apache.nifi.serialization.record.RecordField;
+import org.apache.nifi.serialization.record.RecordFieldType;
+import org.apache.nifi.serialization.record.RecordSchema;
+import org.apache.nifi.serialization.record.RecordSet;
+import org.apache.nifi.serialization.record.SchemaIdentifier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestWriteXMLResultUtils {
+
+    protected static final String FIELD_NAME = "NAME";
+    protected static final String FIELD_AGE = "AGE";
+    protected static final String FIELD_COUNTRY = "COUNTRY";
+    protected static final String FIELD_ADDRESS = "ADDRESS";
+    protected static final String FIELD_STREET = "STREET";
+    protected static final String FIELD_CITY = "CITY";
+    protected static final String FIELD_CHILDREN = "CHILDREN";
+
+    protected static Map<String,Object> RECORD_FIELDS_PERSON_1 = new 
HashMap<>();
+    protected static Map<String,Object> RECORD_FIELDS_PERSON_2 = new 
HashMap<>();
+    protected static Map<String,Object> RECORD_FIELDS_ADDRESS_1 = new 
HashMap<>();
+    protected static Map<String,Object> RECORD_FIELDS_ADDRESS_2 = new 
HashMap<>();
+
+    protected static Object[] ARRAY_CHILDREN = {"Tom", "Anna", "Ben"};
+    protected static Object[] ARRAY_CHILDREN_WITH_NULL_VALUE = {"Tom", null, 
"Ben"};
+    protected static Object[] ARRAY_CHILDREN_ONLY_NULL_VALUES = {null, null, 
null};
+
+    static {
+        RECORD_FIELDS_PERSON_1.put(FIELD_NAME, "Cleve Butler");
+        RECORD_FIELDS_PERSON_1.put(FIELD_AGE, 42);
+        RECORD_FIELDS_PERSON_1.put(FIELD_COUNTRY, "USA");
+        RECORD_FIELDS_PERSON_2.put(FIELD_NAME, "Ainslie Fletcher");
+        RECORD_FIELDS_PERSON_2.put(FIELD_AGE, 33);
+        RECORD_FIELDS_PERSON_2.put(FIELD_COUNTRY, "UK");
+        RECORD_FIELDS_ADDRESS_1.put(FIELD_STREET, "292 West Street");
+        RECORD_FIELDS_ADDRESS_1.put(FIELD_CITY, "Jersey City");
+        RECORD_FIELDS_ADDRESS_2.put(FIELD_STREET, "123 6th St.");
+        RECORD_FIELDS_ADDRESS_2.put(FIELD_CITY, "Seattle");
+
+        RECORD_FIELDS_PERSON_1 = 
Collections.unmodifiableMap(RECORD_FIELDS_PERSON_1);
+        RECORD_FIELDS_PERSON_2 = 
Collections.unmodifiableMap(RECORD_FIELDS_PERSON_2);
+        RECORD_FIELDS_ADDRESS_1 = 
Collections.unmodifiableMap(RECORD_FIELDS_ADDRESS_1);
+        RECORD_FIELDS_ADDRESS_2 = 
Collections.unmodifiableMap(RECORD_FIELDS_ADDRESS_2);
+    }
+
+    protected static final SchemaIdentifier SCHEMA_IDENTIFIER_PERSON = 
SchemaIdentifier.builder().name("PERSON").id(0L).version(0).build();
+    protected static final SchemaIdentifier SCHEMA_IDENTIFIER_RECORD = 
SchemaIdentifier.builder().name("RECORD").id(0L).version(0).build();
+
+    protected static final String DATE_FORMAT = 
RecordFieldType.DATE.getDefaultFormat();
+    protected static final String TIME_FORMAT = 
RecordFieldType.TIME.getDefaultFormat();
+    protected static final String TIMESTAMP_FORMAT = 
RecordFieldType.TIMESTAMP.getDefaultFormat();
+
+    public enum NullValues {
+        ONLY_NULL,
+        HAS_NULL,
+        WITHOUT_NULL,
+        EMPTY
+    }
+
+    /*
+    Simple records
+     */
+
+    protected static RecordSet getSingleRecord() {
+        RecordSchema schema = getSimpleSchema();
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_1));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static RecordSet getSimpleRecords() {
+        RecordSchema schema = getSimpleSchema();
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_1));
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static RecordSet getSimpleRecordsWithoutIdentifierInSchema() {
+        RecordSchema schema = getSimpleSchemaWithoutIdentifier();
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_1));
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static RecordSet getSimpleRecordsWithNullValues() {
+        RecordSchema schema = getSimpleSchema();
+
+        Map<String, Object> recordWithoutName1 = new 
HashMap<>(RECORD_FIELDS_PERSON_1);
+        Map<String, Object> recordWithoutName2 = new 
HashMap<>(RECORD_FIELDS_PERSON_2);
+
+        recordWithoutName1.put(FIELD_NAME, null);
+        recordWithoutName2.remove(FIELD_NAME);
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, recordWithoutName1));
+        records.add(new MapRecord(schema, recordWithoutName2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static RecordSet getEmptyRecordsWithEmptySchema() {
+        RecordSchema schema = getEmptySchema();
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, Collections.emptyMap()));
+        records.add(new MapRecord(schema, Collections.emptyMap()));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static List<RecordField> getSimpleRecordFields() {
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_NAME, 
RecordFieldType.STRING.getDataType()));
+        fields.add(new RecordField(FIELD_AGE, 
RecordFieldType.INT.getDataType()));
+        fields.add(new RecordField(FIELD_COUNTRY, 
RecordFieldType.STRING.getDataType()));
+        return fields;
+    }
+
+    protected static RecordSchema getSimpleSchema() {
+        return new SimpleRecordSchema(getSimpleRecordFields(), 
SCHEMA_IDENTIFIER_PERSON);
+    }
+
+    protected static RecordSchema getSimpleSchemaWithoutIdentifier() {
+        return new SimpleRecordSchema(getSimpleRecordFields());
+    }
+
+    protected static RecordSchema getEmptySchema() {
+        return new SimpleRecordSchema(Collections.emptyList(), 
SCHEMA_IDENTIFIER_PERSON);
+    }
+
+
+
+    /*
+    Simple nested records
+     */
+
+    protected static RecordSet getNestedRecords() {
+        RecordSchema innerSchema = getNestedSchema();
+
+        final DataType recordType = 
RecordFieldType.RECORD.getRecordDataType(innerSchema);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, recordType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Record innerRecord1 = new MapRecord(innerSchema, 
RECORD_FIELDS_ADDRESS_1);
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(innerSchema, 
RECORD_FIELDS_ADDRESS_2);
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+
+    protected static RecordSet getNestedRecordsWithNullValues() {
+        RecordSchema innerSchema = getNestedSchema();
+
+        final DataType recordType = 
RecordFieldType.RECORD.getRecordDataType(innerSchema);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, recordType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Map<String, Object> recordWithoutStreet1 = new 
HashMap<>(RECORD_FIELDS_ADDRESS_1);
+        Map<String, Object> recordWithoutStreet2 = new 
HashMap<>(RECORD_FIELDS_ADDRESS_2);
+
+        recordWithoutStreet1.put(FIELD_STREET, null);
+        recordWithoutStreet2.remove(FIELD_STREET);
+
+        Record innerRecord1 = new MapRecord(innerSchema, recordWithoutStreet1);
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(innerSchema, recordWithoutStreet2);
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+
+    protected static RecordSet getNestedRecordsWithOnlyNullValues() {
+        RecordSchema innerSchema = getNestedSchema();
+
+        final DataType recordType = 
RecordFieldType.RECORD.getRecordDataType(innerSchema);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, recordType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Map<String, Object> recordWithoutStreet1 = new 
HashMap<>(RECORD_FIELDS_ADDRESS_1);
+        Map<String, Object> recordWithoutStreet2 = new 
HashMap<>(RECORD_FIELDS_ADDRESS_2);
+
+        recordWithoutStreet1.put(FIELD_STREET, null);
+        recordWithoutStreet1.put(FIELD_CITY, null);
+        recordWithoutStreet2.remove(FIELD_STREET);
+        recordWithoutStreet2.remove(FIELD_CITY);
+
+        Record innerRecord1 = new MapRecord(innerSchema, recordWithoutStreet1);
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(innerSchema, recordWithoutStreet2);
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+
+    protected static RecordSet getEmptyNestedRecordEmptyNestedSchema() {
+        RecordSchema innerSchema = new 
SimpleRecordSchema(Collections.emptyList());
+
+        final DataType recordType = 
RecordFieldType.RECORD.getRecordDataType(innerSchema);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, recordType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Record innerRecord1 = new MapRecord(innerSchema, 
Collections.emptyMap());
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(innerSchema, 
Collections.emptyMap());
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+
+    protected static RecordSet getEmptyNestedRecordDefinedSchema() {
+        RecordSchema innerSchema = getNestedSchema();
+
+        final DataType recordType = 
RecordFieldType.RECORD.getRecordDataType(innerSchema);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, recordType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Record innerRecord1 = new MapRecord(innerSchema, 
Collections.EMPTY_MAP);
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(innerSchema, 
Collections.EMPTY_MAP);
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+
+    protected static List<RecordField> getNestedRecordFields() {
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_STREET, 
RecordFieldType.STRING.getDataType()));
+        fields.add(new RecordField(FIELD_CITY, 
RecordFieldType.STRING.getDataType()));
+        return fields;
+    }
+
+    protected static RecordSchema getNestedSchema() {
+        return new SimpleRecordSchema(getNestedRecordFields());
+    }
+
+    /*
+    Arrays
+     */
+
+    protected static RecordSet getRecordWithSimpleArray(NullValues nullValues) 
{
+        Object[] children;
+        if (nullValues.equals(NullValues.HAS_NULL)) {
+            children = ARRAY_CHILDREN_WITH_NULL_VALUE;
+        } else if (nullValues.equals(NullValues.ONLY_NULL)) {
+            children = ARRAY_CHILDREN_ONLY_NULL_VALUES;
+        } else if (nullValues.equals(NullValues.EMPTY)) {
+            children = new Object[]{};
+        } else {
+            children = ARRAY_CHILDREN;
+        }
+
+        final DataType arrayType = 
RecordFieldType.ARRAY.getArrayDataType(RecordFieldType.STRING.getDataType());
+
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_CHILDREN, arrayType));
+        fields.addAll(getSimpleRecordFields());
+
+        Map<String,Object> recordFields1 = new HashMap<>();
+        recordFields1.putAll(RECORD_FIELDS_PERSON_1);
+        recordFields1.put(FIELD_CHILDREN, children);
+
+        Map<String,Object> recordFields2 = new HashMap<>();
+        recordFields2.putAll(RECORD_FIELDS_PERSON_2);
+        recordFields2.put(FIELD_CHILDREN, children);
+
+        RecordSchema schema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, recordFields1));
+        records.add(new MapRecord(schema, recordFields2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+
+
+    /*
+    Maps
+     */
+
+    protected static RecordSet getRecordWithSimpleMap(NullValues nullValues) {
+
+        List<Object> values = new ArrayList<>();
+
+        if (nullValues.equals(NullValues.HAS_NULL)) {
+            values.addAll(Arrays.asList(ARRAY_CHILDREN_WITH_NULL_VALUE));
+        } else if (nullValues.equals(NullValues.ONLY_NULL)) {
+            values.addAll(Arrays.asList(ARRAY_CHILDREN_ONLY_NULL_VALUES));
+        } else if (nullValues.equals(NullValues.WITHOUT_NULL)){
+            values.addAll(Arrays.asList(ARRAY_CHILDREN));
+        }
+
+        Map<String,Object> children = new HashMap<>();
+
+        if (!nullValues.equals(NullValues.EMPTY)) {
+
+            children.put("CHILD1", values.get(0));
+            children.put("CHILD2", values.get(1));
+            children.put("CHILD3", values.get(2));
+        }
+
+        final DataType mapType = 
RecordFieldType.MAP.getMapDataType(RecordFieldType.STRING.getDataType());
+
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_CHILDREN, mapType));
+        fields.addAll(getSimpleRecordFields());
+
+        Map<String,Object> recordFields1 = new HashMap<>();
+        recordFields1.putAll(RECORD_FIELDS_PERSON_1);
+        recordFields1.put(FIELD_CHILDREN, children);
+
+        Map<String,Object> recordFields2 = new HashMap<>();
+        recordFields2.putAll(RECORD_FIELDS_PERSON_2);
+        recordFields2.put(FIELD_CHILDREN, children);
+
+        RecordSchema schema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, recordFields1));
+        records.add(new MapRecord(schema, recordFields2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+
+    /*
+    Choice
+     */
+
+    protected static RecordSet getSimpleRecordsWithChoice() {
+
+        final List<DataType> possibleTypes = new ArrayList<>();
+        possibleTypes.add(RecordFieldType.INT.getDataType());
+        possibleTypes.add(RecordFieldType.LONG.getDataType());
+        possibleTypes.add(RecordFieldType.STRING.getDataType());
+
+        final List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_NAME, 
RecordFieldType.STRING.getDataType()));
+        fields.add(new RecordField(FIELD_AGE, 
RecordFieldType.INT.getDataType()));
+        fields.add(new RecordField(FIELD_COUNTRY, 
RecordFieldType.CHOICE.getChoiceDataType(possibleTypes)));
+
+        RecordSchema schema = new SimpleRecordSchema(getSimpleRecordFields(), 
SCHEMA_IDENTIFIER_PERSON);
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_1));
+        records.add(new MapRecord(schema, RECORD_FIELDS_PERSON_2));
+
+        return new ListRecordSet(schema, records);
+    }
+
+    protected static RecordSet getNestedRecordsTypeChoice() {
+        final List<DataType> possibleTypes = new ArrayList<>();
+        possibleTypes.add(RecordFieldType.INT.getDataType());
+        possibleTypes.add(RecordFieldType.LONG.getDataType());
+        possibleTypes.add(RecordFieldType.RECORD.getDataType());
+
+        final DataType choiceType = 
RecordFieldType.CHOICE.getChoiceDataType(possibleTypes);
+        List<RecordField> fields = new ArrayList<>();
+        fields.add(new RecordField(FIELD_ADDRESS, choiceType));
+        fields.addAll(getSimpleRecordFields());
+
+        RecordSchema outerSchema = new SimpleRecordSchema(fields, 
SCHEMA_IDENTIFIER_PERSON);
+
+        Record innerRecord1 = new MapRecord(new 
SimpleRecordSchema(Collections.emptyList()), RECORD_FIELDS_ADDRESS_1);
+        Record outerRecord1 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_1);
+            put(FIELD_ADDRESS, innerRecord1);
+        }});
+
+        Record innerRecord2 = new MapRecord(new 
SimpleRecordSchema(Collections.emptyList()), RECORD_FIELDS_ADDRESS_2);
+        Record outerRecord2 = new MapRecord(outerSchema, new 
HashMap<String,Object>(){{
+            putAll(RECORD_FIELDS_PERSON_2);
+            put(FIELD_ADDRESS, innerRecord2);
+        }});
+
+        List<Record> records = new ArrayList<>();
+        records.add(outerRecord1);
+        records.add(outerRecord2);
+
+        return new ListRecordSet(outerSchema, records);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/2c8c9374/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriter.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriter.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriter.java
new file mode 100755
index 0000000..372e60d
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriter.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.xml;
+
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.schema.access.SchemaAccessUtils;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlunit.diff.DefaultNodeMatcher;
+import org.xmlunit.diff.ElementSelectors;
+import org.xmlunit.matchers.CompareMatcher;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static org.junit.Assert.assertThat;
+
+public class TestXMLRecordSetWriter {
+
+    private TestRunner setup(XMLRecordSetWriter writer) throws 
InitializationException, IOException {
+        TestRunner runner = 
TestRunners.newTestRunner(TestXMLRecordSetWriterProcessor.class);
+
+        final String outputSchemaText = new 
String(Files.readAllBytes(Paths.get("src/test/resources/xml/testschema3")));
+
+        runner.addControllerService("xml_writer", writer);
+        runner.setProperty(TestXMLRecordSetWriterProcessor.XML_WRITER, 
"xml_writer");
+
+        runner.setProperty(writer, SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY, 
SchemaAccessUtils.SCHEMA_TEXT_PROPERTY);
+        runner.setProperty(writer, SchemaAccessUtils.SCHEMA_TEXT, 
outputSchemaText);
+        runner.setProperty(writer, XMLRecordSetWriter.PRETTY_PRINT_XML, new 
AllowableValue("true"));
+
+        runner.setProperty(writer, "Schema Write Strategy", "no-schema");
+
+        return runner;
+    }
+
+    @Test
+    public void testDefault() throws IOException, InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(writer, XMLRecordSetWriter.ROOT_TAG_NAME, "root");
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+        runner.run();
+        runner.assertQueueEmpty();
+        
runner.assertAllFlowFilesTransferred(TestXMLRecordSetWriterProcessor.SUCCESS, 
1);
+
+        String expected = 
"<root><array_record><array_field>1</array_field><array_field></array_field><array_field>3</array_field>"
 +
+                "<name1>val1</name1><name2></name2></array_record>" +
+                
"<array_record><array_field>1</array_field><array_field></array_field><array_field>3</array_field>"
 +
+                "<name1>val1</name1><name2></name2></array_record></root>";
+        String actual = new 
String(runner.getContentAsByteArray(runner.getFlowFilesForRelationship(TestXMLRecordSetWriterProcessor.SUCCESS).get(0)));
+        assertThat(expected, 
CompareMatcher.isSimilarTo(actual).ignoreWhitespace().withNodeMatcher(new 
DefaultNodeMatcher(ElementSelectors.byNameAndText)));
+    }
+
+    @Test
+    public void testDefaultSingleRecord() throws IOException, 
InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(TestXMLRecordSetWriterProcessor.MULTIPLE_RECORDS, 
"false");
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+        runner.run();
+        runner.assertQueueEmpty();
+        
runner.assertAllFlowFilesTransferred(TestXMLRecordSetWriterProcessor.SUCCESS, 
1);
+
+        String expected = 
"<array_record><array_field>1</array_field><array_field></array_field><array_field>3</array_field>"
 +
+                "<name1>val1</name1><name2></name2></array_record>";
+
+        String actual = new 
String(runner.getContentAsByteArray(runner.getFlowFilesForRelationship(TestXMLRecordSetWriterProcessor.SUCCESS).get(0)));
+        assertThat(expected, 
CompareMatcher.isSimilarTo(actual).ignoreWhitespace().withNodeMatcher(new 
DefaultNodeMatcher(ElementSelectors.byNameAndText)));
+    }
+
+    @Test
+    public void testRootAndRecordNaming() throws IOException, 
InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(writer, XMLRecordSetWriter.ROOT_TAG_NAME, 
"ROOT_NODE");
+        runner.setProperty(writer, XMLRecordSetWriter.RECORD_TAG_NAME, 
"RECORD_NODE");
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+        runner.run();
+        runner.assertQueueEmpty();
+        
runner.assertAllFlowFilesTransferred(TestXMLRecordSetWriterProcessor.SUCCESS, 
1);
+
+        String expected = 
"<ROOT_NODE><RECORD_NODE><array_field>1</array_field><array_field></array_field><array_field>3</array_field>"
 +
+                "<name1>val1</name1><name2></name2></RECORD_NODE>" +
+                
"<RECORD_NODE><array_field>1</array_field><array_field></array_field><array_field>3</array_field>"
 +
+                "<name1>val1</name1><name2></name2></RECORD_NODE></ROOT_NODE>";
+        String actual = new 
String(runner.getContentAsByteArray(runner.getFlowFilesForRelationship(TestXMLRecordSetWriterProcessor.SUCCESS).get(0)));
+        assertThat(expected, 
CompareMatcher.isSimilarTo(actual).ignoreWhitespace().withNodeMatcher(new 
DefaultNodeMatcher(ElementSelectors.byNameAndText)));
+    }
+
+    @Test
+    public void testNullSuppression() throws IOException, 
InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(writer, XMLRecordSetWriter.ROOT_TAG_NAME, "root");
+        runner.setProperty(writer, XMLRecordSetWriter.RECORD_TAG_NAME, 
"record");
+
+        runner.setProperty(writer, XMLRecordSetWriter.SUPPRESS_NULLS, 
XMLRecordSetWriter.ALWAYS_SUPPRESS);
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+        runner.run();
+        runner.assertQueueEmpty();
+        
runner.assertAllFlowFilesTransferred(TestXMLRecordSetWriterProcessor.SUCCESS, 
1);
+
+        String expected = 
"<root><record><array_field>1</array_field><array_field>3</array_field>" +
+                "<name1>val1</name1></record>" +
+                
"<record><array_field>1</array_field><array_field>3</array_field>" +
+                "<name1>val1</name1></record></root>";
+        String actual = new 
String(runner.getContentAsByteArray(runner.getFlowFilesForRelationship(TestXMLRecordSetWriterProcessor.SUCCESS).get(0)));
+        assertThat(expected, 
CompareMatcher.isSimilarTo(actual).ignoreWhitespace().withNodeMatcher(new 
DefaultNodeMatcher(ElementSelectors.byNameAndText)));
+    }
+
+    @Test
+    public void testArrayWrapping() throws IOException, 
InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(writer, XMLRecordSetWriter.ROOT_TAG_NAME, "root");
+        runner.setProperty(writer, XMLRecordSetWriter.RECORD_TAG_NAME, 
"record");
+
+        runner.setProperty(writer, XMLRecordSetWriter.ARRAY_WRAPPING, 
XMLRecordSetWriter.USE_PROPERTY_AS_WRAPPER);
+        runner.setProperty(writer, XMLRecordSetWriter.ARRAY_TAG_NAME, "wrap");
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+        runner.run();
+        runner.assertQueueEmpty();
+        
runner.assertAllFlowFilesTransferred(TestXMLRecordSetWriterProcessor.SUCCESS, 
1);
+
+        String expected = 
"<root><record><wrap><array_field>1</array_field><array_field></array_field><array_field>3</array_field></wrap>"
 +
+                "<name1>val1</name1><name2></name2></record>" +
+                
"<record><wrap><array_field>1</array_field><array_field></array_field><array_field>3</array_field></wrap>"
 +
+                "<name1>val1</name1><name2></name2></record></root>";
+        String actual = new 
String(runner.getContentAsByteArray(runner.getFlowFilesForRelationship(TestXMLRecordSetWriterProcessor.SUCCESS).get(0)));
+        assertThat(expected, 
CompareMatcher.isSimilarTo(actual).ignoreWhitespace().withNodeMatcher(new 
DefaultNodeMatcher(ElementSelectors.byNameAndText)));
+    }
+
+    @Test
+    public void testValidation() throws IOException, InitializationException {
+        XMLRecordSetWriter writer = new XMLRecordSetWriter();
+        TestRunner runner = setup(writer);
+
+        runner.setProperty(writer, XMLRecordSetWriter.ROOT_TAG_NAME, "root");
+        runner.setProperty(writer, XMLRecordSetWriter.RECORD_TAG_NAME, 
"record");
+
+        runner.setProperty(writer, XMLRecordSetWriter.ARRAY_WRAPPING, 
XMLRecordSetWriter.USE_PROPERTY_AS_WRAPPER);
+
+        runner.enableControllerService(writer);
+        runner.enqueue("");
+
+        String message = "Processor has 1 validation failures:\n" +
+                "'xml_writer' validated against 'xml_writer' is invalid 
because Controller Service is not valid: " +
+                "'array_tag_name' is invalid because if property 
'array_wrapping' is defined as 'Use Property as Wrapper' " +
+                "or 'Use Property for Elements' the property 'Array Tag Name' 
has to be set.\n";
+
+        try {
+            runner.run();
+        } catch (AssertionError e) {
+            Assert.assertEquals(message, e.getMessage());
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/2c8c9374/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriterProcessor.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriterProcessor.java
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriterProcessor.java
new file mode 100755
index 0000000..57ee624
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/java/org/apache/nifi/xml/TestXMLRecordSetWriterProcessor.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.xml;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.serialization.RecordSetWriter;
+import org.apache.nifi.serialization.RecordSetWriterFactory;
+import org.apache.nifi.serialization.SimpleRecordSchema;
+import org.apache.nifi.serialization.record.ListRecordSet;
+import org.apache.nifi.serialization.record.MapRecord;
+import org.apache.nifi.serialization.record.Record;
+import org.apache.nifi.serialization.record.RecordSchema;
+import org.apache.nifi.serialization.record.RecordSet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class TestXMLRecordSetWriterProcessor extends AbstractProcessor {
+
+    static final PropertyDescriptor XML_WRITER = new 
PropertyDescriptor.Builder()
+            .name("xml_writer")
+            .identifiesControllerService(XMLRecordSetWriter.class)
+            .required(true)
+            .build();
+
+    static final PropertyDescriptor MULTIPLE_RECORDS = new 
PropertyDescriptor.Builder()
+            .name("multiple_records")
+            .allowableValues("true", "false")
+            .defaultValue("true")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final Relationship SUCCESS = new 
Relationship.Builder().name("success").description("success").build();
+
+    @Override
+    public void onTrigger(ProcessContext context, ProcessSession session) 
throws ProcessException {
+        FlowFile flowFile = session.get();
+
+        final RecordSetWriterFactory writerFactory = 
context.getProperty(XML_WRITER).asControllerService(RecordSetWriterFactory.class);
+        flowFile = session.write(flowFile, out -> {
+            try {
+
+                final RecordSchema schema = writerFactory.getSchema(null, 
null);
+
+                boolean multipleRecords = 
Boolean.parseBoolean(context.getProperty(MULTIPLE_RECORDS).getValue());
+                RecordSet recordSet = getRecordSet(multipleRecords);
+
+                final RecordSetWriter writer = 
writerFactory.createWriter(getLogger(), schema, out);
+
+
+                writer.write(recordSet);
+                writer.flush();
+
+
+            } catch (Exception e) {
+                throw new ProcessException(e.getMessage());
+            }
+
+        });
+        session.transfer(flowFile, SUCCESS);
+    }
+
+    @Override
+    protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return new ArrayList<PropertyDescriptor>() {{ add(XML_WRITER); 
add(MULTIPLE_RECORDS); }};
+    }
+
+    @Override
+    public Set<Relationship> getRelationships() {
+        return new HashSet<Relationship>() {{ add(SUCCESS); }};
+    }
+
+    protected static RecordSet getRecordSet(boolean multipleRecords) {
+        Object[] arrayVals = {1, null, 3};
+
+        Map<String,Object> recordFields = new HashMap<>();
+        recordFields.put("name1", "val1");
+        recordFields.put("name2", null);
+        recordFields.put("array_field", arrayVals);
+
+        RecordSchema emptySchema = new 
SimpleRecordSchema(Collections.emptyList());
+
+        List<Record> records = new ArrayList<>();
+        records.add(new MapRecord(emptySchema, recordFields));
+
+        if (multipleRecords) {
+            records.add(new MapRecord(emptySchema, recordFields));
+        }
+
+        return new ListRecordSet(emptySchema, records);
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/2c8c9374/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/resources/xml/testschema3
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/resources/xml/testschema3
 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/resources/xml/testschema3
new file mode 100755
index 0000000..e1937df
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services/src/test/resources/xml/testschema3
@@ -0,0 +1,12 @@
+{
+  "name": "array_record",
+  "namespace": "nifi",
+  "type": "record",
+  "fields": [
+    { "name": "array_field", "type":
+      { "type": "array", "items": "int" }
+    },
+    { "name": "name1", "type": "string" },
+    { "name": "name2", "type": "string" }
+  ]
+}
\ No newline at end of file

Reply via email to