package com.constellio.app.api.cmis.requests;
import static com.constellio.app.ui.i18n.i18n.$;
import java.io.InputStream;
import java.util.Set;
import com.constellio.model.services.contents.ContentVersionDataSummary;
import com.constellio.model.services.contents.icap.IcapException;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.slf4j.Logger;
import com.constellio.app.api.cmis.CmisExceptions.CmisExceptions_Runtime;
import com.constellio.app.api.cmis.CmisExceptions.CmisExceptions_UnsupportedOperation;
import com.constellio.app.api.cmis.ConstellioCmisException;
import com.constellio.app.api.cmis.binding.collection.ConstellioCollectionRepository;
import com.constellio.app.api.cmis.binding.global.ConstellioCmisContextParameters;
import com.constellio.app.api.cmis.builders.object.AllowableActionsBuilder;
import com.constellio.app.api.cmis.builders.object.ContentObjectDataBuilder;
import com.constellio.app.api.cmis.builders.object.ObjectDataBuilder;
import com.constellio.app.api.cmis.builders.object.TaxonomyObjectBuilder;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.data.io.services.facades.IOServices;
import com.constellio.model.entities.Taxonomy;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.services.contents.ContentManager;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.search.SearchServices;
import com.constellio.model.services.taxonomies.TaxonomiesManager;
import com.constellio.model.services.taxonomies.TaxonomiesSearchOptions;
import com.constellio.model.services.taxonomies.TaxonomiesSearchServices;
public abstract class CmisCollectionRequest<T> {
protected final ConstellioCollectionRepository repository;
protected final ModelLayerFactory modelLayerFactory;
protected final AppLayerFactory appLayerFactory;
protected final IOServices ioServices;
protected final RecordServices recordServices;
protected final SearchServices searchServices;
protected final TaxonomiesSearchServices taxonomiesSearchServices;
protected final TaxonomiesManager taxonomiesManager;
protected final ContentManager contentManager;
protected final CallContext callContext;
protected final User user;
protected final String collection;
protected final AllowableActionsBuilder allowableActionsBuilder;
public CmisCollectionRequest(CallContext callContext, ConstellioCollectionRepository repository,
AppLayerFactory appLayerFactory) {
this.repository = repository;
this.appLayerFactory = appLayerFactory;
this.modelLayerFactory = appLayerFactory.getModelLayerFactory();
this.callContext = callContext;
this.user = (User) callContext.get(ConstellioCmisContextParameters.USER);
this.collection = (String) callContext.get(ConstellioCmisContextParameters.COLLECTION);
this.recordServices = modelLayerFactory.newRecordServices();
this.searchServices = modelLayerFactory.newSearchServices();
this.taxonomiesSearchServices = modelLayerFactory.newTaxonomiesSearchService();
this.taxonomiesManager = modelLayerFactory.getTaxonomiesManager();
this.contentManager = modelLayerFactory.getContentManager();
this.ioServices = modelLayerFactory.getIOServicesFactory().newIOServices();
this.allowableActionsBuilder = new AllowableActionsBuilder(repository, appLayerFactory, callContext);
}
public ObjectDataBuilder newObjectDataBuilder() {
return new ObjectDataBuilder(repository, appLayerFactory, callContext);
}
public ContentObjectDataBuilder newContentObjectDataBuilder() {
return new ContentObjectDataBuilder(repository, appLayerFactory, callContext);
}
public TaxonomyObjectBuilder newTaxonomyObjectBuilder() {
return new TaxonomyObjectBuilder(callContext);
}
protected MetadataSchemaTypes types() {
return modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection);
}
public final T processRequest() {
Logger logger = getLogger();
try {
T response = process();
return response;
} catch (UnsupportedOperationException e) {
throw new CmisExceptions_UnsupportedOperation();
} catch (ConstellioCmisException e) {
String requestString = toString().replace("com.constellio.app.api.cmis.requests.", "");
logger.error("Constellio exception while calling cmis request ' " + requestString + "'", e);
throw new CmisExceptions_Runtime(e.getMessage());
} catch (Throwable t) {
String requestString = toString().replace("com.constellio.app.api.cmis.requests.", "");
logger.error("Unepected exception while calling cmis request ' " + requestString + "'", t);
throw new CmisExceptions_Runtime(t.getMessage());
}
}
protected abstract T process()
throws ConstellioCmisException;
protected abstract Logger getLogger();
protected Set<Action> getAllowableActionsOn(Record record) {
return allowableActionsBuilder.build(record).getAllowableActions();
}
protected void ensureUserHasAllowableActionsOnRecord(Record record, Action... actions) {
Set<Action> recordAllowableActions = getAllowableActionsOn(record);
for (Action action : actions) {
if (!recordAllowableActions.contains(action)) {
throw new CmisPermissionDeniedException($("CmisCollectionRequest_forbiddenAction",
user.getUsername(), action.name(), record.getId(), record.getTitle()));
}
}
}
protected void ensureUserHasReadAccessToRecordOrADescendantOf(Record record) {
if (!user.hasReadAccess().on(record)) {
Taxonomy taxonomy = taxonomiesManager.getTaxonomyOf(record);
if (taxonomy == null || taxonomy.hasSameCode(taxonomiesManager.getPrincipalTaxonomy(record.getCollection()))) {
TaxonomiesSearchOptions options = new TaxonomiesSearchOptions().setRows(1)
.setAlwaysReturnTaxonomyConceptsWithReadAccess(true);
if (taxonomiesSearchServices.getVisibleChildConcept(user, record, options).isEmpty()) {
throw new CmisPermissionDeniedException($("CmisCollectionRequest_noReadAccess",
user.getUsername(), record.getId(), record.getTitle()));
}
}
}
}
protected void ensureUserHasWriteAccessOnRecord(Record record) {
if (!user.hasWriteAccess().on(record)) {
throw new CmisPermissionDeniedException($("CmisCollectionRequest_noWriteAccess",
user.getUsername(), record.getId(), record.getTitle()));
}
}
protected ContentVersionDataSummary uploadContent(final InputStream inputStream, final String fileName) {
try {
return modelLayerFactory.getContentManager().upload(inputStream, fileName);
} catch (final IcapException e) {
if (e instanceof IcapException.ThreatFoundException) {
throw new IcapException($(e, e.getFileName(), ((IcapException.ThreatFoundException) e).getThreatName()));
}
if (e.getCause() == null) {
throw new IcapException($(e, e.getFileName()));
} else {
throw new IcapException($(e, e.getFileName()), e.getCause());
}
}
}
}