public interface CDMFactory {
	
	public static CDMFactory INSTANCE = new NativeCDMFactory();
	
	public CanonicalDataType createDataType(String name);
	
	public CDMPrimitiveProperty createPrimitiveProperty(String name, PrimitiveDataType type);
	
	public CDMPrimitiveProperty createPrimitiveProperty(String name, PrimitiveDataType type, Cardinality cardinality);
	
	public CDMReferenceProperty createReferenceProperty(String name, CanonicalDataType targetType);
	
	public CDMReferenceProperty createReferenceProperty(String name, CanonicalDataType targetType, Cardinality cardinality);
} public interface CDMReferenceProperty extends CDMProperty, ReadableCDMReferenceProperty {
	
	public void setTargetDataType(CanonicalDataType type);
	
	public CDMReferenceProperty withTargetDataType(CanonicalDataType type);
	
	public void setInverseProperty(CDMReferenceProperty inverse);
	
	public CDMReferenceProperty withInverseProperty(CDMReferenceProperty inverse);

} public interface CanonicalDataType {
	
	public String getName();
	
	public void setName(String name);
	
	public Iterable<CDMProperty> getProperties();
	
	public CDMProperty getProperty(String propName);
	
	public boolean hasProperty(CDMProperty property);
	
	public CanonicalDataType withPrimitive(String name, PrimitiveDataType type);
	
	public CanonicalDataType withPrimitive(String name, PrimitiveDataType type, Cardinality cardinality);

	public CanonicalDataType withReference(String name, CanonicalDataType type);

	public CanonicalDataType withReference(String name, CanonicalDataType type, Cardinality cardinality);

} public enum Cardinality {
	ONE, ZERO_OR_ONE, ONE_OR_MORE, ZERO_OR_MORE

} public interface ObjectResource {
	
	public Object getCanonicalObject();
	
	public void setCanonicalObject(Object obj);

	public URI getURI();
	
	public void setURI(URI uri);
	
	public ObjectResourceDefinition getResourceDefinition();
	
	public void setResourceDefinition(ObjectResourceDefinition definition);
	
} public interface ObjectResourceDefinition extends ResourceDefinition {

	// write-once properties, should be passed in ctor
	public String getURITemplate();

	/**
	 * @return the ResourceDataModel bound to this class of resources.
	 */
	public ResourceDataModel getResourceDataModel();

	// read-writable properties

	public String getName();

	public void setName(String name);

	public ObjectResourceDefinition withName(String name);

	public void bindTemplateParameter(String parameter, CDMProperty property);
	
	public ObjectResourceDefinition withTemplateParameter(String parameter, CDMProperty property);

	/**
	 * Factory method to create or retrieve an individual Resource bound to the
	 * canonicalObject. The canonicalObject must confirm to the
	 * ResourceDataModel. This method is responsible for populating the resource
	 * URI and any other required properties of the Resource.
	 * 
	 * @param canonicalObject
	 * @return
	 */
	public ObjectResource getResource(Object canonicalObject, CanonicalObjectReader reader);

} public interface ObjectResourceDefinitionRegistry {

	// TODO: Check use of Singleton pattern, consider DI/Resource Locator.
	public static ObjectResourceDefinitionRegistry INSTANCE = new ObjectResourceDefinitionRegistryImpl();

	/**
	 * Register a ResourceDataModel. Registering an ObjectResourceDefinition
	 * with a duplicate name, ResourceDataModel or CanonicalDataType will remove
	 * the previous entry from the registry, and add this one in its place.
	 * 
	 * @param rdm
	 * @param definition
	 */
	public void registerDefinition(ObjectResourceDefinition definition);

	/**
	 * Retrieve an ObjectResourceDefinition by its name.
	 * 
	 * @param name
	 * @return
	 */
	public ObjectResourceDefinition getResourceDefinition(String name);

	/**
	 * Retrieve an ObjectResourceDefinition by its associated ResourceDataModel.
	 * 
	 * @param name
	 * @return
	 */
	public ObjectResourceDefinition getResourceDefinition(ResourceDataModel rdm);

	/**
	 * Retrieve an ObjectResourceDefinition by its associated CanonicalDataType.
	 * 
	 * @param name
	 * @return
	 */
	public ObjectResourceDefinition getResourceDefinition(CanonicalDataType canonicalDataType);

} public interface RDMFactory {

	public static RDMFactory INSTANCE = new NativeRDMFactory();

	public RDMPrimitiveProperty createRDMPrimitiveProperty(
			CDMPrimitiveProperty cdmProperty);

	public ReferenceLink createReferenceLink(CDMReferenceProperty cdmProperty);

	public ReferenceEmbed createReferenceEmbed(CDMReferenceProperty cdmProperty);

	public ResourceDataModel createResourceDataModel(CanonicalDataType cdt);
	
	public ObjectResourceDefinition createObjectResourceDefinition(String uriTemplate, ResourceDataModel rdm);

	public ObjectResource createObjectResource(Object canonicalObject, URI uri,
			ObjectResourceDefinition ord);

} public interface ResourceDataModel {

	public CanonicalDataType getCanonicalDataType();

	public void setCanonicalDataType(CanonicalDataType type);

	public ResourceDataModel withCanonicalDataType(CanonicalDataType type);

	public Iterable<RDMProperty> getIncludedProperties();

	// Add a list of CDM properties from the CanonicalDataType
	public ResourceDataModel includingProperties(CDMProperty... properties);

	public ResourceDataModel includingProperties(String... properties);

	// Add Primitive Property from CDM Property
	public RDMPrimitiveProperty addPrimitiveProperty(
			CDMPrimitiveProperty property);

	// Add Primitive Property directly, chainable, builder style
	public ResourceDataModel withPrimitiveProperty(
			RDMPrimitiveProperty property);

	// Add ReferenceLink from CDMReferenceProperty
	public ReferenceLink addReferenceLink(CDMReferenceProperty property);

	// Add ReferenceLink Directly, chainable, builder style
	public ResourceDataModel withReferenceLink(ReferenceLink refLink);

	// Add ReferenceEmbed from CDMReferenceProperty
	public ReferenceEmbed addReferenceEmbed(CDMReferenceProperty property);

	// Add ReferenceEmbed Directly, chainable, builder style
	public ResourceDataModel withReferenceEmbed(ReferenceEmbed refEmbed);
} public interface CanonicalObjectReader {
	
	public Object getPropertyValue(Object obj, CDMProperty prop);
	
	public Object getPropertyValue(Object obj, RDMProperty prop);
	
	public Object getPropertyValue(Object obj, String propName);
} public class CanonicalObjectBeanReader implements CanonicalObjectReader {

	@Override
	public Object getPropertyValue(Object obj, RDMProperty prop) {
		return getPropertyValue(obj, prop.getName());
	}

	@Override
	public Object getPropertyValue(Object obj, CDMProperty prop) {
		return getPropertyValue(obj, prop.getName());
	}

	@Override
	public Object getPropertyValue(Object obj, String propName) {
		try {
			return PropertyUtils.getProperty(obj, propName);
		} catch (Exception e) {
			throw new RuntimeException("Could not retrieve value for property " + propName, e);
		}
	}
} @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Address")
public class Address {

    @XmlAttribute(name = "street1", required = true)
    protected String street1;
    @XmlAttribute(name = "street2", required = true)
    protected String street2;
    @XmlAttribute(name = "city", required = true)
    protected String city;
    @XmlAttribute(name = "stateOrProvince", required = true)
    protected String stateOrProvince;
    @XmlAttribute(name = "postalCode", required = true)
    protected String postalCode;
    @XmlAttribute(name = "country", required = true)
    protected String country;

    /**
     * Gets the value of the street1 property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStreet1() {
        return street1;
    }

    /**
     * Sets the value of the street1 property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStreet1(String value) {
        this.street1 = value;
    }

    /**
     * Gets the value of the street2 property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStreet2() {
        return street2;
    }

    /**
     * Sets the value of the street2 property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStreet2(String value) {
        this.street2 = value;
    }

    /**
     * Gets the value of the city property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCity() {
        return city;
    }

    /**
     * Sets the value of the city property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCity(String value) {
        this.city = value;
    }

    /**
     * Gets the value of the stateOrProvince property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStateOrProvince() {
        return stateOrProvince;
    }

    /**
     * Sets the value of the stateOrProvince property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStateOrProvince(String value) {
        this.stateOrProvince = value;
    }

    /**
     * Gets the value of the postalCode property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getPostalCode() {
        return postalCode;
    }

    /**
     * Sets the value of the postalCode property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setPostalCode(String value) {
        this.postalCode = value;
    }

    /**
     * Gets the value of the country property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCountry() {
        return country;
    }

    /**
     * Sets the value of the country property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCountry(String value) {
        this.country = value;
    }

} public class Company {
	private String companyID;
	private String EIN;
	private String companyName;
	private String form;
	private Boolean active;
	private Set<Person> employees=new HashSet<Person>();

	public String getCompanyID() {
		return companyID;
	}

	public void setCompanyID(String companyID) {
		this.companyID = companyID;
	}

	public String getEIN() {
		return EIN;
	}

	public void setEIN(String eIN) {
		EIN = eIN;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public String getForm() {
		return form;
	}

	public void setForm(String form) {
		this.form = form;
	}

	public Boolean getActive() {
		return active;
	}

	public void setActive(Boolean active) {
		this.active = active;
	}
	
	public Company withEmployee(Person employee) {
		if(!employees.contains(employee)) {
			employees.add(employee);
		}
		return this;
	}
	
	public Iterable<Person> getEmployees() {
		return employees;
	}
} public class Person {

    protected String taxpayerID;
	protected String lastName;
    protected String firstName;
	protected List<Address> addresses = new ArrayList<Address>();
	protected Company employer;
	protected List<String> otherNames = new ArrayList<String>();

	/**s
     * Gets the value of the addressList property.
     * 
     * @return
     *     possible object is
     *     {@link Person.AddressList }
     *     
     */
    public List<Address> getAddresses() {
        return addresses;
    }

    /**
     * Gets the value of the lastNameList property.
     * 
     * @return
     *     possible object is
     *     {@link Person.LastNameList }
     *     
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Sets the value of the lastNameList property.
     * 
     * @param value
     *     allowed object is
     *     {@link Person.LastNameList }
     *     
     */
    public void setLastName(String value) {
        this.lastName= value;
    }

    /**
     * Gets the value of the taxpayerID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getTaxpayerID() {
        return taxpayerID;
    }

    /**
     * Sets the value of the taxpayerID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setTaxpayerID(String value) {
        this.taxpayerID = value;
    }

    /**
     * Gets the value of the firstName property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Sets the value of the firstName property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setFirstName(String value) {
        this.firstName = value;
    }
    
    public Company getEmployer() {
		return employer;
	}

	public void setEmployer(Company employer) {
		this.employer = employer;
	}
	
	public List<String> getOtherNames() {
		return otherNames;
	}

} @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "TaxFiling")
public class TaxFiling {

    protected String filingID;
    protected Person taxpayer;
    protected String jurisdiction;
    protected XMLGregorianCalendar year;
    protected int period;
    protected String currency;
    protected BigDecimal grossIncome;
    protected BigDecimal taxLiability;

    /**
     * Gets the value of the filingID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getFilingID() {
        return filingID;
    }

    /**
     * Sets the value of the filingID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setFilingID(String value) {
        this.filingID = value;
    }

    public Person getTaxpayer() {
		return taxpayer;
	}

	public void setTaxpayer(Person taxpayer) {
		this.taxpayer = taxpayer;
	}

    /**
     * Gets the value of the jurisdiction property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getJurisdiction() {
        return jurisdiction;
    }

    /**
     * Sets the value of the jurisdiction property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setJurisdiction(String value) {
        this.jurisdiction = value;
    }

    /**
     * Gets the value of the year property.
     * 
     * @return
     *     possible object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public XMLGregorianCalendar getYear() {
        return year;
    }

    /**
     * Sets the value of the year property.
     * 
     * @param value
     *     allowed object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public void setYear(XMLGregorianCalendar value) {
        this.year = value;
    }

    /**
     * Gets the value of the period property.
     * 
     */
    public int getPeriod() {
        return period;
    }

    /**
     * Sets the value of the period property.
     * 
     */
    public void setPeriod(int value) {
        this.period = value;
    }

    /**
     * Gets the value of the currency property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCurrency() {
        return currency;
    }

    /**
     * Sets the value of the currency property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCurrency(String value) {
        this.currency = value;
    }

    /**
     * Gets the value of the grossIncome property.
     * 
     * @return
     *     possible object is
     *     {@link BigDecimal }
     *     
     */
    public BigDecimal getGrossIncome() {
        return grossIncome;
    }

    /**
     * Sets the value of the grossIncome property.
     * 
     * @param value
     *     allowed object is
     *     {@link BigDecimal }
     *     
     */
    public void setGrossIncome(BigDecimal value) {
        this.grossIncome = value;
    }

    /**
     * Gets the value of the taxLiability property.
     * 
     * @return
     *     possible object is
     *     {@link BigDecimal }
     *     
     */
    public BigDecimal getTaxLiability() {
        return taxLiability;
    }

    /**
     * Sets the value of the taxLiability property.
     * 
     * @param value
     *     allowed object is
     *     {@link BigDecimal }
     *     
     */
    public void setTaxLiability(BigDecimal value) {
        this.taxLiability = value;
    }

}
import static com.modelsolv.kaboom.model.canonical.PrimitiveDataType.BOOLEAN;
import static com.modelsolv.kaboom.model.canonical.PrimitiveDataType.DATE;
import static com.modelsolv.kaboom.model.canonical.PrimitiveDataType.DECIMAL;
import static com.modelsolv.kaboom.model.canonical.PrimitiveDataType.INTEGER;
import static com.modelsolv.kaboom.model.canonical.PrimitiveDataType.STRING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.math.BigDecimal;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.modelsolv.kaboom.model.canonical.CDMFactory;
import com.modelsolv.kaboom.model.canonical.CDMReferenceProperty;
import com.modelsolv.kaboom.model.canonical.CanonicalDataType;
import com.modelsolv.kaboom.model.canonical.Cardinality;
import com.modelsolv.kaboom.model.resource.ObjectResource;
import com.modelsolv.kaboom.model.resource.ObjectResourceDefinition;
import com.modelsolv.kaboom.model.resource.ObjectResourceDefinitionRegistry;
import com.modelsolv.kaboom.model.resource.RDMFactory;
import com.modelsolv.kaboom.model.resource.ResourceDataModel;
import com.modelsolv.kaboom.object.CanonicalObjectReader;
import com.modelsolv.kaboom.object.beanImpl.CanonicalObjectBeanReader;
import com.modelsolv.kaboom.testModels.Address;
import com.modelsolv.kaboom.testModels.Company;
import com.modelsolv.kaboom.testModels.Person;
import com.modelsolv.kaboom.testModels.TaxFiling;
/*******************************************************************************
 * Copyright (c) 2014 ModelSolv, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     ModelSolv, Inc. - initial API and implementation.
 *******************************************************************************/
package com.modelsolv.kaboom.serializer;






public class SerializerTest {
    private CDMFactory cdmFactory;
    private RDMFactory rdmFactory;