int main()
{
    // Need to force Windows to load Actuators library if there are no
    // explicit uses.
    LoadOpenSimLibrary("osimActuators");

    try {
        Model testModel;
        srand((unsigned)time(0));

        //Test serialization for all ModelComponents
        ArrayPtrs<OpenSim::ModelComponent> availableComponentTypes;
        Object::getRegisteredObjectsOfGivenType<OpenSim::ModelComponent>(availableComponentTypes);
        for (int i=0; i< availableComponentTypes.getSize(); i++){
            Object* clone = availableComponentTypes[i]->clone();
            Object* randClone = randomize(clone);
            try {
                testModel.addModelComponent(ModelComponent::safeDownCast(randClone));
            } //Ignore the validity of the property values
            // TODO this should specifically handle "InvalidPropertyValue" exceptions
            // once we have that in place.
            catch (const std::exception&) {
                // const string& errMsg = err.getMessage();
                //std::cout << errMsg << std::endl;
            }
        }

        int nc = testModel.getMiscModelComponentSet().getSize();
        cout << nc << " model components were serialized in testModel." << endl;

        //Serialize all the components
        testModel.print("allComponents.osim");

        // The finalize flag is for testing purposes ONLY. This way we
        // can ignore invalid properties and focus the test on serialization.
        Model deserializedModel("allComponents.osim", false);

        try {
            deserializedModel.finalizeFromProperties();
        }
        //Ignore the validity of the property values
        // TODO this should specifically handle "InvalidPropertyValue" exceptions
        // once we have that in place.
        catch (const std::exception&) {
            // const string& errMsg = err.getMessage();
            //std::cout << errMsg << std::endl;
        }

        nc = deserializedModel.getMiscModelComponentSet().getSize();
        cout << nc << " model components were deserialized from file." << endl;

        ASSERT(testModel == deserializedModel,  
            "deserializedModel FAILED to match original model.");

        //Might as well test cloning and assignment
        Model* cloneModel = testModel.clone();

        ASSERT(testModel == *cloneModel,
            "cloneModel FAILED to match original model.");

        Model assignedModel = *cloneModel;

        delete cloneModel;

        ASSERT(testModel == assignedModel,
            "assignedModel FAILED to match original model.");

    }
    catch (const Exception& e) {
        e.print(cerr);
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}
int main()
{
	try {
		Model testModel;
        srand((unsigned)time(0));
        // for Body, Joint, Constraint, Force, Marker, ContactGeometry, Controller and Probe
        ArrayPtrs<OpenSim::Body> availableBodyTypes;
        Object::getRegisteredObjectsOfGivenType<OpenSim::Body>(availableBodyTypes);
        for (int i=0; i< availableBodyTypes.getSize(); i++){
            Object* clone = availableBodyTypes[i]->clone();
            Object* randClone = randomize(clone);
            testModel.addBody(Body::safeDownCast(randClone));
			const Body& inModel = testModel.getBodySet().get(randClone->getName());
			ASSERT(inModel == *randClone);
			randClone->print("bodyTestPrint.xml");
        }

		ArrayPtrs<OpenSim::Joint> availablJointTypes;
		Object::getRegisteredObjectsOfGivenType<OpenSim::Joint>(availablJointTypes);
		for (int i = 0; i< availablJointTypes.getSize(); i++){
			Object* clone = availablJointTypes[i]->clone();
			Object* randClone = randomize(clone);
			testModel.addJoint(Joint::safeDownCast(randClone));
		}

		ArrayPtrs<OpenSim::Constraint> availableConstraintTypes;
		Object::getRegisteredObjectsOfGivenType<OpenSim::Constraint>(availableConstraintTypes);
		for (int i = 0; i< availableConstraintTypes.getSize(); i++){
			Object* clone = availableConstraintTypes[i]->clone();
			Object* randClone = randomize(clone);
			testModel.addConstraint(Constraint::safeDownCast(randClone));
		}

        ArrayPtrs<OpenSim::Force> availableForceTypes;
        Object::getRegisteredObjectsOfGivenType<OpenSim::Force>(availableForceTypes);
        for (int i=0; i< availableForceTypes.getSize(); i++){
            Object* clone = availableForceTypes[i]->clone();
            Object* randClone = randomize(clone);
            testModel.addForce(Force::safeDownCast(randClone));
        }

        ArrayPtrs<OpenSim::Controller> availableControllerTypes;
        Object::getRegisteredObjectsOfGivenType<OpenSim::Controller>(availableControllerTypes);
        for (int i=0; i< availableControllerTypes.getSize(); i++){
            Object* clone = availableControllerTypes[i]->clone();
            Object* randClone = randomize(clone);
            testModel.addController(Controller::safeDownCast(randClone));
        }

        ArrayPtrs<OpenSim::Probe> availableProbeTypes;
        Object::getRegisteredObjectsOfGivenType<OpenSim::Probe>(availableProbeTypes);
        for (int i=0; i< availableProbeTypes.getSize(); i++){
            Object* clone = availableProbeTypes[i]->clone();
            Object* randClone = randomize(clone);
            testModel.addProbe(Probe::safeDownCast(randClone));
        }

        testModel.print("allComponents.osim");

        Model deserializedModel("allComponents.osim", false);
		ASSERT(testModel == deserializedModel,  
			"deserializedModel FAILED to match original model.");       
	}
	catch (const Exception& e) {
        e.print(cerr);
        return 1;
    }
    cout << "Done" << endl;
	return 0;
}