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

de.taimos.dvalin.interconnect.model.maven.MetaModelHelper Maven / Gradle / Ivy

There is a newer version: 1.7
Show newest version
package de.taimos.dvalin.interconnect.model.maven;

/*
 * #%L
 * Dvalin interconnect maven plugin for source generation
 * %%
 * Copyright (C) 2016 Taimos GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.joda.time.DateTime;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;

import de.taimos.dvalin.interconnect.model.ToBeRemoved;
import de.taimos.dvalin.interconnect.model.ivo.AbstractIVO;
import de.taimos.dvalin.interconnect.model.ivo.Direction;
import de.taimos.dvalin.interconnect.model.ivo.IPageable;
import de.taimos.dvalin.interconnect.model.ivo.IPageableBuilder;
import de.taimos.dvalin.interconnect.model.ivo.IVO;
import de.taimos.dvalin.interconnect.model.ivo.IVOBuilder;
import de.taimos.dvalin.interconnect.model.ivo.util.IIVOAuditing;
import de.taimos.dvalin.interconnect.model.metamodel.BigDecimalMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.BooleanMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.CollectionMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.CollectionType;
import de.taimos.dvalin.interconnect.model.metamodel.ContentDef;
import de.taimos.dvalin.interconnect.model.metamodel.DateMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.EnumMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.IFilterableMember;
import de.taimos.dvalin.interconnect.model.metamodel.ILabelMember;
import de.taimos.dvalin.interconnect.model.metamodel.IVODef;
import de.taimos.dvalin.interconnect.model.metamodel.IVOMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.ImplementsDef;
import de.taimos.dvalin.interconnect.model.metamodel.IntegerMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.InterconnectObjectMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.LongMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.MapMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.MapType;
import de.taimos.dvalin.interconnect.model.metamodel.MemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.StringMemberDef;
import de.taimos.dvalin.interconnect.model.metamodel.UUIDMemberDef;

/**
 * Utility functions for helping velocity
 */
public class MetaModelHelper {

	/**
	 * the supported primitive types
	 */
	public static final Set SUPPORTED_PRIMITIVE_TYPES = Sets.newHashSet(BigDecimal.class.getSimpleName(), String.class.getSimpleName(), DateTime.class.getSimpleName(), Boolean.class.getSimpleName(), Long.class.getSimpleName());

	private IVODef ivod;
	private List allMemberDefs = new ArrayList<>();
	private List noCollectionMemberDefs = new ArrayList<>();
	private List implementsDef = new ArrayList<>();
	private List enumMemberDefs = new ArrayList<>();
	private List ivoMemberDefs = new ArrayList<>();
	private List interconnectObjectMemberDefs = new ArrayList<>();
	private List collectionMemberDefs = new ArrayList<>();
	private List mapMemberDefs = new ArrayList<>();
	private List filterableMemberDefs = new ArrayList<>();
	private List entityLinkLabel = new ArrayList<>();
	private Set imports = new TreeSet<>();
	private Set iimports = new TreeSet<>();
	private Set fimports = new TreeSet<>();
	private FileType type = FileType.IVO;


	/**
	 * @param ivod the ivo definition
	 */
	public MetaModelHelper(IVODef ivod) {
		this.ivod = ivod;
		this.buildCache();
	}

	private void buildCache() {
		// sort children
		boolean hasDate = false;
		boolean hasBigDecimal = false;
		boolean hasUUID = false;
		if (this.ivod.getChildren() == null) {
			this.ivod.setChildren(new ArrayList<>());
		}
		if (this.ivod.getPageable()) {
			List children = new ArrayList<>(this.ivod.getChildren());
			children.add(this.createID(IPageable.class));
			children.add(this.createIMD("limit", "the maximum result size", true));
			children.add(this.createIMD("offset", "the offset of the first result", true));
			children.add(this.createSMD("sortBy", "provide this to enable a correct sorted paging of your lists. Use {@link #withSortDirection(Direction)} to provide information about sort direction", false));
			children.add(this.createEMD("sortDirection", Direction.class, "provide this to enable a correct sorted paging of your lists. Use {@link #withSortBy(String)} to provide information about the property to sort by", false));
			this.ivod.setChildren(children);
		}
		if (this.ivod.getGenerateFilter()) {
			this.filterableMemberDefs.add(this.createIMD("limit", "the maximum result size", true));
			this.filterableMemberDefs.add(this.createIMD("offset", "the offset of the first result", true));
			this.filterableMemberDefs.add(this.createSMD("sortBy", "provide this to enable a correct sorted paging of your lists. Use {@link #withSortDirection(Direction)} to provide information about sort direction", false));
			this.filterableMemberDefs.add(this.createEMD("sortDirection", Direction.class, "provide this to enable a correct sorted paging of your lists. Use {@link #withSortBy(String)} to provide information about the property to sort by", false));
		}

		for (Object o : this.ivod.getChildren()) {
			if ((o instanceof UUIDMemberDef) || (o instanceof BigDecimalMemberDef) || (o instanceof BooleanMemberDef) //
					|| (o instanceof DateMemberDef) || (o instanceof IntegerMemberDef) || (o instanceof LongMemberDef) //
					|| (o instanceof StringMemberDef)) {
				this.allMemberDefs.add((MemberDef) o);
				this.noCollectionMemberDefs.add((MemberDef) o);
			} else if (o instanceof CollectionMemberDef) {
				this.collectionMemberDefs.add((CollectionMemberDef) o);
			} else if (o instanceof EnumMemberDef) {
				this.enumMemberDefs.add((EnumMemberDef) o);
			} else if (o instanceof MapMemberDef) {
				this.mapMemberDefs.add((MapMemberDef) o);
			} else if (o instanceof InterconnectObjectMemberDef) {
				this.interconnectObjectMemberDefs.add((InterconnectObjectMemberDef) o);
			} else if (o instanceof IVOMemberDef) {
				this.ivoMemberDefs.add((IVOMemberDef) o);
			} else if (o instanceof ImplementsDef) {
				this.implementsDef.add((ImplementsDef) o);
			}

			if ((o instanceof ILabelMember) && ((ILabelMember) o).useAsLabel()) {
				this.entityLinkLabel.add((MemberDef) o);
			}

			if ((o instanceof IFilterableMember) && ((IFilterableMember) o).isAFilterMember()) {
				this.filterableMemberDefs.add((MemberDef) o);
			}

			// import stuff
			if (o instanceof BigDecimalMemberDef) {
				hasBigDecimal = true;
			}
			if (o instanceof DateMemberDef) {
				hasDate = true;
			}
			if (o instanceof UUIDMemberDef) {
				hasUUID = true;
			}
		}
		this.allMemberDefs.addAll(this.collectionMemberDefs);
		this.allMemberDefs.addAll(this.enumMemberDefs);
		this.allMemberDefs.addAll(this.mapMemberDefs);
		this.allMemberDefs.addAll(this.ivoMemberDefs);
		this.allMemberDefs.addAll(this.interconnectObjectMemberDefs);
		this.noCollectionMemberDefs.addAll(this.enumMemberDefs);
		this.noCollectionMemberDefs.addAll(this.ivoMemberDefs);
		this.noCollectionMemberDefs.addAll(this.interconnectObjectMemberDefs);
		// determine imports
		this.imports.add(JsonDeserialize.class.getCanonicalName());
		this.imports.add(JsonPOJOBuilder.class.getCanonicalName());
		this.imports.add(Nullable.class.getCanonicalName());
		this.imports.add(IVOBuilder.class.getCanonicalName());
		this.iimports.add(Nullable.class.getCanonicalName());
		this.imports.add(IVO.class.getCanonicalName());
		this.imports.add(Nonnull.class.getCanonicalName());
		this.iimports.add(Nonnull.class.getCanonicalName());
		this.iimports.add(JsonTypeInfo.class.getCanonicalName());
		if (this.isDeprecated()) {
			this.imports.add(ToBeRemoved.class.getCanonicalName());
			this.iimports.add(ToBeRemoved.class.getCanonicalName());
		}
		if (this.ivod.getAuditing()) {
			this.iimports.add(IIVOAuditing.class.getCanonicalName());
		}
		if (this.ivod.getPageable()) {
			this.imports.add(IPageableBuilder.class.getCanonicalName());
			this.iimports.add(IPageableBuilder.class.getCanonicalName());
		}
		if (Boolean.TRUE.equals(this.ivod.getIdentity())) {
			this.iimports.add(JsonIgnore.class.getCanonicalName());
		}
		if ((this.ivod.getParentName() == null)) {
			this.imports.add(AbstractIVO.class.getCanonicalName());
		}
		if ((this.ivod.getFilterPkgName() != null) && !this.ivod.getFilterPkgName().equals(this.ivod.getPkgName())) {
			this.fimports.add(this.ivod.getPkgName() + "." + this.getIVOInterfaceName());
			this.fimports.add(this.ivod.getPkgName() + "." + this.getIVOClazzName());
		}
		if (this.ivod.getParentName() != null) {
			if ((this.ivod.getParentPkgName() != null) && !this.ivod.getParentPkgName().isEmpty() && !this.ivod.getPkgName().equals(this.ivod.getParentPkgName())) {
				this.fimports.add(this.ivod.getParentPkgName() + "." + this.getParentIVOFilterName() + "." + this.getParentIVONFName());
				this.imports.add(this.ivod.getParentPkgName() + "." + this.getVersionedClazzType(this.ivod.getParentName(), this.ivod.getParentVersion()));
				this.iimports.add(this.ivod.getParentPkgName() + "." + this.getVersionedType(this.ivod.getParentName(), this.ivod.getParentVersion(), true));
			}
			if ((this.ivod.getFilterPkgName() != null) && ((this.ivod.getParentFilterPkgName() == null) || this.ivod.getParentFilterPkgName().equals(this.ivod.getFilterPkgName()))) {
				this.fimports.add(this.ivod.getFilterPkgName() + "." + this.getParentIVOFilterName() + "." + this.getParentIVONFName());
			} else if (this.ivod.getFilterPkgName() != null) {
				this.fimports.add(this.ivod.getParentFilterPkgName() + "." + this.getParentIVOFilterName() + "." + this.getParentIVONFName());
			}
		}
		if (hasBigDecimal) {
			this.imports.add(BigDecimal.class.getCanonicalName());
			this.iimports.add(BigDecimal.class.getCanonicalName());
		}
		if (hasDate) {
			this.imports.add(DateTime.class.getCanonicalName());
			this.iimports.add(DateTime.class.getCanonicalName());
		}
		if (hasUUID) {
			this.imports.add(UUID.class.getCanonicalName());
			this.iimports.add(UUID.class.getCanonicalName());
		}
		for (EnumMemberDef emd : this.enumMemberDefs) {
			this.imports.add(emd.getPkgName() + "." + emd.getClazz());
			this.iimports.add(emd.getPkgName() + "." + emd.getClazz());
		}
		for (InterconnectObjectMemberDef iomd : this.interconnectObjectMemberDefs) {
			this.imports.add(iomd.getPkgName() + "." + iomd.getClazz());
			this.iimports.add(iomd.getPkgName() + "." + iomd.getClazz());
		}
		for (ImplementsDef id : this.implementsDef) {
			this.imports.add(id.getPkgName() + "." + id.getName());
			this.iimports.add(id.getPkgName() + "." + id.getName());
		}
		for (IVOMemberDef imd : this.ivoMemberDefs) {
			if (imd.getIvoName() == null) {
				this.imports.add(IVO.class.getCanonicalName());
				this.iimports.add(IVO.class.getCanonicalName());
			} else {
				if ((imd.getPkgName() != null) && !imd.getPkgName().equals(this.ivod.getPkgName())) {
					this.imports.add(imd.getPkgName() + "." + this.getVersionedType(imd.getIvoName(), imd.getVersion(), false));
					this.iimports.add(imd.getPkgName() + "." + this.getVersionedType(imd.getIvoName(), imd.getVersion(), true));
				}
				// if ((imd.getPkgName() != null) && (this.ivod.getFilterPkgName() != null) &&
				// !imd.getPkgName().equals(this.ivod.getFilterPkgName())) {
				// this.fimports.add(imd.getPkgName() + "." + this.getVersionedType(imd.getIvoName(), imd.getVersion()));
				// }
			}
		}
		for (CollectionMemberDef cmd : this.collectionMemberDefs) {
			this.imports.add(Collections.class.getCanonicalName());
			if (CollectionType.List.equals(cmd.getCollectionType())) {
				this.imports.add(List.class.getCanonicalName());
				this.iimports.add(List.class.getCanonicalName());
				this.imports.add(ArrayList.class.getCanonicalName());
			} else {
				this.imports.add(Set.class.getCanonicalName());
				this.iimports.add(Set.class.getCanonicalName());
				this.imports.add(HashSet.class.getCanonicalName());
			}
			this.addToImports(cmd.getContentDef());
		}
		for (MapMemberDef mmd : this.mapMemberDefs) {
			if (MapType.Map.equals(mmd.getMapType())) {
				this.imports.add(Map.class.getCanonicalName());
				this.imports.add(HashMap.class.getCanonicalName());
				this.iimports.add(Map.class.getCanonicalName());
				this.imports.add(Collections.class.getCanonicalName());
			} else {
				this.imports.add(Map.class.getCanonicalName());
				this.imports.add(Multimaps.class.getCanonicalName());
				this.imports.add(Multimap.class.getCanonicalName());
				this.imports.add(HashMultimap.class.getCanonicalName());
				this.iimports.add(Multimap.class.getCanonicalName());
			}
			this.addToImports(mmd.getKeyContent());
			this.addToImports(mmd.getValueContent());
		}
		for (MemberDef md : this.allMemberDefs) {
			if (Boolean.TRUE.equals(md.getJsonTransientFlag())) {
				this.imports.add(JsonIgnore.class.getCanonicalName());
			}
		}
		this.fimports.addAll(this.iimports);
		this.fimports.add(Collection.class.getCanonicalName());
	}

	private ImplementsDef createID(Class clazz) {
		ImplementsDef id = new ImplementsDef();
		id.setName(clazz.getSimpleName());
		id.setPkgName(clazz.getPackage().getName());
		return id;
	}

	private IntegerMemberDef createIMD(String name, String comment, boolean required) {
		IntegerMemberDef imd = new IntegerMemberDef();
		imd.setComment(comment);
		imd.setJavaTransientFlag(Boolean.FALSE);
		imd.setJsonTransientFlag(Boolean.FALSE);
		imd.setName(name);
		imd.setOrderTransient(Boolean.FALSE);
		imd.setRequired(required);
		return imd;
	}

	private LongMemberDef createLMD(String name, String comment, boolean required) {
		LongMemberDef lmd = new LongMemberDef();
		lmd.setComment(comment);
		lmd.setJavaTransientFlag(Boolean.FALSE);
		lmd.setJsonTransientFlag(Boolean.FALSE);
		lmd.setName(name);
		lmd.setOrderTransient(Boolean.FALSE);
		lmd.setRequired(required);
		return lmd;
	}

	private StringMemberDef createSMD(String name, String comment, boolean required) {
		StringMemberDef smd = new StringMemberDef();
		smd.setComment(comment);
		smd.setJavaTransientFlag(Boolean.FALSE);
		smd.setJsonTransientFlag(Boolean.FALSE);
		smd.setName(name);
		smd.setOrderTransient(Boolean.FALSE);
		smd.setRequired(required);
		return smd;
	}

	private EnumMemberDef createEMD(String name, Class clazz, String comment, boolean required) {
		EnumMemberDef emd = new EnumMemberDef();
		emd.setComment(comment);
		emd.setJavaTransientFlag(Boolean.FALSE);
		emd.setJsonTransientFlag(Boolean.FALSE);
		emd.setName(name);
		emd.setOrderTransient(Boolean.FALSE);
		emd.setRequired(required);
		emd.setClazz(clazz.getSimpleName());
		emd.setPkgName(clazz.getPackage().getName());
		return emd;
	}

	private void addToImports(ContentDef def) {
		switch (def.getType()) {
		case Date:
			this.imports.add(DateTime.class.getCanonicalName());
			this.iimports.add(DateTime.class.getCanonicalName());
			break;
		case Decimal:
			this.imports.add(BigDecimal.class.getCanonicalName());
			this.iimports.add(BigDecimal.class.getCanonicalName());
			break;
		case Enum:
			this.imports.add(def.getPkgName() + "." + def.getClazz());
			this.iimports.add(def.getPkgName() + "." + def.getClazz());
			break;
		case IVO:
			if (def.getIvoName() == null) {
				this.imports.add(IVO.class.getCanonicalName());
				this.iimports.add(IVO.class.getCanonicalName());
			} else {
				if ((def.getPkgName() != null) && !def.getPkgName().equals(this.ivod.getPkgName())) {
					this.imports.add(def.getPkgName() + "." + this.getVersionedType(def.getIvoName(), def.getVersion(), false));
					this.iimports.add(def.getPkgName() + "." + this.getVersionedType(def.getIvoName(), def.getVersion(), true));
				}
				// if ((def.getPkgName() != null) && (this.ivod.getFilterPkgName() != null) &&
				// !def.getPkgName().equals(this.ivod.getFilterPkgName())) {
				// this.fimports.add(def.getPkgName() + "." + this.getVersionedType(def.getIvoName(), def.getVersion(), false));
				// }
			}
			break;
		default:
			break;

		}
	}

	/**
	 * @return the real class name
	 */
	public String getIVOClazzName() {
		return this.getRealVersionedType(this.ivod.getName());
	}

	/**
	 * @return the modified class name
	 */
	public String getModIVOClazzName() {
		switch (this.type) {
		case CREATE:
			return "Create" + this.getRealVersionedType(this.ivod.getName());
		case DELETE:
			return "Delete" + this.getRealVersionedType(this.ivod.getName());
		case FINDBY:
			return "Find" + this.ivod.getName() + "ByIdIVO_v" + this.ivod.getVersion();
		case IVO:
			return this.getRealVersionedType(this.ivod.getName());
		case UPDATE:
			return "Update" + this.getRealVersionedType(this.ivod.getName());
		case FILTER:
			return "Find" + this.getRealVersionedType(this.ivod.getName());
		case AUDITING:
			return "Find" + this.ivod.getName() + "ByIdAuditedIVO_v" + this.ivod.getVersion();
		default:
			return this.getRealVersionedType(this.ivod.getName());
		}
	}

	/**
	 * @return the real interface name
	 */
	public String getIVOInterfaceName() {
		return "I" + this.getIVOClazzName();
	}

	/**
	 * @return the modified interface name
	 */
	public String getModIVOInterfaceName() {
		return "I" + this.getModIVOClazzName();
	}

	/**
	 * @return the real filter name
	 */
	public String getIVOFilterName() {
		return this.ivod.getName() + "IVOFilter_v" + this.ivod.getVersion();
	}

	/**
	 * @return the real filter name
	 */
	public String getParentIVOFilterName() {
		return this.ivod.getParentName() + "IVOFilter_v" + this.ivod.getParentVersion();
	}

	/**
	 * @return the real filter name
	 */
	public String getIVODNFName() {
		return this.ivod.getName() + "IVODNF_v" + this.ivod.getVersion();
	}

	/**
	 * @return the real filter name
	 */
	public String getIVOCNFName() {
		return this.ivod.getName() + "IVOCNF_v" + this.ivod.getVersion();
	}

	/**
	 * @return the real filter name
	 */
	public String getIVONFName() {
		return this.ivod.getName() + "IVONF_v" + this.ivod.getVersion();
	}

	/**
	 * @return the real filter name
	 */
	public String getParentIVONFName() {
		return this.ivod.getParentName() + "IVONF_v" + this.ivod.getParentVersion();
	}

	/**
	 * @return the implements string
	 */
	public String getIImplements() {
		StringBuilder builder = new StringBuilder();
		boolean first = true;
		if ((this.ivod.getParentName() != null) && (this.type == FileType.IVO)) {
			builder.append("extends ");
			first = false;
			builder.append(this.getVersionedType(this.ivod.getParentName(), this.ivod.getParentVersion(), true));
			if (this.ivod.getCompatibleBaseVersion() != null) {
				builder.append(", ");
				builder.append(this.getVersionedType(this.ivod.getName(), this.ivod.getCompatibleBaseVersion(), true));
			}
		} else if (this.ivod.getCompatibleBaseVersion() != null) {
			builder.append("extends ");
			first = false;
			builder.append(this.getVersionedType(this.ivod.getName(), this.ivod.getCompatibleBaseVersion(), true));
		}
		if (this.ivod.getAuditing() && (this.type == FileType.IVO)) {
			if (first) {
				builder.append("extends ");
				first = false;
			} else {
				builder.append(", ");
			}
			builder.append("IIVOAuditing");
		}
		for (ImplementsDef i : this.implementsDef) {
			if (first) {
				builder.append("extends ");
				first = false;
			} else {
				builder.append(", ");
			}
			builder.append(i.getName());
		}
		if (this.type == FileType.FILTER) {
			if (first) {
				builder.append("extends ");
				first = false;
			} else {
				builder.append(", ");
			}
			builder.append(IPageable.class.getCanonicalName());
		}
		return builder.toString();
	}

	/**
	 * @param buffer string to return with the first char in upper case
	 * @return the upper-case-first string
	 */
	public String upperCaseFirst(String buffer) {
		return buffer.length() > 0 ? buffer.substring(0, 1).toUpperCase() + buffer.substring(1) : "";
	}

	/**
	 * @return the implementsDef
	 */
	public List getImplementsDef() {
		return this.implementsDef;
	}

	/**
	 * @return the ivo member defs
	 */
	public List getIvoMemberDefs() {
		return this.ivoMemberDefs;
	}

	/**
	 * @return the enumMemberDefs
	 */
	public List getEnumMemberDefs() {
		return this.enumMemberDefs;
	}

	/**
	 * @return the MapMemberDefs
	 */
	public List getMapMemberDefs() {
		return this.mapMemberDefs;
	}

	/**
	 * @return the collectionMemberDefs
	 */
	public List getCollectionMemberDefs() {
		return this.collectionMemberDefs;
	}

	/**
	 * @return the allMemberDefs
	 */
	public List getAllMemberDefs() {
		return this.allMemberDefs;
	}

	/**
	 * @return the allMemberDefs
	 */
	public List getEntitLinkLabels() {
		return this.entityLinkLabel;
	}

	/**
	 * @return the allMemberDefs
	 */
	public List getFilterableMemberDefs() {
		return this.filterableMemberDefs;
	}

	/**
	 * @return the no collection member defs
	 */
	public List getNoCollectionMemberDefs() {
		return this.noCollectionMemberDefs;
	}

	/**
	 * @return the imports
	 */
	public Set getImports() {
		switch (this.type) {
		case IVO:
			Set r = new HashSet<>();
			r.addAll(this.imports);
			r.add(JsonIgnore.class.getCanonicalName());
			return r;
		case FILTER:
			Set r1 = new HashSet<>();
			r1.addAll(this.imports);
			r1.add(IPageable.class.getCanonicalName());
			r1.add(IPageableBuilder.class.getCanonicalName());
			r1.add(Direction.class.getCanonicalName());
			return r1;
		case CREATE:
		case UPDATE:
		case DELETE:
		case FINDBY:
		case AUDITING:
		default:
			return this.imports;
		}
	}

	/**
	 * @return the imports for filters
	 */
	public Set getFImports() {
		return this.fimports;
	}

	/**
	 * @param def the member
	 * @return the type as string
	 */
	public String getDefault(MemberDef def) {
		String result = "null";
		if (def instanceof CollectionMemberDef) {
			CollectionMemberDef cmd = (CollectionMemberDef) def;
			switch (cmd.getCollectionType()) {
			case List:
				result = "new ArrayList<>()";
				break;
			case Set:
				result = "new HashSet<>()";
				break;
			}
		} else if (def instanceof MapMemberDef) {
			MapMemberDef mmd = (MapMemberDef) def;
			switch (mmd.getMapType()) {
			case Map:
				result = "new HashMap<>()";
				break;
			case Multimap:
				result = "HashMultimap.create()";
				break;
			}
		}
		return result;
	}

	private String getRealVersionedType(String typeName) {
		return typeName + "IVO_v" + this.ivod.getVersion();
	}

	/**
	 * @param typeName the type name
	 * @param version the version
	 * @param isInterface true if interface should be used
	 * @return the type string
	 */
	private String getVersionedType(String typeName, Integer version, boolean isInterface) {
		return (isInterface ? "I" : "") + typeName + "IVO_v" + version;
	}

	/**
	 * @param typeName the type name
	 * @param version the version
	 * @return the type string
	 */
	public String getVersionedClazzType(String typeName, Integer version) {
		return typeName + "IVO_v" + version;
	}

	/**
	 * @param content the content
	 * @param isInterface true if interface
	 * @return the generic type
	 */
	private String getGenericType(ContentDef content, boolean isInterface) {
		String result = null;
		switch (content.getType()) {
		case IVO:
			result = "? extends " + (content.getIvoName() == null ? "IVO" : this.getVersionedType(content.getIvoName(), content.getVersion(), isInterface));
			break;
		case Boolean:
			result = Boolean.class.getSimpleName();
			break;
		case Date:
			result = DateTime.class.getSimpleName();
			break;
		case Decimal:
			result = BigDecimal.class.getSimpleName();
			break;
		case Integer:
			result = Integer.class.getSimpleName();
			break;
		case Long:
			result = Long.class.getSimpleName();
			break;
		case String:
			result = String.class.getSimpleName();
			break;
		case InterconnectObject:
		case Enum:
			result = content.getClazz();
			break;
		case UUID:
			result = UUID.class.getSimpleName();
			break;
		}
		return result;
	}

	/**
	 * @param def the member
	 * @param isInterface true if using interface mode
	 * @return the type as string
	 */
	public String getType(MemberDef def, boolean isInterface) {
		String result = null;
		if (def instanceof BigDecimalMemberDef) {
			result = BigDecimal.class.getSimpleName();
		} else if (def instanceof BooleanMemberDef) {
			result = Boolean.class.getSimpleName();
		} else if (def instanceof CollectionMemberDef) {
			CollectionMemberDef cmd = (CollectionMemberDef) def;
			StringBuilder builder = new StringBuilder();
			switch (cmd.getCollectionType()) {
			case List:
				builder.append(List.class.getSimpleName());
				break;
			case Set:
				builder.append(Set.class.getSimpleName());
				break;
			}
			builder.append("<");
			builder.append(this.getGenericType(cmd.getContentDef(), isInterface));
			builder.append(">");
			result = builder.toString();
		} else if (def instanceof DateMemberDef) {
			result = DateTime.class.getSimpleName();
		} else if (def instanceof EnumMemberDef) {
			result = ((EnumMemberDef) def).getClazz();
		} else if (def instanceof IntegerMemberDef) {
			result = Integer.class.getSimpleName();
		} else if (def instanceof InterconnectObjectMemberDef) {
			result = ((InterconnectObjectMemberDef) def).getClazz();
		} else if (def instanceof IVOMemberDef) {
			IVOMemberDef imd = (IVOMemberDef) def;
			result = imd.getIvoName() == null ? IVO.class.getSimpleName() : this.getVersionedType(imd.getIvoName(), imd.getVersion(), isInterface);
		} else if (def instanceof LongMemberDef) {
			result = Long.class.getSimpleName();
		} else if (def instanceof StringMemberDef) {
			result = String.class.getSimpleName();
		} else if (def instanceof MapMemberDef) {
			MapMemberDef mmd = (MapMemberDef) def;
			StringBuilder builder = new StringBuilder();
			switch (mmd.getMapType()) {
			case Map:
				builder.append(Map.class.getSimpleName());
				break;
			case Multimap:
				builder.append(Multimap.class.getSimpleName());
				break;
			}
			builder.append("<");
			builder.append(this.getGenericType(mmd.getKeyContent(), isInterface));
			builder.append(", ");
			builder.append(this.getGenericType(mmd.getValueContent(), isInterface));
			builder.append(">");
			result = builder.toString();
		} else if (def instanceof UUIDMemberDef) {
			result = UUID.class.getSimpleName();
		}
		return result;
	}

	/**
	 * @return the interface imports
	 */
	public Set getIImports() {
		switch (this.type) {
		case FILTER:
			Set r1 = new HashSet<>();
			r1.addAll(this.imports);
			r1.add(IPageable.class.getCanonicalName());
			r1.add(Direction.class.getCanonicalName());
			r1.add(JsonTypeInfo.class.getCanonicalName());
			return r1;
		default:
			return this.iimports;
		}
	}

	/**
	 * @return the parent clazz
	 */
	public String getParent() {
		switch (this.type) {
		case CREATE:
		case UPDATE:
		case DELETE:
		case FINDBY:
		case FILTER:
		case AUDITING:
			return AbstractIVO.class.getSimpleName();
		case IVO:
		default:
			return this.ivod.getParentName() == null ? AbstractIVO.class.getSimpleName() : this.getVersionedClazzType(this.ivod.getParentName(), this.ivod.getParentVersion());
		}
	}

	/**
	 * @return the parent builder
	 */
	public String getParentBuilder() {
		switch (this.type) {
		case CREATE:
		case UPDATE:
		case DELETE:
		case FINDBY:
		case FILTER:
		case AUDITING:
			return "";
		case IVO:
		default:
			return this.ivod.getParentName() == null ? "" : " extends Abstract" + this.getVersionedClazzType(this.ivod.getParentName(), this.ivod.getParentVersion()) + "Builder";
		}
	}

	/**
	 * @return true if ivo is deprecated
	 */
	public boolean isDeprecated() {
		return (this.ivod.getRemovalDate() != null) && !this.ivod.getRemovalDate().isEmpty();
	}

	/**
	 * @return the implements for the builder
	 */
	public String getBuilderImplements() {
		StringBuilder result = new StringBuilder();
		if (this.ivod.getPageable() || (this.type == FileType.FILTER)) {
			result.append("implements ");
			if (this.ivod.getPageable() || (this.type == FileType.FILTER)) {
				result.append(IPageableBuilder.class.getSimpleName());
			}
		}
		return result.toString();
	}

	/**
	 * @param type the type to set
	 */
	public void setType(FileType type) {
		this.type = type;
	}
}