package com.constellio.app.servlet; import static com.constellio.app.ui.i18n.i18n.$; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.MediaType; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.StringUtils; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.constellio.app.api.HttpServletRequestAuthenticator; import com.constellio.app.services.factories.ConstellioFactories; import com.constellio.model.entities.records.Record; import com.constellio.model.entities.records.Transaction; import com.constellio.model.entities.records.wrappers.User; import com.constellio.model.entities.schemas.Metadata; import com.constellio.model.entities.schemas.MetadataSchema; import com.constellio.model.entities.schemas.MetadataSchemaType; import com.constellio.model.entities.schemas.MetadataSchemaTypes; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.frameworks.validation.ValidationRuntimeException; import com.constellio.model.services.factories.ModelLayerFactory; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.records.RecordServicesException; import com.constellio.model.services.search.query.ReturnedMetadatasFilter; import com.constellio.model.services.search.query.logical.LogicalSearchQuery; import com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.google.common.base.Joiner; public class ConstellioCreateRecordServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(ConstellioCreateRecordServlet.class); private static final String SCHEMA_QUERY_PARAM_NAME = "schema"; private static final String MULTIVALUE_SEPARATOR = ","; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { LOGGER.info("Create record called!"); createRecords(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { LOGGER.info("Create records called!"); createRecords(request, response); } private void createRecords(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final PrintWriter responseWriter = response.getWriter(); final User user = new HttpServletRequestAuthenticator(modelLayerFactory()).authenticateSystemAdminInCollection(request); if (user == null) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); responseWriter.append("Unauthorized access : Invalid collection/servicesKey/token"); } else { responseWriter.append("<html>"); String collection = user.getCollection(); MetadataSchemaTypes metadataSchemaTypes = modelLayerFactory().getMetadataSchemasManager().getSchemaTypes(collection); String schemaCode = request.getParameter(SCHEMA_QUERY_PARAM_NAME); MetadataSchema metadataSchema = getMetadataSchema(schemaCode, metadataSchemaTypes, collection, responseWriter); if (metadataSchema != null) { if (HttpMethod.GET.equalsIgnoreCase(request.getMethod())) { createRecordFromGetRequest(metadataSchema, metadataSchemaTypes, request, responseWriter); } else if (HttpMethod.POST.equalsIgnoreCase(request.getMethod())) { createRecordsFromPostRequest(metadataSchema, metadataSchemaTypes, request, response, responseWriter); } else { response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); } } responseWriter.append("</html>"); } } private void createRecordFromGetRequest(MetadataSchema metadataSchema, MetadataSchemaTypes metadataSchemaTypes, HttpServletRequest request, PrintWriter responseWriter) { RecordServices recordServices = modelLayerFactory().newRecordServices(); Record record = recordServices.newRecordWithSchema(metadataSchema); for (Metadata metadata : metadataSchema.getMetadatas().onlyManuals()) { String metadataValue = request.getParameter(metadata.getLocalCode()); setRecordMetadata(record, metadata, metadataValue, metadataSchemaTypes); } boolean error = false; try { recordServices.add(record); } catch (RecordServicesException.ValidationException e) { responseWriter.append($(e.getErrors())); error = true; } catch (ValidationRuntimeException e) { responseWriter.append($(e.getValidationErrors())); error = true; } catch (RecordServicesException e) { responseWriter.append($("ConstellioCreateRecordServlet.RecordServicesException", e.getMessage())); error = true; } if (!error) { responseWriter.append(record.getId()); } } private void createRecordsFromPostRequest(MetadataSchema metadataSchema, MetadataSchemaTypes metadataSchemaTypes, HttpServletRequest request, HttpServletResponse response, PrintWriter responseWriter) throws IOException { if (MediaType.APPLICATION_XML.equalsIgnoreCase(request.getContentType())) { Transaction transaction = new Transaction(); RecordServices recordServices = modelLayerFactory().newRecordServices(); Document domDocument; try { domDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(request.getInputStream()); } catch (ParserConfigurationException | SAXException e) { responseWriter.append(e.getMessage()); return; } NodeList recordsNodeList = domDocument.getDocumentElement().getChildNodes(); for (int i = 0, recordsCount = recordsNodeList.getLength(); i < recordsCount; i++) { Record record = recordServices.newRecordWithSchema(metadataSchema); NamedNodeMap recordNamedNodeMap = recordsNodeList.item(i).getAttributes(); for (Metadata metadata : metadataSchema.getMetadatas().onlyManuals()) { Node recordMetadataValue = recordNamedNodeMap.getNamedItem(metadata.getLocalCode()); if (recordMetadataValue != null) { setRecordMetadata(record, metadata, recordMetadataValue.getNodeValue(), metadataSchemaTypes); } } transaction.add(record); } try { recordServices.execute(transaction); } catch (RecordServicesException.ValidationException e) { responseWriter.append($(e.getErrors())); } catch (RecordServicesException e) { responseWriter.append($("ConstellioCreateRecordServlet.RecordServicesException", e.getMessage())); } responseWriter.append(Joiner.on(" ").join(transaction.getRecordIds())); } else { response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); } } private MetadataSchema getMetadataSchema(String schemaCode, MetadataSchemaTypes types, String collection, PrintWriter responseWriter) { MetadataSchema schema = null; if (StringUtils.isNotBlank(collection) && types != null) { try { schema = types.getSchema(schemaCode); } catch (Exception e) { responseWriter.append($("ConstellioCreateRecordServlet.InvalidSchema", schemaCode)); } } else { responseWriter.append($("ConstellioCreateRecordServlet.InvalidCollection", collection)); } return schema; } private ModelLayerFactory modelLayerFactory() { return ConstellioFactories.getInstance().getModelLayerFactory(); } private void setRecordMetadata(Record record, Metadata metadata, String metadataValue, MetadataSchemaTypes metadataSchemaTypes) { if (StringUtils.isNotBlank(metadataValue)) { if (metadata.isMultivalue()) { List<String> values = new ArrayList<>(Arrays.asList(metadataValue.split(MULTIVALUE_SEPARATOR))); record.set(metadata, values); } else { switch (metadata.getType()) { case DATE: record.set(metadata, LocalDate.parse(metadataValue)); break; case DATE_TIME: record.set(metadata, LocalDateTime.parse(metadataValue)); break; case STRING: case TEXT: record.set(metadata, metadataValue); case INTEGER: break; case NUMBER: break; case BOOLEAN: break; case REFERENCE: String schemaTypeCode = metadata.getAllowedReferences().getAllowedSchemaType(); MetadataSchemaType metadataSchemaType = metadataSchemaTypes.getSchemaType(schemaTypeCode); Metadata whereMetadata; if (schemaTypeCode.equals(User.SCHEMA_TYPE)) { whereMetadata = metadataSchemaType.getDefaultSchema().getMetadata(User.USERNAME); } else { whereMetadata = Schemas.CODE; } LogicalSearchCondition logicalSearchCondition = LogicalSearchQueryOperators.from(metadataSchemaType) .where(whereMetadata).isEqualTo(metadataValue); LogicalSearchQuery logicalSearchQuery = new LogicalSearchQuery(logicalSearchCondition) .setReturnedMetadatas(ReturnedMetadatasFilter.onlyMetadatas(Schemas.IDENTIFIER)); List<String> foundRecordIds = modelLayerFactory().newSearchServices().searchRecordIds(logicalSearchQuery); if (foundRecordIds.isEmpty()) { record.set(metadata, metadataValue); } else { record.set(metadata, foundRecordIds.get(0)); } break; case CONTENT: break; case STRUCTURE: break; case ENUM: break; } } } } }