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

com.regnosys.rosetta.translate.OurJsonParser Maven / Gradle / Ivy

There is a newer version: 11.25.1
Show newest version
package com.regnosys.rosetta.translate;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.xml.validation.Schema;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.regnosys.rosetta.common.hashing.ReferenceConfig;
import com.regnosys.rosetta.common.translation.Mapping;
import com.regnosys.rosetta.common.translation.Path;
import com.regnosys.rosetta.common.translation.Path.PathElement;
import com.regnosys.rosetta.translate.ParserResult.Context;
import com.rosetta.model.lib.RosettaModelObject;
import com.rosetta.model.lib.RosettaModelObjectBuilder;

public class OurJsonParser extends ParserParent {

	private static final Logger LOGGER = LoggerFactory.getLogger(OurJsonParser.class);

	public OurJsonParser(HandlerFactory factory, SynonymToEnumMapBuilder synonymToEnumMap, ReferenceConfig referenceConfig) {
		super(factory, synonymToEnumMap, referenceConfig);
	}

	@Override
	protected  ParserResult parseTheDocument(Reader reader, Schema schema, Class returnClass) {
		Context context = new Context(synonymToEnumMap);
		
		Map, HandlerSupplier> handlers = factory.getHandlerSuppliers(context.getMappingContext());
		if (!handlers.containsKey(returnClass)) {
			throw new IngestException("Do not have parser for " + returnClass.getSimpleName());
		}
		
		try (Reader json = new CharArrayReader(ParserHelper.toCharsfromReader(reader))) {
			ROMParseHandler handler = (ROMParseHandler) handlers.get(returnClass).apply(new Path(), new Path());
			handler.setRosettaPath(new Path().addElement(new PathElement(returnClass.getSimpleName())));
			
			JsonFactory factory = new JsonFactory();
			JsonParser parser = factory.createParser(json);
			while (!parser.isClosed()) {
				parse(parser, handler, context);
			}
			RosettaModelObjectBuilder rosettaInstance = handler.getUnderlying();

			LOGGER.info("Finished parsing");
			return new ParserResult(rosettaInstance, context);

		} catch (IOException e) {
			throw new IngestException("error reading input json", e);
		}
	}

	private void parse(JsonParser parser, ROMParseHandler rootHandler, Context context) throws IOException {
		Deque handlerStack = new ArrayDeque<>();
		boolean end = false;
		HandlerStackItem currentHandlers = new HandlerStackItem(Collections.singletonList(new HandlerWithPath(rootHandler)), new Path(Collections.emptyList()));
		handlerStack.push(currentHandlers);

		while (!end) {
			JsonToken currentToken = parser.nextToken();
			if (null == currentToken) {
				end = true;
				break;
			}
			List handlers = currentHandlers.handlers();
			Path fullPath = currentHandlers.fullPath();
			switch (currentToken) {
			case FIELD_NAME:
				String fieldName = parser.getCurrentName();
				PathElement element = currentHandlers.addChild(fieldName, Collections.emptyMap());
				Path newPath = fullPath.addElement(element);

				// a new element - our current list of handlers either
				// - can't match the new element,
				// - matches the new element fully to give a new handler
				// - or partially matches and waits to see if the next element matches

				// only the complex handlers are going to be able to accept this new element
				List complexHandlers = handlers.stream()
																.filter(HandlerWithPath::isComplexHandler)
																.collect(Collectors.toList());

				List newHandlers = complexHandlers.stream()
																   .flatMap(hwp -> hwp.matchingHandlers(element, fullPath).stream())
																   .collect(Collectors.toList());

				complexHandlers.stream()
							   .flatMap(hwp -> hwp.matchingMappingProcessors(fullPath, context.getMappingContext()).stream())
							   .forEach(mapEntryProcessor -> context.getMappingProcessors()
																	.put(mapEntryProcessor.getKey(), mapEntryProcessor.getValue()));

				// If there are no handlers then this value cannot be mapped
				if (newHandlers.isEmpty()) {
					LOGGER.debug(newPath + " had no destination");
					context.getMappingContext().getMappings()
						   .add(new Mapping(newPath, null, new Path(Collections.emptyList()), null, "had no destination", false, false, false));
				}

				currentHandlers = new HandlerStackItem(newHandlers, newPath);

				break;
			case VALUE_FALSE:
			case VALUE_TRUE:
			case VALUE_NUMBER_INT:
			case VALUE_NUMBER_FLOAT:
			case VALUE_STRING:
				handlerStack.push(currentHandlers);
				String stringVal = parser.getValueAsString().trim();
				if (stringVal.length() > 0) {
					context.getMappingContext().getMappings().addAll(HandlerWithPath.createMappings(handlers, stringVal, fullPath));
				}
				currentHandlers = stepOutPopFilter(handlerStack);
				break;
			case END_OBJECT:
				currentHandlers = stepOutPopFilter(handlerStack);
				if (currentHandlers == null) {
					//This will be the document end
					return;
				}
				break;
			case START_OBJECT:
				handlerStack.push(currentHandlers);
				break;
			case START_ARRAY:
				handlerStack.push(currentHandlers);
				break;
			case END_ARRAY:
				currentHandlers = stepOutPopFilter(handlerStack);
				break;
			// other primitives should be pushed/popped through the stack, but we are not using them right now				
			//$FALL-THROUGH$
			case VALUE_EMBEDDED_OBJECT:
			case VALUE_NULL:
				break;
			default:
				throw new AssertionError("Unhandled JsonToken parsed value: " + currentToken);
			}
		}
	}

	protected HandlerStackItem stepOutPopFilter(Deque handlerStack) {
		handlerStack.pop();
		if (handlerStack.isEmpty()) {
			return null;
		}
		handlerStack.peek().handlers().stream()
					.filter(HandlerWithPath::isComplexHandler)
					.forEach(HandlerWithPath::removeLastIfExists);
		return handlerStack.peek();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy