package com.libreecm.commonAPI.model.objects;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.libreecm.commonAPI.auxiliars.exceptions.NotDefinedPropertyDefinitionException;
import com.libreecm.commonAPI.model.CmisExtensionElement;
import com.libreecm.commonAPI.model.enums.BaseTypeId;
import com.libreecm.commonAPI.model.enums.Cardinality;
import com.libreecm.commonAPI.model.enums.DateTimeResolution;
import com.libreecm.commonAPI.model.enums.PropertyIds;
import com.libreecm.commonAPI.model.enums.PropertyType;
import java.util.GregorianCalendar;
import java.util.HashMap;

import com.libreecm.commonAPI.model.enums.Updatability;
import com.libreecm.commonAPI.model.objects.properties.Properties;
import com.libreecm.commonAPI.model.objects.properties.PropertyBooleanDefinitionImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyBooleanImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyDateTimeDefinitionImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyDateTimeImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyDefinition;
import com.libreecm.commonAPI.model.objects.properties.PropertyIdDefinitionImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyIntegerImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyStringDefinitionImpl;
import com.libreecm.commonAPI.model.objects.properties.PropertyStringImpl;


@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
public abstract class ObjectType extends ExtensionsData {

	private BaseTypeId baseTypeId;
	
	private Boolean controllableAcl;
	private Boolean controllablePolicy;

	private Boolean creatable;

	private String description;

	private String displayName;

	private List<CmisExtensionElement> extensions;

	private Boolean fileable;

	private Boolean fulltextIndexed;

	private String id;

	private Boolean includedInSupertypeQuery;

	private String localName;

	private String localNamespace;

	private String parentTypeId;

	private Map<String, PropertyDefinition<?>> propertyDefinitions=new HashMap<String, PropertyDefinition<?>>();

	private Boolean queryable;

	private String queryName;

	private String repositoryId;

	private TypeMutability typeMutability=new TypeMutability();

	private Properties properties;
	public ObjectType(){
			
		List<Boolean> defaultBooleanTrue=new ArrayList<>();
		defaultBooleanTrue.add(true);
		
		List<Choice<Boolean>> defaultChoices = new ArrayList<>();
		Choice<Boolean> choice = new Choice<Boolean>();
		choice.setDisplayName("Boolean");

		List<Boolean> defaultBooleans=new ArrayList<>();
		defaultBooleans.add(true);
		defaultBooleans.add(false);
		
		choice.setValue(defaultBooleans);
		defaultChoices.add(choice);
		//Init CMIS default propertiesDefinitions, this could be not used
														//PropertyIdDefinitionImpl							( name, id, description,local_namespace, local_name, query_name, 												type, cardinality, updatability, 										queryable, orderable,required,inherited, 	default_value, open_choice,  choices
		//this.getPropertyDefinitions().put("cmis:id",new PropertyIdDefinitionImpl							("Type Id", "cmis:id","Type id","","cmis:id","cmis:id", 														PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,				true,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:localName",new PropertyStringDefinitionImpl					("Local name","cmis:localName","Local name","","cmis:localName","cmis:localName",								PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			true,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:localNamespace",new PropertyStringDefinitionImpl			("Local namespace","cmis:localNamespace","Local namespace","","cmis:localNamespace","cmis:localNamespace",		PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:displayName",new PropertyStringDefinitionImpl				("Display name","cmis:displayName","Display name","","cmis:displayName","cmis:displayName",						PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:repositoryId",new PropertyIdDefinitionImpl				("Repository Id","cmis:repositoryId","Repository Id","","cmis:repositoryId","cmis:repositoryId",					PropertyType.ID,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:queryName",new PropertyStringDefinitionImpl					("Query name","cmis:queryName","Query name","","cmis:queryName","cmis:queryName",								PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:description",new PropertyStringDefinitionImpl				("Description","cmis:description","Description","","cmis:description","cmis:description",						PropertyType.STRING,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:parentTypeId",new PropertyIdDefinitionImpl						("Parent Type Id","cmis:parentTypeId","Parent Type Id","","cmis:parentTypeId","cmis:parentTypeId",			PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,				true,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:baseTypeId",new PropertyIdDefinitionImpl						("Base Type Id","cmis:baseTypeId","Base Type Id","","cmis:baseTypeId","cmis:baseTypeId",					PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,				true,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:creatable",new PropertyBooleanDefinitionImpl				("Creatable","cmis:creatable","Creatable","","cmis:creatable","cmis:creatable",									PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:typeMutability",new PropertyBooleanDefinitionImpl			("typeMutability","cmis:typeMutability","typeMutability","","cmis:typeMutability","cmis:typeMutability",		PropertyType.BOOLEAN,Cardinality.MULTI,Updatability.ONCREATE,			false,false,true,true,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:fileable",new PropertyBooleanDefinitionImpl					("Fileable","cmis:fileable","Fileable","","cmis:fileable","cmis:fileable",										PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
			this.getPropertyDefinitions().put("cmis:queryable",new PropertyBooleanDefinitionImpl				("Queryable","cmis:queryable","Queryable","","cmis:queryable","cmis:queryable",								PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
this.getPropertyDefinitions().put("cmis:fulltextIndexed",new PropertyBooleanDefinitionImpl			("Full text indexed","cmis:fulltextIndexed","Full text indexed","","cmis:fulltextIndexed","cmis:fulltextIndexed",		PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
this.getPropertyDefinitions().put("cmis:includedInSupertypeQuery",new PropertyBooleanDefinitionImpl	("Included in supertype query","cmis:includedInSupertypeQuery","Included in supertype query","","cmis:includedInSupertypeQuery","cmis:includedInSupertypeQuery",PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,false,true,true,false, defaultBooleanTrue,false,defaultChoices));
this.getPropertyDefinitions().put("cmis:controllablePolicy",new PropertyBooleanDefinitionImpl		("Controllable policy","cmis:controllablePolicy","Controllable policy","","cmis:controllablePolicy","cmis:controllablePolicy",PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,	false,true,false,false,					defaultBooleanTrue,false,defaultChoices));
this.getPropertyDefinitions().put("cmis:controllableACL",new PropertyBooleanDefinitionImpl			("Controllable ACL","cmis:controllableACL","Controllable ACL","","cmis:controllableACL","cmis:controllableACL",			PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,false,false,						defaultBooleanTrue,false,defaultChoices));
//PropertyIdDefinitionImpl																			( name, id, description,local_namespace, local_name, query_name, 												type, cardinality, updatability, 										queryable, orderable,required,inherited, 	default_value, open_choice,  choices
		this.getPropertyDefinitions().put("libreecm:accessible",new PropertyBooleanDefinitionImpl			("accessible","libreecm:accessible","accessible","","libreecm:accessible","libreecm:accessible",				PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.ONCREATE,			true,false,false,false,						defaultBooleans,true,defaultChoices));
		this.getPropertyDefinitions().put("libreecm:active",new PropertyBooleanDefinitionImpl				("active","libreecm:active","active","","libreecm:active","libreecm:active",									PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.ONCREATE,			true,false,false,false,						defaultBooleans,true,defaultChoices));
		this.getPropertyDefinitions().put("cmis:allowableActions",new PropertyStringDefinitionImpl			("Allowable actions","cmis:allowableActions","Allowable actions","","cmis:allowableActions","cmis:allowableActions",PropertyType.STRING,Cardinality.MULTI,Updatability.ONCREATE,		false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:baseTypeId",new PropertyIdDefinitionImpl					("Base Type Id","cmis:baseTypeId","Base Type Id","","cmis:baseTypeId","cmis:baseTypeId",								PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,		true,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:controllablePolicy",new PropertyBooleanDefinitionImpl		("Controllable policy","cmis:controllablePolicy","Controllable policy","","cmis:controllablePolicy","cmis:controllablePolicy",PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,false,true,false,false,					defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:controlableACL",new PropertyBooleanDefinitionImpl			("Controllable ACL","cmis:controlableACL","Controllable ACL","","cmis:controlableACL","cmis:controlableACL",	PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,false,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:creatable",new PropertyBooleanDefinitionImpl				("Creatable","cmis:creatable","Creatable","","cmis:creatable","cmis:creatable",									PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:PropertyIds.CREATED_BY",new PropertyStringDefinitionImpl	("CREATED BY",PropertyIds.CREATED_BY,"CREATED BY","",PropertyIds.CREATED_BY,PropertyIds.CREATED_BY,				PropertyType.STRING,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:exactACL",new PropertyBooleanDefinitionImpl					("Exact ACL","cmis:exactACL","Exact ACL","","cmis:exactACL","cmis:exactACL",									PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:folders",new PropertyStringDefinitionImpl				("Parent folders","cmis:folders","Parent folders","","cmis:folders","cmis:folders",									PropertyType.STRING,Cardinality.MULTI,Updatability.READWRITE,			false,false,false,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put(PropertyIds.LAST_MODIFICATION_DATE,new PropertyDateTimeDefinitionImpl	("Last Modification Date",PropertyIds.LAST_MODIFICATION_DATE,"Last Modification Date","",PropertyIds.LAST_MODIFICATION_DATE,PropertyIds.LAST_MODIFICATION_DATE,PropertyType.DATETIME,Cardinality.SINGLE,Updatability.ONCREATE,		true,false,false,false,						new ArrayList<GregorianCalendar>(),false,new ArrayList<Choice<GregorianCalendar>>(), DateTimeResolution.DATE ));
		this.getPropertyDefinitions().put("cmis:createdBy",new PropertyStringDefinitionImpl				("Created By","cmis:createdBy","Created By","","cmis:createdBy","cmis:createdBy",									PropertyType.STRING,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:lastModifiedBy",new PropertyStringDefinitionImpl				("Last Modified By","cmis:lastModifiedBy","Last Modified By","","cmis:lastModifiedBy","cmis:lastModifiedBy",PropertyType.STRING,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put(PropertyIds.CREATION_DATE,new PropertyDateTimeDefinitionImpl		("Creation Date",PropertyIds.CREATION_DATE,"Creation Date","",PropertyIds.CREATION_DATE,PropertyIds.CREATION_DATE,PropertyType.DATETIME,Cardinality.SINGLE,Updatability.ONCREATE,		true,false,false,false,						new ArrayList<GregorianCalendar>(),false,new ArrayList<Choice<GregorianCalendar>>(), DateTimeResolution.DATE ));
		this.getPropertyDefinitions().put("cmis:description",new PropertyStringDefinitionImpl				("Description","cmis:description","Description","","cmis:description","cmis:description",						PropertyType.STRING,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:name",new PropertyStringDefinitionImpl				("Display name","cmis:name","Display name","","cmis:name","cmis:name",													PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:fileable",new PropertyBooleanDefinitionImpl					("Fileable","cmis:fileable","Fileable","","cmis:fileable","cmis:fileable",										PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:fulltextIndexed",new PropertyBooleanDefinitionImpl			("Full text indexed","cmis:fulltextIndexed","Full text indexed","","cmis:fulltextIndexed","cmis:fulltextIndexed",PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put(PropertyIds.OBJECT_TYPE_ID,new PropertyIdDefinitionImpl		("Object Type ID",PropertyIds.OBJECT_TYPE_ID,"Object Type Id","",PropertyIds.OBJECT_TYPE_ID,PropertyIds.OBJECT_TYPE_ID,PropertyType.ID,Cardinality.SINGLE,Updatability.READWRITE,			false,false,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		
		//this.getPropertyDefinitions().put("cmis:acl",new PropertyStringDefinitionImpl						("acl","cmis:acl","acl","","cmis:acl","cmis:acl",																PropertyType.STRING,Cardinality.SINGLE,Updatability.ONCREATE,			false,false,false,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put(PropertyIds.OBJECT_ID,new PropertyIdDefinitionImpl				("Id", PropertyIds.OBJECT_ID,"Id","",PropertyIds.OBJECT_ID,PropertyIds.OBJECT_ID, 								PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,				true,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:isImmutable",new PropertyBooleanDefinitionImpl				("isImmutable", "cmis:isImmutable","Is Immutable","","cmis:isImmutable","cmis:isImmutable", 					PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,				defaultBooleans,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:includedInSupertypeQuery",new PropertyBooleanDefinitionImpl	("Included in supertype query","cmis:includedInSupertypeQuery","Included in supertype query","","cmis:includedInSupertypeQuery","cmis:includedInSupertypeQuery",PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,false,true,true,false, defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:localName",new PropertyStringDefinitionImpl					("Local name","cmis:localName","Local name","","cmis:localName","cmis:localName",								PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			true,false,false,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:localNamespace",new PropertyStringDefinitionImpl			("Local namespace","cmis:localNamespace","Local namespace","","cmis:localNamespace","cmis:localNamespace",		PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:queryName",new PropertyStringDefinitionImpl					("Query name","cmis:queryName","Query name","","cmis:queryName","cmis:queryName",								PropertyType.STRING,Cardinality.SINGLE,Updatability.READONLY,			false,false,false,false,					new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:parentId",new PropertyIdDefinitionImpl						("Parent Id","cmis:parentId","Parent Id","","cmis:parentId","cmis:parentId",										PropertyType.ID,Cardinality.SINGLE,Updatability.ONCREATE,			true,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:path",new PropertyStringDefinitionImpl						("Object absolute path","cmis:path","Object absolute path","","cmis:path","cmis:path",							PropertyType.STRING,Cardinality.SINGLE,Updatability.ONCREATE,				true,true,true,false,						new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
		this.getPropertyDefinitions().put("cmis:typeMutability",new PropertyBooleanDefinitionImpl			("typeMutability","cmis:typeMutability","typeMutability","","cmis:typeMutability","cmis:typeMutability",		PropertyType.BOOLEAN,Cardinality.MULTI,Updatability.ONCREATE,			false,false,true,true,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:queryable",new PropertyBooleanDefinitionImpl				("Queryable","cmis:queryable","Queryable","","cmis:queryable","cmis:queryable",									PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.READONLY,			false,true,true,false,						defaultBooleanTrue,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:typeMutability",new PropertyBooleanDefinitionImpl			("types mutability", "cmis:typeMutability","typeMutability","","cmis:typeMutability","cmis:typeMutability",		PropertyType.BOOLEAN,Cardinality.MULTI,Updatability.READONLY,			false,false,false,false,					defaultBooleans,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:versionable",new PropertyBooleanDefinitionImpl				("Versionable","cmis:versionable","Versionable","","cmis:versionable","cmis:versionable",						PropertyType.BOOLEAN,Cardinality.SINGLE,Updatability.ONCREATE,			true,false,false,false,						defaultBooleans,false,defaultChoices));
		this.getPropertyDefinitions().put("cmis:allowedChildObjectTypeIds",new PropertyIdDefinitionImpl			("Allowed Child Type Ids","cmis:allowedChildObjectTypeIds","Allowed Child Type Ids","","cmis:allowedChildObjectTypeIds","cmis:allowedChildObjectTypeIds",PropertyType.ID,Cardinality.MULTI,Updatability.ONCREATE,true,true,false,false,new ArrayList<String>(),true,new ArrayList<Choice<String>>()));
	}

	public BaseTypeId getBaseTypeId() {
		return this.baseTypeId;
	}

	/**
	 * @return the controllableAcl
	 */
	public Boolean getControllableAcl() {
		return controllableAcl;
	}
	
	/**
	 * @return the controllablePolicy
	 */
	public Boolean getControllablePolicy() {
		return controllablePolicy;
	}

	/**
	 * @return the creatable
	 */
	public Boolean getCreatable() {
		return creatable;
	}

	public String getDescription() {
		return this.description;
	}

	public String getDisplayName() {
		return displayName;
	}

	public List<com.libreecm.commonAPI.model.CmisExtensionElement> getExtensions() {
		if (extensions==null){
			extensions=new ArrayList<>();
		}
		return this.extensions;
	}

	/**
	 * @return the fileable
	 */
	public Boolean getFileable() {
		return fileable;
	}

	/**
	 * @return the fulltextIndexed
	 */
	public Boolean getFulltextIndexed() {
		return fulltextIndexed;
	}

	public String getId() {
		return this.id;
	}

	/**
	 * @return the includedInSupertypeQuery
	 */
	public Boolean getIncludedInSupertypeQuery() {
		return includedInSupertypeQuery;
	}

	public String getLocalName() {
		return localName;
	}

	public String getLocalNamespace() {
		return localNamespace;
	}

	public String getParentTypeId() {
		return this.parentTypeId;
	}

	public Map<String, PropertyDefinition<?>> getPropertyDefinitions() {
		if (propertyDefinitions==null){
			propertyDefinitions=new HashMap<>();
		}
		return propertyDefinitions;
	}

	
	/**
	 * @return the queryable
	 */
	public Boolean getQueryable() {
		return queryable;
	}

	/*/**
	 * @param repositoryId
	 *            the repositoryId to set
	 */
	/*public void setRepositoryId(String repositoryId) {
		this.repositoryId = repositoryId;
	}
	public String getRepositoryId() {
		return repositoryId;
	}*/

	public String getQueryName() {
		return this.queryName;
	}

	/**
	 * @return the repositoryId
	 */
	public String getRepositoryId() {
		return repositoryId;
	}

	public TypeMutability getTypeMutability() {
		return typeMutability;
	}

	public void initialize(ObjectType type) {
		this.setId(type.getId());
		this.extensions=type.getExtensions();
		this.setRepositoryId(type.getRepositoryId());
		this.setLocalName(type.getLocalName());
		this.setLocalNamespace(type.getLocalNamespace());
		this.setDisplayName(type.getDisplayName());
		this.setQueryName(type.getQueryName());
		this.setDescription(type.getDescription());
		this.setBaseTypeId(type.getBaseTypeId());
		this.setParentTypeId(type.getParentTypeId());
		this.setCreatable(type.getCreatable());
		this.setFileable(type.getFileable());
		this.setFulltextIndexed(type.getFulltextIndexed());
		this.setQueryable(type.getQueryable());
		this.setPropertyDefinitions(type.getPropertyDefinitions());
		this.setControllableAcl(type.getControllableAcl());
		this.setControllablePolicy(type.getControllablePolicy());
		this.setIncludedInSupertypeQuery(type.getIncludedInSupertypeQuery());
		this.setTypeMutability(type.getTypeMutability());
	}

	public Boolean isControllableAcl() {
		return controllableAcl;
	}

	public Boolean isControllablePolicy() {
		return controllablePolicy;
	}

	public Boolean isCreatable() {
		return creatable;
	}

	public Boolean isFileable() {
		return fileable;
	}
	public Boolean isFulltextIndexed() {
		return this.fulltextIndexed;
	}

	public Boolean isIncludedInSupertypeQuery() {
		return includedInSupertypeQuery;
	}

	public Boolean isQueryable() {
		return this.queryable;
	}

	/**
	 * @param baseTypeId
	 *            the baseTypeId to set
	 */
	public void setBaseTypeId(BaseTypeId baseTypeId) {
		if (baseTypeId==null) return;
		this.baseTypeId = baseTypeId;
		addStringProperty(PropertyIds.BASE_TYPE_ID, baseTypeId.value());
	}

	/**
	 * @param controllableAcl
	 *            the controllableAcl to set
	 */
	public void setControllableAcl(Boolean controllableAcl) {
		if (controllableAcl==null) return;
		addBooleanProperty("cmis:controllableACL", controllableAcl);
		this.controllableAcl = controllableAcl;
	}

	/**
	 * @param controllablePolicy
	 *            the controllablePolicy to set
	 */
	public void setControllablePolicy(Boolean controllablePolicy) {
		if (controllablePolicy==null) return;
		addBooleanProperty("cmis:controllablePolicy", controllablePolicy);
		this.controllablePolicy = controllablePolicy;
	}

	/**
	 * @param creatable
	 *            the creatable to set
	 */
	public void setCreatable(Boolean creatable) {
		if (creatable==null) return;
		addBooleanProperty("cmis:creatable", creatable);
		this.creatable = creatable;
	}

	/**
	 * @param description
	 *            the description to set
	 */
	public void setDescription(String description) {
		if (description==null) return;
		addStringProperty(PropertyIds.DESCRIPTION, description);
		this.description = description;
	}

	/**
	 * @param displayName
	 *            the displayName to set
	 */
	public void setDisplayName(String displayName) {
		if (displayName==null) return;
		addStringProperty("cmis:displayName", displayName);
		this.displayName = displayName;
	}

	public void setExtensions(List<CmisExtensionElement> extensions) {
		this.extensions = extensions;
	}

	/**
	 * @param fileable
	 *            the fileable to set
	 */
	public void setFileable(Boolean fileable) {
		if (fileable==null) return;
		addBooleanProperty("cmis:fileable", fileable);
		this.fileable = fileable;
	}

	/**
	 * @param fulltextIndexed
	 *            the fulltextIndexed to set
	 */
	public void setFulltextIndexed(Boolean fulltextIndexed) {
		if (fulltextIndexed==null) return;
		addBooleanProperty("cmis:fulltextIndexed", fulltextIndexed);
		this.fulltextIndexed = fulltextIndexed;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(String id) {
		if (id==null) return;
		addStringProperty("cmis:objectTypeId", id);
		this.id = id;
	}

	/**
	 * @param includedInSupertypeQuery
	 *            the includedInSupertypeQuery to set
	 */
	public void setIncludedInSupertypeQuery(Boolean includedInSupertypeQuery) {
		if (includedInSupertypeQuery==null) return;
		addBooleanProperty("cmis:includedInSupertypeQuery", includedInSupertypeQuery);
		this.includedInSupertypeQuery = includedInSupertypeQuery;
	}

	/**
	 * @param localName
	 *            the localName to set
	 */
	public void setLocalName(String localName) {
		if (localName==null) return;
		addStringProperty("cmis:localName", localName);
		this.localName = localName;
	}

	/**
	 * @param localNamespace
	 *            the localNamespace to set
	 */
	public void setLocalNamespace(String localNamespace) {
		if (localNamespace==null) return;
		addStringProperty("cmis:localNamespace", localNamespace);
		this.localNamespace = localNamespace;
	}

	/**
	 * @param parentTypeId
	 *            the parentTypeId to set
	 */
	public void setParentTypeId(String parentTypeId) {
		if (parentTypeId==null) return;
		addStringProperty("cmis:parentTypeId", parentTypeId);
		this.parentTypeId = parentTypeId;
	}

	/**
	 * @param propertyDefinitions
	 *            the propertyDefinitions to set
	 */
	public void setPropertyDefinitions(Map<String, PropertyDefinition<?>> propertyDefinitions) {
		this.propertyDefinitions = propertyDefinitions;
	}

	/**
	 * @param queryable
	 *            the queryable to set
	 */
	public void setQueryable(Boolean queryable) {
		if (queryable==null) return;
		addBooleanProperty("cmis:queryable", queryable);
		this.queryable = queryable;
	}

	/**
	 * @param queryName
	 *            the queryName to set
	 */
	public void setQueryName(String queryName) {
		if (queryName==null) return;
		addStringProperty("cmis:queryName", queryName);
		this.queryName = queryName;
	}

	/**
	 * @param repositoryId the repositoryId to set
	 */
	public void setRepositoryId(String repositoryId) {
		if (repositoryId==null) return;
		addStringProperty("cmis:repositoryId", repositoryId);
		this.repositoryId = repositoryId;
	}
	
	/**
	 * @param typeMutability
	 *            the typeMutability to set
	 */
	public void setTypeMutability(TypeMutability typeMutability) {
		if (typeMutability==null) return;
		addStringProperty("cmis:typeMutability", typeMutability.toString());
		this.typeMutability = typeMutability;
	}

	public String toString(){
		return "ObjectType: "+this.getId()+" "+this.description+" from parent "+this.parentTypeId;
	}
	


	protected void addBooleanProperty(String propertyIds, boolean value) {
		PropertyBooleanImpl property = new PropertyBooleanImpl();
		property.setId(propertyIds);
		property.setDisplayName(property.getId());
		property.setQueryName(property.getId());
		property.setLocalName(property.getId());
		property.setValue(value);

		if (!getPropertyDefinitions().containsKey(propertyIds)){
			throw new NotDefinedPropertyDefinitionException(propertyIds);
		}
		this.getProperties().addProperty(property);
	}

	
	protected void addDateTimeProperty(String propertyIds, GregorianCalendar value) {
		PropertyDateTimeImpl property = new PropertyDateTimeImpl();
		property.setId(propertyIds);
		property.setDisplayName(property.getId());
		property.setQueryName(property.getId());
		property.setLocalName(property.getId());
		property.setValue(value);

		if (!getPropertyDefinitions().containsKey(propertyIds)){
			throw new NotDefinedPropertyDefinitionException(propertyIds);
		}
		this.getProperties().addProperty(property);	
	}

	private Properties getProperties() {
		if (this.properties==null){
			this.properties=new Properties();
		}
		return properties;
	}

	protected void addIntegerProperty(String propertyIds, BigInteger value) {
		PropertyIntegerImpl property = new PropertyIntegerImpl();
		property.setId(propertyIds);
		property.setDisplayName(property.getId());
		property.setQueryName(property.getId());
		property.setLocalName(property.getId());
		property.setValue(value);

		if (!getPropertyDefinitions().containsKey(propertyIds)){
			throw new NotDefinedPropertyDefinitionException(propertyIds);
		}
		this.getProperties().addProperty(property);
	}

	protected void addStringProperty(String propertyIds, String value) {
		PropertyStringImpl property = new PropertyStringImpl();
		property.setDisplayName(property.getId());
		property.setQueryName(property.getId());
		property.setLocalName(property.getId());
		property.setValue(value);
		property.setId(propertyIds);

		if (!getPropertyDefinitions().containsKey(propertyIds)){
			throw new NotDefinedPropertyDefinitionException(propertyIds);
		}
		this.getProperties().addProperty(property);
	}

	protected void addStringProperty(String propertyIds, List<String> value) {
		PropertyStringImpl property = new PropertyStringImpl();
		property.setDisplayName(property.getId());
		property.setQueryName(property.getId());
		property.setLocalName(property.getId());
		property.setValues(value);
		property.setId(propertyIds);

		if (!getPropertyDefinitions().containsKey(propertyIds)){
			throw new NotDefinedPropertyDefinitionException(propertyIds);
		}
		this.getProperties().addProperty(property);
	}

}
