// This file is part of the Coral project.
// Please read the copyright notice in the LICENSE file.

#include <coral/core/DCE_UUID.h>
#include <coral/lib/helper_uuid.h>

#include <coral/core/Element.h>
#include <coral/coral.h>

#include <coral/lang/SMD01/SMD01.h>

NAMESPACE_BEGIN(coral);
NAMESPACE_BEGIN(SMD01);

static bool has_loaded = false;

coral::Language* language;


coral::ElementDefinition* Named;
coral::ElementDefinition* Property;
coral::ElementDefinition* AbstractElementDefinition;
coral::ElementDefinition* Operation;
coral::ElementDefinition* Package;
coral::ElementDefinition* DatatypeDefinition;
coral::ElementDefinition* EnumerationDefinition;
coral::ElementDefinition* ElementDefinition;
coral::ElementDefinition* Language;
coral::EnumerationDefinition* PropertyType;

/*
 * All our enumerations
 */

static const char* cc0[] = { "association", "composition", NULL };
static const coral::util::mmcreator::Enumeration enum0 = { &PropertyType, "PropertyType", cc0 };
/*
 * All our enumerations
 */
static const coral::util::mmcreator::Enumeration* enums[] = {
	&enum0,
	NULL
};

static const coral::util::mmcreator::Datatype dtypes[] = {
	{ NULL, NULL }
};

/*
 * All our language elements
 */
static const coral::util::mmcreator::Element elems[] = {
	{ &Named, "Named" },
	{ &Property, "Property" },
	{ &AbstractElementDefinition, "AbstractElementDefinition" },
	{ &Operation, "Operation" },
	{ &Package, "Package" },
	{ &DatatypeDefinition, "DatatypeDefinition" },
	{ &EnumerationDefinition, "EnumerationDefinition" },
	{ &ElementDefinition, "ElementDefinition" },
	{ &Language, "Language" },
	{NULL, NULL}
};

/*
 * All our subclass <-> superclass relations
 */
static const coral::util::mmcreator::SubAndSuper bases[] = {
	{ "Named", "CORE::AnyAbstractElement" }, 
	{ "Property", "CORE::AnyAbstractElement" }, 
	{ "AbstractElementDefinition", "Named" }, 
	{ "AbstractElementDefinition", "CORE::AnyAbstractElement" }, 
	{ "Operation", "Named" },
	{ "Package", "AbstractElementDefinition" }, 
	{ "DatatypeDefinition", "AbstractElementDefinition" }, 
	{ "EnumerationDefinition", "DatatypeDefinition" }, 
	{ "ElementDefinition", "AbstractElementDefinition" }, 
	{ "Language", "Package" }, 
	{NULL, NULL}
};

/*
 * All our slots
 */
static const coral::util::mmcreator::Feature slots[] = {
	{ "EnumerationDefinition", "values", "CORE::String", "", 0, -1, coral::kind_t::KIND_COMPOSITION | coral::kind_t::KIND_ORDERED },
	{ "AbstractElementDefinition", "package", "Package", "elements", 0, 1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION },
	{ "AbstractElementDefinition", "operations", "Operation", "correspondingElement", 0, -1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_COMPOSITION },
	{ "AbstractElementDefinition", "superclasses", "AbstractElementDefinition", "subclasses", 0, -1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION | coral::kind_t::KIND_ORDERED },
	{ "AbstractElementDefinition", "subclasses", "AbstractElementDefinition", "superclasses", 0, -1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION | coral::kind_t::KIND_NOSERIALIZE },
	{ "AbstractElementDefinition", "isAbstract", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION },
	{ "Operation", "correspondingElement", "AbstractElementDefinition", "operations", 1, 1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION },
	{ "Operation", "isWFR", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION },
	{ "Operation", "language", "CORE::String", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION },
	{ "Operation", "code", "CORE::String", NULL, 0, -1, coral::kind_t::KIND_COMPOSITION | coral::kind_t::KIND_ORDERED},
	{ "Language", "version", "CORE::Integer", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Language", "revision", "CORE::Integer", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Package", "URInamespace", "CORE::String", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Language", "root_ed", "ElementDefinition", NULL, 1, 1, coral::kind_t::KIND_ASSOCIATION },
	{ "Package", "elements", "AbstractElementDefinition", "package", 0, -1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_COMPOSITION },
	// This could have an opposite unserializable end...
	{ "Package", "imported_elements", "AbstractElementDefinition", "", 0, -1, coral::kind_t::KIND_ASSOCIATION },
	{ "Named", "name", "CORE::String", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "multiplicity_lower", "CORE::Integer", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "multiplicity_upper", "CORE::Integer", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "isUnserializable", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "isOrdered", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "name", "CORE::String", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "isBag", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "defaultValue", "CORE::String", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "type", "PropertyType", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION }, 
	{ "Property", "isAnonymous", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION | coral::kind_t::KIND_NOSERIALIZE}, 
	{ "Property", "owner", "ElementDefinition", "properties", 1, 1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION },
	{ "Property", "opposite", "Property", "opposite", 0, 1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_ASSOCIATION },
	{ "Property", "element_kind", "AbstractElementDefinition", NULL, 1, 1, coral::kind_t::KIND_ASSOCIATION },
	{ "ElementDefinition", "properties", "Property", "owner", 0, -1, coral::kind_t::KIND_BIDI | coral::kind_t::KIND_COMPOSITION | coral::kind_t::KIND_ORDERED },
	{ "ElementDefinition", "MOFDatatype", "CORE::Boolean", NULL, 1, 1, coral::kind_t::KIND_COMPOSITION },
	{NULL, NULL, NULL, NULL, 0, 0, 0}
};

/*
 * The initialization routines
 * - Create all language elements 
 * - create language slots and insert them into respective
 *   ElementDefinitions
 */
bool init_language() throw () {

	if (has_loaded) return true;

	try {
		if (!language) language = new coral::Language(std::string("SMD"), 0, 1);
		coral::util::mmcreator::create_elems(language, enums, dtypes, elems, bases, slots);

		language->setRoot(SMD01::Language);

		language->setXMLNS("http://www.abo.fi/SMD/0.1");


	} catch (...) {

		return false;
	}

	has_loaded = true;
	return true;
}

NAMESPACE_END();
NAMESPACE_END();
