/*
* 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.persistence;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import org.apache.nifi.util.ComponentIdGenerator;
import org.apache.nifi.web.api.dto.FlowSnippetDTO;
import org.apache.nifi.web.api.dto.ProcessorDTO;
import org.apache.nifi.web.api.dto.TemplateDTO;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.HistogramDiff;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.junit.Test;
public class TemplateSerializerTest {
@Test
public void validateDiffWithChangingComponentIdAndAdditionalElements() throws Exception {
// Create initial template (TemplateDTO)
FlowSnippetDTO snippet = new FlowSnippetDTO();
Set<ProcessorDTO> procs = new HashSet<>();
for (int i = 4; i > 0; i--) {
ProcessorDTO procDTO = new ProcessorDTO();
procDTO.setType("Processor" + i + ".class");
procDTO.setId(ComponentIdGenerator.generateId().toString());
procs.add(procDTO);
}
snippet.setProcessors(procs);
TemplateDTO origTemplate = new TemplateDTO();
origTemplate.setDescription("MyTemplate");
origTemplate.setId("MyTemplate");
origTemplate.setSnippet(snippet);
byte[] serTemplate = TemplateSerializer.serialize(origTemplate);
// Deserialize Template into TemplateDTP
ByteArrayInputStream in = new ByteArrayInputStream(serTemplate);
JAXBContext context = JAXBContext.newInstance(TemplateDTO.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement<TemplateDTO> templateElement = unmarshaller.unmarshal(new StreamSource(in), TemplateDTO.class);
TemplateDTO deserTemplate = templateElement.getValue();
// Modify deserialized template
FlowSnippetDTO deserSnippet = deserTemplate.getSnippet();
Set<ProcessorDTO> deserProcs = deserSnippet.getProcessors();
int c = 0;
for (ProcessorDTO processorDTO : deserProcs) {
if (c % 2 == 0) {
processorDTO.setName("Hello-" + c);
}
c++;
}
// add new Processor
ProcessorDTO procDTO = new ProcessorDTO();
procDTO.setType("ProcessorNew" + ".class");
procDTO.setId(ComponentIdGenerator.generateId().toString());
deserProcs.add(procDTO);
// Serialize modified template
byte[] serTemplate2 = TemplateSerializer.serialize(deserTemplate);
RawText rt1 = new RawText(serTemplate);
RawText rt2 = new RawText(serTemplate2);
EditList diffList = new EditList();
diffList.addAll(new HistogramDiff().diff(RawTextComparator.DEFAULT, rt1, rt2));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (DiffFormatter diff = new DiffFormatter(out);) {
diff.format(diffList, rt1, rt2);
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), StandardCharsets.UTF_8));
List<String> changes = reader.lines().peek(System.out::println)
.filter(line -> line.startsWith("+") || line.startsWith("-")).collect(Collectors.toList());
assertEquals("+ <name>Hello-0</name>", changes.get(0));
assertEquals("+ <name>Hello-2</name>", changes.get(1));
assertEquals("+ <processors>", changes.get(2));
assertEquals("+ <type>ProcessorNew.class</type>", changes.get(4));
assertEquals("+ </processors>", changes.get(5));
}
}
}