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

jasima.core.util.JasimaBeanConverter Maven / Gradle / Ivy

/*******************************************************************************
 * This file is part of jasima, v1.3, the Java simulator for manufacturing and 
 * logistics.
 *  
 * Copyright (c) 2015 		jasima solutions UG
 * Copyright (c) 2010-2015 Torsten Hildebrandt and jasima contributors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 *******************************************************************************/
package jasima.core.util;

import java.util.HashSet;
import java.util.Set;

import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
import com.thoughtworks.xstream.converters.javabean.JavaBeanProvider;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;

/**
 * Converts beans serialized using the jasima GUI, which uses a slightly
 * modified XML format. This converter can read input generated by plain XStream
 * as well as jasima_gui's PermissiveBeanConverter.
 * 
 * @author Robin Kreis
 */
public class JasimaBeanConverter extends JavaBeanConverter {
	protected static final String NULL_ATTRIBUTE_NAME = "is-null";
	protected static final String NULL_ATTRIBUTE_VALUE = "yes";
	protected boolean saveExtendedInfo;

	public JasimaBeanConverter(Mapper mapper, boolean saveExtendedInfo) {
		super(mapper);
		this.saveExtendedInfo = saveExtendedInfo;
	}

	public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
		if (!saveExtendedInfo) {
			// save plain XStream
			super.marshal(source, writer, context);
			return;
		}

		final String classAttributeName = mapper.aliasForSystemAttribute("class");
		beanProvider.visitSerializableProperties(source, new JavaBeanProvider.Visitor() {
			@SuppressWarnings("rawtypes")
			public boolean shouldVisit(String name, Class definedIn) {
				return mapper.shouldSerializeMember(definedIn, name);
			}

			@SuppressWarnings("rawtypes")
			public void visit(String propertyName, Class fieldType, Class definedIn, Object newObj) {
				if (newObj == null) {
					writer.startNode(propertyName);
					writer.addAttribute(classAttributeName, "null");
					writer.endNode();
				} else {
					Class actualType = newObj.getClass();
					String serializedMember = mapper.serializedMember(source.getClass(), propertyName);
					ExtendedHierarchicalStreamWriterHelper.startNode(writer, serializedMember, actualType);
					writer.addAttribute(classAttributeName, mapper.serializedClass(actualType));
					context.convertAnother(newObj);

					writer.endNode();
				}
			}
		});
	}

	public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
		final Object result = instantiate(context);

		final Set seenProperties = new HashSet<>();
		Class resultType = result.getClass();
		while (reader.hasMoreChildren()) {
			reader.moveDown();

			String propertyName = mapper.realMember(resultType, reader.getNodeName());

			if (mapper.shouldSerializeMember(resultType, propertyName)) {
				if (!seenProperties.add(propertyName))
					throw new DuplicatePropertyException(propertyName);

				Object value;

				if (NULL_ATTRIBUTE_VALUE.equals(reader.getAttribute(NULL_ATTRIBUTE_NAME))) {
					value = null;
				} else {
					value = context.convertAnother(result, determineType(reader, resultType, propertyName));
				}

				beanProvider.writeProperty(result, propertyName, value);
			}
			reader.moveUp();
		}

		return result;
	}

	protected Object instantiate(UnmarshallingContext context) {
		Object result = context.currentObject();
		if (result == null) {
			result = beanProvider.newInstance(context.getRequiredType());
		}
		return result;
	}

	protected Class determineType(HierarchicalStreamReader reader, Object result, String fieldName) {
		final String classAttributeName = mapper.aliasForSystemAttribute("class");
		String classAttribute = classAttributeName == null ? null : reader.getAttribute(classAttributeName);
		if (classAttribute != null) {
			return mapper.realClass(classAttribute);
		} else {
			// only happens with the plain XStream format
			return mapper.defaultImplementationOf(beanProvider.getPropertyType(result, fieldName));
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy