All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fixprotocol.orchestra.owl.MessageDiff Maven / Gradle / Ivy

package io.fixprotocol.orchestra.owl;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import io.fixprotocol.orchestra.owl.MessageOntologyManager.CodeObject;
import io.fixprotocol.orchestra.owl.MessageOntologyManager.CodeSetObject;
import io.fixprotocol.orchestra.owl.MessageOntologyManager.DataTypeObject;
import io.fixprotocol.orchestra.owl.MessageOntologyManager.FieldObject;

public class MessageDiff {

	public class DefaultListener implements MessageDiffListener {

		private final PrintStream out;

		public DefaultListener(PrintStream out) {
			this.out = out;
		}

		@Override
		public void accept(Source source, String description) {
			char sourceIndicator;
			switch (source) {
			case FIRST_SOURCE:
				sourceIndicator = '<';
				break;
			case SECOND_SOURCE:
				sourceIndicator = '>';
				break;
			default:
				sourceIndicator = '=';

			}
			out.format("%c %s\n", sourceIndicator, description);
		}

	}

	/**
	 * Compares two message ontologies. By default, report is sent to console.
	 * 
	 * @param args
	 *            file names of two ontologies to compare
	 */
	public static void main(String[] args) throws Exception {
		if (args.length < 2) {
			usage();
		} else {
			MessageDiff tool = new MessageDiff();
			tool.init();
			FileInputStream inputStream1 = new FileInputStream(args[0]);
			FileInputStream inputStream2 = new FileInputStream(args[1]);
			tool.diff(inputStream1, inputStream2);
		}
	}

	/**
	 * Prints application usage
	 */
	public static void usage() {
		System.out.println("Usage: MessageDiffTool  ");
	}

	private MessageDiffListener listener = new DefaultListener(System.out);
	private Model model1;
	private Model model2;
	private final MessageOntologyManager ontologyManager = new MessageOntologyManager();

	public void diff(InputStream inputStream1, InputStream inputStream2) throws Exception {
		model1 = ontologyManager.loadModel(inputStream1);
		model2 = ontologyManager.loadModel(inputStream2);

		Set messageSet1 = ontologyManager.getMessages(model1);
		Set messageSet2 = ontologyManager.getMessages(model2);

		Set intersection = messageSet1.stream().filter(messageSet2::contains)
				.collect(Collectors.toSet());
		Set in1only = messageSet1.stream().filter(m -> !messageSet2.contains(m))
				.collect(Collectors.toSet());
		Set in2only = messageSet2.stream().filter(m -> !messageSet1.contains(m))
				.collect(Collectors.toSet());

		in1only.forEach(m -> listener.accept(MessageDiffListener.Source.FIRST_SOURCE, m.getName()));
		in2only.forEach(m -> listener.accept(MessageDiffListener.Source.SECOND_SOURCE, m.getName()));

		intersection.forEach(m -> diff(m, ontologyManager.getMessage(model2, m.getName())));
	}

	public void diff(FieldObject field1, FieldObject field2) {
		DataTypeObject type1 = field1.getDataType();
		DataTypeObject type2 = field2.getDataType();
		if (!type1.equals(type2)) {
			listener.accept(MessageDiffListener.Source.FIRST_SOURCE,
					String.format("Datatype of %s=%s", field1.getName(), type1.getName()));
			listener.accept(MessageDiffListener.Source.SECOND_SOURCE,
					String.format("Datatype of %s=%s", field2.getName(), type2.getName()));
		} else if (type1 instanceof CodeSetObject) {
			CodeSetObject cs1 = (CodeSetObject) type1;
			CodeSetObject cs2 = (CodeSetObject) type2;
			
			Set codes1 = ontologyManager.getCodes(model1, cs1.getName());
			Set codes2 = ontologyManager.getCodes(model2, cs2.getName());
			
			Set CodeIn1only = codes1.stream().filter(m -> !codes2.contains(m)).collect(Collectors.toSet());
			Set CodeIn2only = codes2.stream().filter(m -> !codes1.contains(m)).collect(Collectors.toSet());

			CodeIn1only.forEach(c -> listener.accept(MessageDiffListener.Source.FIRST_SOURCE,
					String.format("Code %s/%s [%s]", field1.getName(), c.getName(), c.getValue())));
			CodeIn2only.forEach(c -> listener.accept(MessageDiffListener.Source.SECOND_SOURCE,
					String.format("Code %s/%s [%s]", field1.getName(), c.getName(), c.getValue())));


		}
	}

	public void diff(MessageEntity msg1, MessageEntity msg2) {
		Set req1 = new HashSet<>();
		ontologyManager.getRequiredFields(msg1, req1);
		Set req2 = new HashSet<>();
		ontologyManager.getRequiredFields(msg2, req2);

		Set reqIntersection = req1.stream().filter(req2::contains).collect(Collectors.toSet());
		Set ReqIn1only = req1.stream().filter(m -> !req2.contains(m)).collect(Collectors.toSet());
		Set ReqIn2only = req2.stream().filter(m -> !req1.contains(m)).collect(Collectors.toSet());

		ReqIn1only.forEach(m -> listener.accept(MessageDiffListener.Source.FIRST_SOURCE,
				String.format("Required %s/%s", msg1.getName(), m.getName())));
		ReqIn2only.forEach(m -> listener.accept(MessageDiffListener.Source.SECOND_SOURCE,
				String.format("Required %s/%s", msg1.getName(), m.getName())));

		for (FieldObject field : reqIntersection) {
			diff(field, ontologyManager.getField(model2, field.getName()));
		}

		Set opt1 = new HashSet<>();
		ontologyManager.getOptionalFields(msg1, opt1);
		Set opt2 = new HashSet<>();
		ontologyManager.getOptionalFields(msg2, opt2);

		Set optIntersection = opt1.stream().filter(opt2::contains).collect(Collectors.toSet());
		Set OptIn1only = opt1.stream().filter(m -> !opt2.contains(m)).collect(Collectors.toSet());
		Set OptIn2only = opt2.stream().filter(m -> !opt1.contains(m)).collect(Collectors.toSet());

		OptIn1only.forEach(m -> listener.accept(MessageDiffListener.Source.FIRST_SOURCE,
				String.format("Optional %s/%s", msg1.getName(), m.getName())));
		OptIn2only.forEach(m -> listener.accept(MessageDiffListener.Source.SECOND_SOURCE,
				String.format("Optional %s/%s", msg1.getName(), m.getName())));

		for (FieldObject field : optIntersection) {
			diff(field, ontologyManager.getField(model2, field.getName()));
		}
	}

	/**
	 * Initializes resources
	 * 
	 * @throws Exception
	 *             if resources cannot be initialized
	 */
	public void init() throws Exception {
		ontologyManager.init();
	}

	/**
	 * Registers a listener for ontology differences. If one is not registered,
	 * a default listener sends reports to the console.
	 * 
	 * @param listener
	 *            a listener
	 */
	public void setListener(MessageDiffListener listener) {
		this.listener = listener;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy