String generateModel(String packageName, boolean annotateSchema, boolean trimStrings) {

		// import statements
		Set<String> imports = Utils.newHashSet();
		imports.add(Serializable.class.getCanonicalName());
		imports.add(IQSchema.class.getCanonicalName());
		imports.add(IQTable.class.getCanonicalName());
		imports.add(IQIndexes.class.getCanonicalName());
		imports.add(IQIndex.class.getCanonicalName());
		imports.add(IQColumn.class.getCanonicalName());
		imports.add(IndexType.class.getCanonicalName());

		// fields
		StringBuilder fields = new StringBuilder();
		List<ColumnInspector> sortedColumns = Utils.newArrayList(columns.values());
		Collections.sort(sortedColumns);
		for (ColumnInspector col : sortedColumns) {
			fields.append(generateColumn(imports, col, trimStrings));
		}

		// build complete class definition
		StringBuilder model = new StringBuilder();
		if (!isNullOrEmpty(packageName)) {
			// package
			model.append("package " + packageName + ";");
			model.append(eol).append(eol);
		}

		// imports
		List<String> sortedImports = new ArrayList<String>(imports);
		Collections.sort(sortedImports);
		for (String imp : sortedImports) {
			model.append("import ").append(imp).append(';').append(eol);
		}
		model.append(eol);

		// @IQSchema
		if (annotateSchema && !isNullOrEmpty(schema)) {
			model.append('@').append(IQSchema.class.getSimpleName());
			model.append('(');
			AnnotationBuilder ap = new AnnotationBuilder();
			ap.addParameter(null, schema);
			model.append(ap);
			model.append(')').append(eol);
		}

		// @IQTable
		model.append('@').append(IQTable.class.getSimpleName());
		model.append('(');

		// IQTable annotation parameters
		AnnotationBuilder ap = new AnnotationBuilder();
		ap.addParameter("name", table);

		if (primaryKeys.size() > 1) {
			ap.addParameter("primaryKey", primaryKeys);
		}

		// finish @IQTable annotation
		model.append(ap);
		model.append(')').append(eol);

		// @IQIndexes
		// @IQIndex
		String indexAnnotations = generateIndexAnnotations();
		if (!StringUtils.isNullOrEmpty(indexAnnotations)) {
			model.append(indexAnnotations);
		}

		// class declaration
		String clazzName = ModelUtils.convertTableToClassName(table);
		model.append(format("public class {0} implements Serializable '{'", clazzName)).append(eol);
		model.append(eol);
		model.append("\tprivate static final long serialVersionUID = 1L;").append(eol);
		model.append(eol);

		// field declarations
		model.append(fields);

		// default constructor
		model.append("\t" + "public ").append(clazzName).append("() {").append(eol);
		model.append("\t}").append(eol);

		// end of class body
		model.append('}');
		model.trimToSize();
		return model.toString();
	}