/
akadnikov
/
CMIS_agent_Java
Обзор
Документация
Войти
/
akadnikov
/
CMIS_agent_Java
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/main/java/com/example/cmisagent/CMISService.java
335 строк
13 KB
akadnikov
Initial commit
25 фев 2026, 23:17
Верифицирован
25 фев 2026, 23:17
882add4
Код
Авторство
О чём код?
package com.example.cmisagent; import lombok.extern.slf4j.Slf4j; import org.apache.chemistry.opencmis.client.api.*; import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.SessionParameter; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.chemistry.opencmis.commons.enums.BindingType; import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** * Сервис для работы с CMIS репозиторием * Использует Apache Chemistry OpenCMIS */ @Slf4j @Service public class CMISService { private final Session session; private final CMISAgentConfig config; public CMISService(CMISAgentConfig config) { this.config = config; this.session = createSession(); } /** * Создание CMIS сессии */ private Session createSession() { Map<String, String> parameters = new HashMap<>(); parameters.put(SessionParameter.USER, config.getCmisUsername()); parameters.put(SessionParameter.PASSWORD, config.getCmisPassword()); parameters.put(SessionParameter.ATOMPUB_URL, config.getCmisUrl()); parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); parameters.put(SessionParameter.REPOSITORY_ID, config.getCmisRepositoryId()); SessionFactory sessionFactory = SessionFactoryImpl.newInstance(); Session session = sessionFactory.getRepositories(parameters).get(0).createSession(); log.info("CMIS session created successfully"); return session; } /** * Поиск документов по критериям */ public List<DocumentInfo> search(SearchCriteria criteria) { log.info("Searching documents with criteria: {}", criteria); try { String cmisQuery = buildCmisQuery(criteria); log.debug("Executing CMIS query: {}", cmisQuery); ItemIterable<QueryResult> results = session.query(cmisQuery, false); List<DocumentInfo> documents = new ArrayList<>(); for (QueryResult result : results) { documents.add(parseQueryResult(result)); } log.info("Found {} documents", documents.size()); return documents; } catch (Exception e) { log.error("Error searching documents", e); throw new CMISException("Error searching documents", e); } } /** * Построение CMIS-QL запроса */ private String buildCmisQuery(SearchCriteria criteria) { List<String> conditions = new ArrayList<>(); // Базовый поиск по имени/содержанию if (criteria.getQuery() != null && !criteria.getQuery().isEmpty()) { String safeQuery = criteria.getQuery().replace("'", "''"); conditions.add(String.format( "(cmis:name LIKE '%%%s%%' OR CONTAINS('%s'))", safeQuery, safeQuery )); } // Фильтр по типу документа if (criteria.getDocumentType() != null && !criteria.getDocumentType().isEmpty()) { String cmisType = mapDocumentType(criteria.getDocumentType()); conditions.add(String.format("cmis:objectTypeId = '%s'", cmisType)); } // Фильтр по дате создания if (criteria.getDateFrom() != null && !criteria.getDateFrom().isEmpty()) { conditions.add(String.format( "cmis:creationDate >= TIMESTAMP '%sT00:00:00.000Z'", criteria.getDateFrom() )); } if (criteria.getDateTo() != null && !criteria.getDateTo().isEmpty()) { conditions.add(String.format( "cmis:creationDate <= TIMESTAMP '%sT23:59:59.999Z'", criteria.getDateTo() )); } // Собираем запрос String whereClause = conditions.isEmpty() ? "1=1" : String.join(" AND ", conditions); return String.format(""" SELECT cmis:objectId, cmis:name, cmis:creationDate, cmis:createdBy, cmis:contentStreamLength, cmis:objectTypeId FROM cmis:document WHERE %s ORDER BY cmis:creationDate DESC """, whereClause).trim(); } /** * Маппинг типов документов */ private String mapDocumentType(String userType) { Map<String, String> typeMapping = Map.of( "договор", "D:contract:agreement", "контракт", "D:contract:agreement", "счет", "D:finance:invoice", "счет-фактура", "D:finance:invoice", "акт", "D:document:act", "отчет", "D:document:report", "протокол", "D:document:protocol" ); return typeMapping.getOrDefault(userType.toLowerCase(), "cmis:document"); } /** * Парсинг результата CMIS запроса */ private DocumentInfo parseQueryResult(QueryResult result) { return DocumentInfo.builder() .id(getPropertyValue(result, PropertyIds.OBJECT_ID)) .name(getPropertyValue(result, PropertyIds.NAME)) .type(getPropertyValue(result, PropertyIds.OBJECT_TYPE_ID)) .created(getPropertyValue(result, PropertyIds.CREATION_DATE)) .author(getPropertyValue(result, PropertyIds.CREATED_BY)) .size(parseSize(getPropertyValue(result, PropertyIds.CONTENT_STREAM_LENGTH))) .build(); } /** * Получение значения свойства из результата */ private String getPropertyValue(QueryResult result, String propertyId) { PropertyData<?> property = result.getPropertyById(propertyId); return property != null && property.getFirstValue() != null ? property.getFirstValue().toString() : "N/A"; } /** * Парсинг размера файла */ private long parseSize(String sizeStr) { try { return Long.parseLong(sizeStr); } catch (NumberFormatException e) { return 0L; } } /** * Получение метаданных документа */ public DocumentMetadata getMetadata(String documentId) { log.info("Getting metadata for document: {}", documentId); try { CmisObject cmisObject = session.getObject(documentId); if (!(cmisObject instanceof Document)) { throw new CMISException("Object is not a document: " + documentId); } Document document = (Document) cmisObject; // Основные свойства Map<String, Object> customProperties = new HashMap<>(); document.getProperties().forEach(property -> { String id = property.getId(); if (!id.startsWith("cmis:")) { customProperties.put(id, property.getFirstValue()); } }); return DocumentMetadata.builder() .id(document.getId()) .name(document.getName()) .type(document.getType().getId()) .created(formatDate(document.getCreationDate())) .modified(formatDate(document.getLastModificationDate())) .author(document.getCreatedBy()) .lastModifiedBy(document.getLastModifiedBy()) .size(document.getContentStreamLength()) .mimeType(document.getContentStreamMimeType()) .version(document.getVersionLabel()) .customProperties(customProperties) .build(); } catch (CmisObjectNotFoundException e) { log.warn("Document not found: {}", documentId); return null; } catch (Exception e) { log.error("Error getting document metadata", e); throw new CMISException("Error getting document metadata", e); } } /** * Форматирование даты */ private String formatDate(GregorianCalendar calendar) { if (calendar == null) return "N/A"; LocalDateTime dateTime = LocalDateTime.ofInstant( calendar.toInstant(), calendar.getTimeZone().toZoneId() ); return dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } /** * Получение содержимого документа */ public DocumentContent getContent(String documentId) { log.info("Getting content for document: {}", documentId); try { CmisObject cmisObject = session.getObject(documentId); if (!(cmisObject instanceof Document)) { throw new CMISException("Object is not a document: " + documentId); } Document document = (Document) cmisObject; ContentStream contentStream = document.getContentStream(); if (contentStream == null) { log.warn("Document has no content stream: {}", documentId); return null; } String text = extractText(contentStream, document.getContentStreamMimeType()); return DocumentContent.builder() .documentId(documentId) .name(document.getName()) .mimeType(document.getContentStreamMimeType()) .text(text) .build(); } catch (CmisObjectNotFoundException e) { log.warn("Document not found: {}", documentId); return null; } catch (Exception e) { log.error("Error getting document content", e); throw new CMISException("Error getting document content", e); } } /** * Извлечение текста из различных форматов */ private String extractText(ContentStream contentStream, String mimeType) { try { // Для текстовых файлов if (mimeType != null && mimeType.startsWith("text/")) { BufferedReader reader = new BufferedReader( new InputStreamReader(contentStream.getStream(), StandardCharsets.UTF_8) ); return reader.lines().collect(Collectors.joining("\n")); } // Для PDF - здесь нужно использовать Apache PDFBox if ("application/pdf".equals(mimeType)) { return extractTextFromPdf(contentStream); } // Для DOCX - здесь нужно использовать Apache POI if ("application/vnd.openxmlformats-officedocument.wordprocessingml.document".equals(mimeType)) { return extractTextFromDocx(contentStream); } log.warn("Unsupported mime type for text extraction: {}", mimeType); return "[Извлечение текста не поддерживается для типа: " + mimeType + "]"; } catch (Exception e) { log.error("Error extracting text", e); return "[Ошибка извлечения текста: " + e.getMessage() + "]"; } } /** * Извлечение текста из PDF (заглушка) * В реальном проекте использовать Apache PDFBox */ private String extractTextFromPdf(ContentStream contentStream) { // TODO: Реализовать с помощью Apache PDFBox // PDDocument document = PDDocument.load(contentStream.getStream()); // PDFTextStripper stripper = new PDFTextStripper(); // return stripper.getText(document); return "[PDF text extraction - требуется Apache PDFBox]"; } /** * Извлечение текста из DOCX (заглушка) * В реальном проекте использовать Apache POI */ private String extractTextFromDocx(ContentStream contentStream) { // TODO: Реализовать с помощью Apache POI // XWPFDocument document = new XWPFDocument(contentStream.getStream()); // XWPFWordExtractor extractor = new XWPFWordExtractor(document); // return extractor.getText(); return "[DOCX text extraction - требуется Apache POI]"; } }