package com.constellio.app.modules.tasks.migrations;
import static com.constellio.app.entities.schemasDisplay.enums.MetadataInputType.DROPDOWN;
import static com.constellio.app.entities.schemasDisplay.enums.MetadataInputType.HIDDEN;
import static com.constellio.app.entities.schemasDisplay.enums.MetadataInputType.LOOKUP;
import static com.constellio.app.entities.schemasDisplay.enums.MetadataInputType.RICHTEXT;
import static com.constellio.app.modules.tasks.model.wrappers.TaskStatusType.CLOSED;
import static com.constellio.app.modules.tasks.model.wrappers.TaskStatusType.FINISHED;
import static com.constellio.app.modules.tasks.model.wrappers.TaskStatusType.IN_PROGRESS;
import static com.constellio.app.modules.tasks.model.wrappers.TaskStatusType.STANDBY;
import static com.constellio.app.modules.tasks.model.wrappers.types.TaskStatus.CLOSED_CODE;
import static com.constellio.app.modules.tasks.model.wrappers.types.TaskStatus.STANDBY_CODE;
import static com.constellio.model.entities.records.wrappers.ValueListItem.CODE;
import static com.constellio.model.entities.schemas.MetadataValueType.CONTENT;
import static com.constellio.model.entities.schemas.MetadataValueType.DATE;
import static com.constellio.model.entities.schemas.MetadataValueType.NUMBER;
import static com.constellio.model.entities.schemas.MetadataValueType.STRING;
import static com.constellio.model.entities.schemas.MetadataValueType.STRUCTURE;
import static com.constellio.model.entities.schemas.MetadataValueType.TEXT;
import static java.util.Arrays.asList;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import com.constellio.app.entities.modules.MetadataSchemasAlterationHelper;
import com.constellio.app.entities.modules.MigrationHelper;
import com.constellio.app.entities.modules.MigrationResourcesProvider;
import com.constellio.app.entities.modules.MigrationScript;
import com.constellio.app.entities.schemasDisplay.SchemaDisplayConfig;
import com.constellio.app.entities.schemasDisplay.SchemaTypeDisplayConfig;
import com.constellio.app.entities.schemasDisplay.enums.MetadataInputType;
import com.constellio.app.modules.rm.services.ValueListItemSchemaTypeBuilder;
import com.constellio.app.modules.rm.services.ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeBuilderOptions;
import com.constellio.app.modules.rm.services.ValueListItemSchemaTypeBuilder.ValueListItemSchemaTypeCodeMode;
import com.constellio.app.modules.rm.wrappers.RMTask;
import com.constellio.app.modules.rm.wrappers.structures.CommentFactory;
import com.constellio.app.modules.tasks.TasksEmailTemplates;
import com.constellio.app.modules.tasks.model.calculators.TaskFollowersCalculator;
import com.constellio.app.modules.tasks.model.calculators.TaskNextReminderOnCalculator;
import com.constellio.app.modules.tasks.model.calculators.TaskTokensCalculator;
import com.constellio.app.modules.tasks.model.validators.TaskStatusValidator;
import com.constellio.app.modules.tasks.model.validators.TaskValidator;
import com.constellio.app.modules.tasks.model.wrappers.Task;
import com.constellio.app.modules.tasks.model.wrappers.TaskStatusType;
import com.constellio.app.modules.tasks.model.wrappers.structures.TaskFollowerFactory;
import com.constellio.app.modules.tasks.model.wrappers.structures.TaskReminderFactory;
import com.constellio.app.modules.tasks.model.wrappers.types.TaskStatus;
import com.constellio.app.modules.tasks.model.wrappers.types.TaskType;
import com.constellio.app.modules.tasks.services.TasksSchemasRecordsServices;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.app.services.schemasDisplay.SchemaDisplayManagerTransaction;
import com.constellio.app.services.schemasDisplay.SchemaTypesDisplayTransactionBuilder;
import com.constellio.app.services.schemasDisplay.SchemasDisplayManager;
import com.constellio.data.dao.managers.config.ConfigManagerException.OptimisticLockingConfiguration;
import com.constellio.model.entities.Language;
import com.constellio.model.entities.records.Transaction;
import com.constellio.model.entities.records.wrappers.Group;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.schemas.builders.MetadataBuilder;
import com.constellio.model.services.schemas.builders.MetadataSchemaBuilder;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypeBuilder;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder;
import com.constellio.model.services.schemas.validators.PercentageValidator;
public class TasksMigrationTo5_0_7 extends MigrationHelper implements MigrationScript {
@Override
public String getVersion() {
return "5.0.7";
}
@Override
public void migrate(String collection, MigrationResourcesProvider migrationResourcesProvider,
AppLayerFactory appLayerFactory) {
if (!appLayerFactory.getModelLayerFactory().getMetadataSchemasManager().getSchemaTypes(collection)
.hasType(RMTask.SCHEMA_TYPE)) {
new TaskStatusSchemaAlterationFor5_0_7(collection, migrationResourcesProvider, appLayerFactory).migrate();
createTaskStatusTypes(collection, appLayerFactory, migrationResourcesProvider);
TasksSchemasRecordsServices tasksSchemas = new TasksSchemasRecordsServices(collection, appLayerFactory);
TaskStatus standbyStatus = tasksSchemas.getTaskStatusWithCode(STANDBY_CODE);
new TaskSchemaAlterationFor5_0_7(collection, migrationResourcesProvider, appLayerFactory, standbyStatus).migrate();
setupDisplayConfig(collection, appLayerFactory, migrationResourcesProvider);
}
addEmailTemplates(appLayerFactory, migrationResourcesProvider, collection);
}
private void setupDisplayConfig(String collection, AppLayerFactory appLayerFactory,
MigrationResourcesProvider migrationResourcesProvider) {
Language language = migrationResourcesProvider.getLanguage();
String definitionTab = "default:init.userTask.definition";
String filesTab = "init.userTask.details";
String assignmentTab = "init.userTask.assignment";
String remindersTab = "init.userTask.remindersTab";
String followersTab = "init.userTask.followersTab";
SchemasDisplayManager manager = appLayerFactory.getMetadataSchemasDisplayManager();
SchemaDisplayManagerTransaction transaction = new SchemaDisplayManagerTransaction();
SchemaTypeDisplayConfig taskSchemaType = manager.getType(collection, Task.SCHEMA_TYPE);
SchemaDisplayConfig taskSchema = manager.getSchema(collection, Task.DEFAULT_SCHEMA);
transaction.add(taskSchemaType
.withMetadataGroup(migrationResourcesProvider.getLanguageMap(asList(
definitionTab, filesTab, assignmentTab, remindersTab, followersTab)))
.withAdvancedSearchStatus(true).withSimpleSearchStatus(true));
transaction.add(taskSchema
.withSearchResultsMetadataCodes(asList(
Task.DEFAULT_SCHEMA + "_" + Schemas.TITLE,
Task.DEFAULT_SCHEMA + "_" + Task.STATUS,
Task.DEFAULT_SCHEMA + "_" + Task.ASSIGNEE,
Task.DEFAULT_SCHEMA + "_" + Task.DUE_DATE)));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.CONTENTS)
.withMetadataGroup(filesTab).withInputType(MetadataInputType.CONTENT).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.DESCRIPTION)
.withInputType(RICHTEXT).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.ASSIGNEE_USERS_CANDIDATES)
.withMetadataGroup(assignmentTab).withInputType(LOOKUP).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.ASSIGNEE_GROUPS_CANDIDATES)
.withMetadataGroup(assignmentTab).withInputType(LOOKUP).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.ASSIGNEE)
.withMetadataGroup(assignmentTab).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.STATUS)
.withInputType(LOOKUP).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.ASSIGNER)
.withInputType(HIDDEN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.ASSIGNED_ON)
.withInputType(HIDDEN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.END_DATE)
.withInputType(HIDDEN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, TaskStatus.DEFAULT_SCHEMA, TaskStatus.STATUS_TYPE)
.withInputType(DROPDOWN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.REMINDERS)
.withMetadataGroup(remindersTab));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.TASK_FOLLOWERS)
.withMetadataGroup(followersTab));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.PARENT_TASK)
.withInputType(HIDDEN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.START_DATE)
.withInputType(HIDDEN).withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.TYPE)
.withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.TITLE)
.withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.DUE_DATE)
.withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.PARENT_TASK_DUE_DATE)
.withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.FOLLOWERS_IDS)
.withVisibleInAdvancedSearchStatus(true));
transaction.add(manager.getMetadata(collection, Task.DEFAULT_SCHEMA, Task.PROGRESS_PERCENTAGE)
.withVisibleInAdvancedSearchStatus(true));
manager.execute(transaction);
SchemaTypesDisplayTransactionBuilder transactionBuilder = manager.newTransactionBuilderFor(collection);
transactionBuilder
.in(Task.SCHEMA_TYPE)
.addToSearchResult(Task.DUE_DATE, Task.ASSIGNEE)
.atTheEnd();
manager.execute(transactionBuilder.build());
}
private void createTaskStatusTypes(String collection, AppLayerFactory appLayerFactory,
MigrationResourcesProvider migrationResourcesProvider) {
Transaction transaction = new Transaction();
TasksSchemasRecordsServices schemas = new TasksSchemasRecordsServices(collection, appLayerFactory);
String standByCode = STANDBY_CODE;
String inProcessCode = migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.I");
String finishedCode = migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.F");
String closedCode = CLOSED_CODE;
transaction.add(schemas.newTaskStatus().setCode(standByCode)
.setTitle(migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.STitle"))
.setStatusType(STANDBY));
transaction.add(schemas.newTaskStatus().setCode(inProcessCode)
.setTitle(migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.ITitle"))
.setStatusType(IN_PROGRESS));
transaction.add(schemas.newTaskStatus().setCode(finishedCode)
.setTitle(migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.FTitle"))
.setStatusType(FINISHED));
transaction.add(schemas.newTaskStatus().setCode(closedCode)
.setTitle(migrationResourcesProvider.getDefaultLanguageString("TaskStatusType.CTitle"))
.setStatusType(CLOSED));
try {
appLayerFactory.getModelLayerFactory().newRecordServices().execute(transaction);
} catch (RecordServicesException e) {
throw new RuntimeException(e);
}
}
private void addEmailTemplates(AppLayerFactory appLayerFactory, MigrationResourcesProvider migrationResourcesProvider,
String collection) {
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection, "taskAssigneeModificationTemplate.html",
TasksEmailTemplates.TASK_ASSIGNEE_MODIFIED);
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection,
"taskStatusModificationToCompletedTemplate.html",
TasksEmailTemplates.TASK_COMPLETED);
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection, "taskDeletionTemplate.html",
TasksEmailTemplates.TASK_DELETED);
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection, "taskStatusModificationTemplate.html",
TasksEmailTemplates.TASK_STATUS_MODIFIED);
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection, "subTasksModificationTemplate.html",
TasksEmailTemplates.TASK_SUB_TASKS_MODIFIED);
addEmailTemplate(appLayerFactory, migrationResourcesProvider, collection, "taskReminderTemplate.html",
TasksEmailTemplates.TASK_REMINDER);
}
private void addEmailTemplate(AppLayerFactory appLayerFactory, MigrationResourcesProvider migrationResourcesProvider,
String collection,
String templateFileName, String templateId) {
InputStream remindReturnBorrowedFolderTemplate = migrationResourcesProvider.getStream(templateFileName);
try {
appLayerFactory.getModelLayerFactory().getEmailTemplatesManager()
.addCollectionTemplateIfInexistent(templateId, collection, remindReturnBorrowedFolderTemplate);
} catch (IOException | OptimisticLockingConfiguration e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(remindReturnBorrowedFolderTemplate);
}
}
private class TaskStatusSchemaAlterationFor5_0_7 extends MetadataSchemasAlterationHelper {
public TaskStatusSchemaAlterationFor5_0_7(String collection, MigrationResourcesProvider migrationResourcesProvider,
AppLayerFactory appLayerFactory) {
super(collection, migrationResourcesProvider, appLayerFactory);
}
@Override
protected void migrate(MetadataSchemaTypesBuilder typesBuilder) {
createTaskSchemaTypes(typesBuilder);
}
private void createTaskSchemaTypes(MetadataSchemaTypesBuilder typesBuilder) {
createTaskStatusType();
}
private MetadataSchemaTypeBuilder createTaskStatusType() {
MetadataSchemaTypeBuilder schemaType = new ValueListItemSchemaTypeBuilder(types())
.createValueListItemSchema(TaskStatus.SCHEMA_TYPE, "Statut",
ValueListItemSchemaTypeBuilderOptions.codeMetadataRequiredAndUnique())
.setSecurity(false);
MetadataSchemaBuilder defaultSchema = schemaType.getDefaultSchema();
defaultSchema.defineValidators().add(TaskStatusValidator.class);
defaultSchema.getMetadata(CODE).setUniqueValue(true).setUnmodifiable(true);
defaultSchema.createUndeletable(TaskStatus.STATUS_TYPE).defineAsEnum(TaskStatusType.class)
.setDefaultRequirement(true);
return schemaType;
}
}
private class TaskSchemaAlterationFor5_0_7 extends MetadataSchemasAlterationHelper {
TaskStatus standbyStatus;
public TaskSchemaAlterationFor5_0_7(String collection, MigrationResourcesProvider migrationResourcesProvider,
AppLayerFactory appLayerFactory, TaskStatus standbyStatus) {
super(collection, migrationResourcesProvider, appLayerFactory);
this.standbyStatus = standbyStatus;
}
@Override
protected void migrate(MetadataSchemaTypesBuilder typesBuilder) {
MetadataSchemaBuilder taskType = createTaskTypeSchemaType(typesBuilder);
createTaskSchemaType(typesBuilder, taskType);
}
private MetadataSchemaBuilder createTaskTypeSchemaType(MetadataSchemaTypesBuilder typesBuilder) {
String label = migrationResourcesProvider.getDefaultLanguageString("init.ddvTaskType");
MetadataSchemaTypeBuilder schemaType = new ValueListItemSchemaTypeBuilder(typesBuilder)
.createValueListItemSchema(
TaskType.SCHEMA_TYPE, label, ValueListItemSchemaTypeBuilderOptions.codeMetadataRequiredAndUnique())
.setSecurity(false);
MetadataSchemaBuilder schema = schemaType.getDefaultSchema();
schema.create(TaskType.LINKED_SCHEMA).setType(STRING);
return schema;
}
private MetadataSchemaTypeBuilder createTaskSchemaType(MetadataSchemaTypesBuilder typesBuilder,
MetadataSchemaBuilder taskType) {
MetadataSchemaTypeBuilder taskStatusType = typesBuilder.getSchemaType(TaskStatus.SCHEMA_TYPE);
MetadataSchemaTypeBuilder schemaType = types().createNewSchemaType(Task.SCHEMA_TYPE).setSecurity(true);
MetadataSchemaBuilder defaultSchema = schemaType.getDefaultSchema();
defaultSchema.defineValidators().add(TaskValidator.class);
MetadataSchemaBuilder userSchemaBuilder = typesBuilder.getDefaultSchema(User.SCHEMA_TYPE);
defaultSchema.createUndeletable(Task.TYPE).defineReferencesTo(taskType);
defaultSchema.createUndeletable(Task.ASSIGNEE).defineReferencesTo(userSchemaBuilder);
defaultSchema.createUndeletable(Task.ASSIGNER).defineReferencesTo(userSchemaBuilder);
defaultSchema.createUndeletable(Task.ASSIGNEE_GROUPS_CANDIDATES)
.defineReferencesTo(typesBuilder.getDefaultSchema(Group.SCHEMA_TYPE)).setMultivalue(true);
defaultSchema.createUndeletable(Task.ASSIGNEE_USERS_CANDIDATES).defineReferencesTo(
typesBuilder.getDefaultSchema(User.SCHEMA_TYPE)).setMultivalue(true);
defaultSchema.createUndeletable(Task.ASSIGNED_ON).setType(DATE);
defaultSchema.createUndeletable(Task.FOLLOWERS_IDS).defineReferencesTo(userSchemaBuilder).setMultivalue(true)
.defineDataEntry()
.asCalculated(TaskFollowersCalculator.class);
defaultSchema.createUndeletable(Task.TASK_FOLLOWERS).setType(STRUCTURE).setMultivalue(true).defineStructureFactory(
TaskFollowerFactory.class);
defaultSchema.createUndeletable(Task.DESCRIPTION).setType(TEXT).setSearchable(true);
defaultSchema.createUndeletable(Task.CONTENTS).setType(CONTENT).setMultivalue(true).setSearchable(true);
defaultSchema.createUndeletable(Task.NEXT_REMINDER_ON).setType(DATE).defineDataEntry().asCalculated(
TaskNextReminderOnCalculator.class);
defaultSchema.createUndeletable(Task.REMINDERS).setType(STRUCTURE).setMultivalue(true).defineStructureFactory(
TaskReminderFactory.class);
defaultSchema.createUndeletable(Task.START_DATE).setType(DATE);
MetadataBuilder dueDate = defaultSchema.createUndeletable(Task.DUE_DATE).setType(DATE);
defaultSchema.createUndeletable(Task.END_DATE).setType(DATE);
defaultSchema.createUndeletable(Task.STATUS).defineReferencesTo(taskStatusType).setDefaultRequirement(true)
.setDefaultValue(standbyStatus.getId());
defaultSchema.createUndeletable(Task.PROGRESS_PERCENTAGE).setType(NUMBER).addValidator(PercentageValidator.class);
MetadataBuilder parent = defaultSchema.createUndeletable(Task.PARENT_TASK)
.defineChildOfRelationshipToType(schemaType);
defaultSchema.createUndeletable(Task.PARENT_TASK_DUE_DATE).setType(DATE).defineDataEntry().asCopied(
parent, dueDate);
defaultSchema.createUndeletable(Task.COMMENTS).setType(STRUCTURE).defineStructureFactory(CommentFactory.class)
.setMultivalue(true);
defaultSchema.get(Schemas.TITLE.getLocalCode()).setDefaultRequirement(true);
defaultSchema.get(Schemas.TOKENS.getLocalCode()).defineDataEntry().asCalculated(TaskTokensCalculator.class);
return schemaType;
}
}
}