diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts index ad34702c5489ad0eb2049774da49fa83014daf1d..ff91911dd499d2a33de029e1f59b7b16efb53a74 100644 --- a/smp-angular/src/app/app.module.ts +++ b/smp-angular/src/app/app.module.ts @@ -147,6 +147,7 @@ import {DnsToolsService} from "./tools/dns-tools/dns-tools.service"; import { DnsQueryPanelComponent } from "./tools/dns-tools/dns-query-panel/dns-query-panel.component"; +import {ResourceMetadataService} from "./common/services/resource-metadata.service"; @NgModule({ @@ -296,6 +297,7 @@ import { GlobalLookups, HttpEventService, NavigationService, + ResourceMetadataService, SecurityEventService, SecurityService, SmlIntegrationService, diff --git a/smp-angular/src/app/common/services/resource-metadata.service.ts b/smp-angular/src/app/common/services/resource-metadata.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..1f71f36e493c22f46a8b0062b682bfe1ef624d11 --- /dev/null +++ b/smp-angular/src/app/common/services/resource-metadata.service.ts @@ -0,0 +1,15 @@ +import {Injectable} from "@angular/core"; +import {HttpClient} from "@angular/common/http"; +import {Observable} from "rxjs"; +import {SmpConstants} from "../../smp.constants"; +import {ResourceMetadataRo} from "../model/resource-metadata-ro.model"; + +@Injectable() +export class ResourceMetadataService { + + constructor(private http: HttpClient) { } + + getResourceMetadata$(): Observable<ResourceMetadataRo> { + return this.http.get<ResourceMetadataRo>(SmpConstants.REST_PUBLIC_SEARCH_RESOURCE_METADATA); + } +} diff --git a/smp-angular/src/app/resource-search/resource-search.component.html b/smp-angular/src/app/resource-search/resource-search.component.html index ecb41d8f46c089142d7cb91a290b1658bfbc69de..666087b9afc7d62c75926866b52a13cd6bb4faea 100644 --- a/smp-angular/src/app/resource-search/resource-search.component.html +++ b/smp-angular/src/app/resource-search/resource-search.component.html @@ -16,7 +16,6 @@ href="{{contextPath}}{{createResourceURL(row)}}">Open URL</a> </ng-template> - <ng-template #searchPanel> <div style="display: flex;flex-direction: row;width: 100%"> <mat-form-field class="smp-data-panel-field"> @@ -30,15 +29,37 @@ <input matInput name="ResourceScheme" [(ngModel)]="filter.participantScheme" #messageId="ngModel" id="ResourceScheme"> </mat-form-field> + <mat-form-field class="smp-data-panel-field"> + <mat-label>Domain</mat-label> + <mat-select placeholder="Domain" + matTooltip="Domain" + id="Domain" + [(value)]="filter.domainCode"> + <mat-option *ngFor="let domainCode of domainList" + [value]="domainCode"> + {{domainCode}} + </mat-option> + </mat-select> + </mat-form-field> + <mat-form-field class="smp-data-panel-field"> + <mat-label>Document Type</mat-label> + <mat-select placeholder="Document type" + matTootip="Document type" + id="DocumentType" + [(value)]="filter.documentType"> + <mat-option *ngFor="let documentType of documentTypeList" + [value]="documentType"> + {{documentType}} + </mat-option> + </mat-select> + </mat-form-field> </div> </ng-template> - <ng-template #additionalToolButtons> </ng-template> <ng-template #tableRowDetailContainer let-row="row"> - <div *ngIf="row.serviceMetadata.length===0" style="padding-left:20px;"> No subresources </div> @@ -64,8 +85,6 @@ URL</a> </ng-template> </ngx-datatable> - </div> </ng-template> - </smp-search-table> diff --git a/smp-angular/src/app/resource-search/resource-search.component.ts b/smp-angular/src/app/resource-search/resource-search.component.ts index 9f78ec7bf591319e08d44bea282174a5eddacaea..1e96a58c9f874ad0fbf5801173d598b7b6e6918f 100644 --- a/smp-angular/src/app/resource-search/resource-search.component.ts +++ b/smp-angular/src/app/resource-search/resource-search.component.ts @@ -18,6 +18,8 @@ import {GlobalLookups} from "../common/global-lookups"; import {SearchTableComponent} from "../common/search-table/search-table.component"; import {ResourceSearchRo} from "./resource-search-ro.model"; import {SubresourceSearchRo} from "./subresource-search-ro.model"; +import {ResourceMetadataService} from "../common/services/resource-metadata.service"; +import {ResourceMetadataRo} from "../common/model/resource-metadata-ro.model"; @Component({ templateUrl: './resource-search.component.html', @@ -34,19 +36,29 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView filter: any = {}; contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s baseUrl: string; + domainList: string[]; + documentTypeList: string[]; constructor(protected lookups: GlobalLookups, protected http: HttpClient, - protected alertService: - AlertMessageService, + protected alertService: AlertMessageService, public dialog: MatDialog, - private changeDetector: ChangeDetectorRef) { + private changeDetector: ChangeDetectorRef, + private resourceMetadataService: ResourceMetadataService) { this.baseUrl = SmpConstants.REST_PUBLIC_SEARCH_RESOURCE; } - ngOnInit(): void { - this.resourceSearchController = new ResourceSearchController(this.dialog); + ngOnInit() { + this.resourceMetadataService.getResourceMetadata$().subscribe({ + next: (value: ResourceMetadataRo) => { + this.domainList = value.availableDomains || []; + this.documentTypeList = value.availableDocumentTypes || []; + + this.resourceSearchController = new ResourceSearchController(this.dialog); + }, + error: (err) => this.alertService.exception('Error occurred while retrieving the resource metadata', err) + }); } initColumns(): void { @@ -82,6 +94,13 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView resizable: 'true', showInitially: true, }, + { + name: 'Document type', + prop: 'documentType', + width: 450, + resizable: 'true', + showInitially: true, + }, { cellTemplate: this.rowSMPUrlLinkAction, name: 'Resource URL', @@ -103,23 +122,18 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView } createResourceURL(row: ResourceSearchRo) { - return (!row?.domainCode? "" : row.domainCode+ '/') + (!row?.resourceDefUrlSegment?"" : row.resourceDefUrlSegment + '/') + encodeURIComponent((!row.participantScheme ? '' : row.participantScheme) + '::' + row.participantIdentifier); } createServiceMetadataURL(row: ResourceSearchRo, rowSMD: SubresourceSearchRo) { - return this.createResourceURL(row) + '/' + rowSMD.subresourceDefUrlSegment + '/' + encodeURIComponent((!rowSMD.documentIdentifierScheme ? '' : rowSMD.documentIdentifierScheme) + '::' + rowSMD.documentIdentifier); } - - details(row: any) { this.resourceSearchController.showDetails(row); - } } diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts index 05cf40aeaf96ee9e24636f2a6ea4894da79441be..5d8546138acb5045e2ed15605839eb7c9e9bcf78 100644 --- a/smp-angular/src/app/smp.constants.ts +++ b/smp-angular/src/app/smp.constants.ts @@ -19,6 +19,7 @@ export class SmpConstants { public static readonly PATH_ACTION_UPDATE_RESOURCE_TYPES = 'update-resource-types'; public static readonly PATH_ACTION_UPDATE_SML_INTEGRATION = 'update-sml-integration-data'; public static readonly PATH_ACTION_GENERATE_DNS_QUERY : string = 'generate-dns-query'; + /* URL variables */ public static readonly PATH_PARAM_ENC_USER_ID = '{user-id}'; public static readonly PATH_PARAM_ENC_DOMAIN_ID = '{domain-id}'; @@ -46,7 +47,6 @@ export class SmpConstants { public static readonly PATH_RESOURCE_TYPE_DOCUMENT = 'document'; public static readonly PATH_QUERY_FILTER_TYPE = 'type' - //------------------------------ // public endpoints public static readonly REST_PUBLIC = 'public/rest/'; @@ -72,6 +72,7 @@ export class SmpConstants { /* Public services */ public static readonly REST_PUBLIC_SEARCH_RESOURCE = SmpConstants.REST_PUBLIC + SmpConstants.PATH_ACTION_SEARCH; + public static readonly REST_PUBLIC_SEARCH_RESOURCE_METADATA = SmpConstants.REST_PUBLIC + SmpConstants.PATH_ACTION_SEARCH + "/metadata"; public static readonly REST_PUBLIC_DOMAIN = SmpConstants.REST_PUBLIC + SmpConstants.PATH_RESOURCE_TYPE_DOMAIN; public static readonly REST_PUBLIC_DNS_TOOLS = SmpConstants.REST_PUBLIC + SmpConstants.PATH_DNS_TOOLS; public static readonly REST_PUBLIC_DNS_TOOLS_GEN_QUERY: string = SmpConstants.REST_PUBLIC_DNS_TOOLS + '/' + SmpConstants.PATH_ACTION_GENERATE_DNS_QUERY; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java index 860bde5ab9bcaddae2715f4909d074143c7e735c..3bddc435ed609182605fef6282848c9852e6db45 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java @@ -118,4 +118,15 @@ public class DocumentDao extends BaseDao<DBDocument> { query.setParameter(PARAM_SUBRESOURCE_ID, subresource.getId()); return query.getResultList(); } + + /** + * Returns document type records from smp_domain table. + * + * @return the list of document types from smp_domain table + */ + public List<String> getAllDocumentTypes() { + TypedQuery<String> query = memEManager.createNamedQuery(QUERY_DOCUMENT_ALL_TYPES, String.class); + return query.getResultList(); + } + } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java index 4c739082a84a067ece0f8903bcc302563b7193eb..a31bc1cb564aa80c42a69afe66e36211449e9c60 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java @@ -77,6 +77,16 @@ public class DomainDao extends BaseDao<DBDomain> { return query.getResultList(); } + /** + * Returns domain code records from smp_domain table. + * + * @return the list of domain codes from smp_domain table + */ + public List<String> getAllDomainCodes() { + TypedQuery<String> query = memEManager.createNamedQuery(QUERY_DOMAIN_ALL_CODES, String.class); + return query.getResultList(); + } + public Optional<DBDomain> getFirstDomain() { TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_ALL, DBDomain.class); diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java index 7d77d21af838d2b0dcc9a0b8bcc45b32103cf751..96d7d1494b8179e3ef1037bebe190663a0af41f9 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java @@ -30,6 +30,7 @@ public class QueryNames { public static final String QUERY_DOMAIN_ALL = "DBDomain.getAll"; + public static final String QUERY_DOMAIN_ALL_CODES = "DBDomain.getAllCodes"; public static final String QUERY_DOMAIN_CODE = "DBDomain.getDomainByCode"; public static final String QUERY_DOMAIN_SMP_SML_ID = "DBDomain.getDomainBySmlSmpId"; @@ -120,6 +121,7 @@ public class QueryNames { public static final String QUERY_RESOURCE_DEF_BY_IDENTIFIER_EXTENSION = "DBExtResourceDef.getByIdentifierExtension"; public static final String QUERY_DOCUMENT_FOR_RESOURCE = "DBDocument.getForResource"; + public static final String QUERY_DOCUMENT_ALL_TYPES = "DBDocument.getAllTypes"; public static final String QUERY_DOCUMENT_VERSION_CURRENT_FOR_RESOURCE = "DBDocumentVersion.forCurrentForResource"; public static final String QUERY_DOCUMENT_VERSION_LIST_FOR_RESOURCE = "DBDocumentVersion.getAllForResource"; @@ -189,6 +191,7 @@ public class QueryNames { public static final String PARAM_DOMAIN_IDS = "domain_ids"; public static final String PARAM_DOCUMENT_ID = "document_id"; + public static final String PARAM_DOCUMENT_TYPE = "document_type"; public static final String PARAM_GROUP_ID = "group_id"; public static final String PARAM_GROUP_IDS = "group_ids"; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java index 7de33a2b32fa6df481bfd4d5c6fa222343910157..93b25d5d66497fdd9cba54d4bb66bf05a981927a 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java @@ -33,9 +33,11 @@ import org.springframework.transaction.annotation.Transactional; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; +import javax.persistence.Tuple; import javax.persistence.TypedQuery; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; @@ -49,6 +51,39 @@ public class ResourceDao extends BaseDao<DBResource> { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ResourceDao.class); + public static final class DBResourceWrapper { + + private final DBResource dbResource; + + private final String domainCode; + + private final String documentType; + + private final String urlSegment; + + public DBResourceWrapper(DBResource dbResource, String domainCode, String documentType, String urlSegment) { + this.dbResource = dbResource; + this.domainCode = domainCode; + this.documentType = documentType; + this.urlSegment = urlSegment; + } + + public DBResource getDbResource() { + return dbResource; + } + + public String getDomainCode() { + return domainCode; + } + + public String getDocumentType() { + return documentType; + } + + public String getUrlSegment() { + return urlSegment; + } + } /** * The method returns DBResource for the participant identifier, domain, and resource type. If the resource does not exist, it returns an empty Option. @@ -76,7 +111,6 @@ public class ResourceDao extends BaseDao<DBResource> { } } - public Long getResourcesForFilterCount(DBResourceFilter resourceFilter) { LOG.debug("Get resources count for filter [{}]", resourceFilter); @@ -110,10 +144,10 @@ public class ResourceDao extends BaseDao<DBResource> { return query.getResultList(); } - public List<DBResource> getPublicResourcesSearch(int iPage, int iPageSize, DBUser user, String schema, String identifier) { + public List<DBResourceWrapper> getPublicResourcesSearch(int iPage, int iPageSize, DBUser user, String schema, String identifier, String domainCode, String documentType) { LOG.debug("Get resources list for user [{}], search scheme [{}] and search value [{}]", user, schema, identifier); - TypedQuery<DBResource> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER, DBResource.class); + TypedQuery<Tuple> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER, Tuple.class); if (iPageSize > -1 && iPage > -1) { query.setFirstResult(iPage * iPageSize); } @@ -123,17 +157,28 @@ public class ResourceDao extends BaseDao<DBResource> { query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null); query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema) ? null : StringUtils.wrapIfMissing(schema, "%")); query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier) ? null : StringUtils.wrapIfMissing(identifier, "%")); - - return query.getResultList(); + query.setParameter(PARAM_DOMAIN_CODE, StringUtils.defaultIfBlank(domainCode, null)); + query.setParameter(PARAM_DOCUMENT_TYPE, StringUtils.defaultIfBlank(documentType, null)); + List<Tuple> resultList = query.getResultList(); + + return resultList.stream().map(tuple -> { + DBResource resource = tuple.get(0, DBResource.class); + String domainCodeValue = tuple.get("domainCode").toString(); + String documentTypeValue = tuple.get("documentType").toString(); + String urlSegment = tuple.get("urlSegment").toString(); + return new DBResourceWrapper(resource, domainCodeValue, documentTypeValue, urlSegment); + }).collect(Collectors.toList()); } - public Long getPublicResourcesSearchCount(DBUser user, String schema, String identifier) { + public Long getPublicResourcesSearchCount(DBUser user, String schema, String identifier, String domainCode, String documentType) { LOG.debug("Get resources count for user [{}], search scheme [{}] and search value [{}]", user, schema, identifier); TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER_COUNT, Long.class); query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null); query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema) ? null : StringUtils.wrapIfMissing(schema, "%")); query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier) ? null : StringUtils.wrapIfMissing(identifier, "%")); + query.setParameter(PARAM_DOMAIN_CODE, StringUtils.defaultIfBlank(domainCode, null)); + query.setParameter(PARAM_DOCUMENT_TYPE, StringUtils.defaultIfBlank(documentType, null)); return query.getSingleResult(); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java index c826b4c6b7efc6fa8b801a4e1b4811b3284111e9..be3c09fdf4c3342217774d321faf7701b0758bb6 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java @@ -41,6 +41,7 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; indexes = {@Index(name = "SMP_DOM_UNIQ_CODE_IDX", columnList = "DOMAIN_CODE", unique = true) }) @NamedQuery(name = QUERY_DOMAIN_ALL, query = "SELECT d FROM DBDomain d order by d.id asc") +@NamedQuery(name = QUERY_DOMAIN_ALL_CODES, query = "SELECT DISTINCT d.domainCode FROM DBDomain d") @NamedQuery(name = QUERY_DOMAIN_CODE, query = "SELECT d FROM DBDomain d WHERE d.domainCode = :domain_code") @NamedQuery(name = QUERY_DOMAIN_SMP_SML_ID, query = "SELECT d FROM DBDomain d WHERE lower(d.smlSmpId) = lower(:sml_smp_id)") diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java index b4f9dd9db96f8ed20935abc050035a0c0fdeba9f..debc6251181dce6abb37d3d046983106ea89d18c 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOCUMENT_ALL_TYPES; import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOCUMENT_FOR_RESOURCE; /** @@ -47,6 +48,7 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOCUMENT_FOR_ @org.hibernate.annotations.Table(appliesTo = "SMP_DOCUMENT", comment = "SMP document entity for resources and subresources") @NamedQueries({ @NamedQuery(name = QUERY_DOCUMENT_FOR_RESOURCE, query = "SELECT d FROM DBResource r JOIN r.document d WHERE r.id =:resource_id"), + @NamedQuery(name = QUERY_DOCUMENT_ALL_TYPES, query = "SELECT DISTINCT d.name FROM DBDocument d"), }) public class DBDocument extends BaseEntity { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBDocument.class); diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java index 34c01df66b259af7a2c23ddc272fb44d2505966d..6890502a75ec22c450761196c793d3351c5d51ea 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java @@ -99,7 +99,9 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; " AND (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier )" + " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme) order by r.identifierScheme, r.identifierValue" ) -@NamedQuery(name = QUERY_RESOURCE_ALL_FOR_USER, query = "SELECT DISTINCT r FROM DBResource r LEFT JOIN DBResourceMember rm ON r.id = rm.resource.id WHERE " + +@NamedQuery(name = QUERY_RESOURCE_ALL_FOR_USER, query = "SELECT DISTINCT r, r.domainResourceDef.domain.domainCode as domainCode, " + + " r.domainResourceDef.resourceDef.urlSegment as urlSegment, r.document.name as documentType " + + "FROM DBResource r LEFT JOIN DBResourceMember rm ON r.id = rm.resource.id WHERE " + " (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier) " + " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme) " + " AND ( :user_id IS NOT NULL AND rm.user.id = :user_id " + @@ -112,8 +114,10 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; " OR (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " + " OR (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.domain.id = r.group.domain.id) > 0 " + " OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.domain.id = r.group.domain.id) > 0 " + - ")))"+ - "order by r.identifierScheme, r.identifierValue" + "))) " + + " AND (:domain_code IS NULL OR r.domainResourceDef.domain.domainCode = :domain_code) " + + " AND (:document_type IS NULL OR r.document.name = :document_type) " + + " ORDER BY r.identifierScheme, r.identifierValue" ) @NamedQuery(name = QUERY_RESOURCE_ALL_FOR_USER_COUNT, query = "SELECT count(distinct r.id) FROM DBResource r LEFT JOIN DBResourceMember rm ON r.id = rm.resource.id WHERE " + " (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier) " + @@ -128,7 +132,9 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; " OR (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " + " OR (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.domain.id = r.group.domain.id) > 0 " + " OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.domain.id = r.group.domain.id) > 0 " + - ")))" + "))) " + + " AND (:domain_code IS NULL OR r.domainResourceDef.domain.domainCode = :domain_code) " + + " AND (:document_type IS NULL OR r.document.name = :document_type) " ) public class DBResource extends BaseEntity { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java index cdf665c99c48dbd8084752d22fa950d6eda06c96..cf080ac997fa8bccabf073e016f4fe716357050c 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java @@ -36,6 +36,7 @@ public class ServiceGroupSearchRO extends BaseRO { private Long id; private String domainCode; + private String documentType; private String resourceDefUrlSegment; private String participantIdentifier; private String participantScheme; @@ -85,4 +86,12 @@ public class ServiceGroupSearchRO extends BaseRO { public List<ServiceMetadataRO> getServiceMetadata() { return lstServiceMetadata; } + + public String getDocumentType() { + return documentType; + } + + public void setDocumentType(String documentType) { + this.documentType = documentType; + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java index df80781d4f0f0e608b82c01b74bbeea448cd2bb1..71aa71b6a5cc7f16f909cf0cd3dc4616ccb9c53f 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java @@ -18,12 +18,10 @@ */ package eu.europa.ec.edelivery.smp.services.ui; -import eu.europa.ec.edelivery.smp.data.dao.BaseDao; -import eu.europa.ec.edelivery.smp.data.dao.DomainDao; -import eu.europa.ec.edelivery.smp.data.dao.ResourceDao; -import eu.europa.ec.edelivery.smp.data.dao.UserDao; +import eu.europa.ec.edelivery.smp.data.dao.*; import eu.europa.ec.edelivery.smp.data.model.doc.DBResource; import eu.europa.ec.edelivery.smp.data.model.user.DBUser; +import eu.europa.ec.edelivery.smp.data.ui.ResourceMetadataResult; import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupSearchRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; @@ -31,7 +29,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import eu.europa.ec.edelivery.smp.services.ui.filters.ResourceFilter; import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.convert.ConversionService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,14 +40,23 @@ import java.util.List; public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGroupSearchRO> { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIResourceSearchService.class); - @Autowired - DomainDao domainDao; + private final DomainDao domainDao; - @Autowired - ResourceDao resourceDao; + private final ResourceDao resourceDao; - @Autowired - UserDao userDao; + private final UserDao userDao; + + private final DocumentDao documentDao; + + private final ConversionService conversionService; + + public UIResourceSearchService(DomainDao domainDao, ResourceDao resourceDao, UserDao userDao, DocumentDao documentDao, ConversionService conversionService) { + this.domainDao = domainDao; + this.resourceDao = resourceDao; + this.userDao = userDao; + this.documentDao = documentDao; + this.conversionService = conversionService; + } @Override @@ -77,7 +84,7 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr sg.setPageSize(pageSize); DBUser user = SessionSecurityUtils.getSessionUserDetails() != null ? SessionSecurityUtils.getSessionUserDetails().getUser() : null; - long iCnt = resourceDao.getPublicResourcesSearchCount(user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike()); + long iCnt = resourceDao.getPublicResourcesSearchCount(user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike(), filter.getDomainCode(), filter.getDocumentType()); sg.setCount(iCnt); if (iCnt > 0) { @@ -87,10 +94,10 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr sg.setPage(page); // go back for a page iStartIndex = pageSize < 0 ? -1 : page * pageSize; } - List<DBResource> lst = resourceDao.getPublicResourcesSearch(page, pageSize, user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike()); + List<ResourceDao.DBResourceWrapper> lst = resourceDao.getPublicResourcesSearch(page, pageSize, user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike(), filter.getDomainCode(), filter.getDocumentType()); List<ServiceGroupSearchRO> lstRo = new ArrayList<>(); - for (DBResource resource : lst) { - ServiceGroupSearchRO serviceGroupRo = convertToRo(resource); + for (ResourceDao.DBResourceWrapper resource : lst) { + ServiceGroupSearchRO serviceGroupRo = convert(resource); serviceGroupRo.setIndex(iStartIndex++); lstRo.add(serviceGroupRo); } @@ -102,19 +109,20 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr /** * Convert Database object to Rest object for UI * - * @param resource - database entity + * @param resource - database entity wrapper * @return ServiceGroupRO */ - public ServiceGroupSearchRO convertToRo(DBResource resource) { + private ServiceGroupSearchRO convert(ResourceDao.DBResourceWrapper resource) { ServiceGroupSearchRO serviceGroupRo = new ServiceGroupSearchRO(); - serviceGroupRo.setId(resource.getId()); - serviceGroupRo.setDomainCode(resource.getDomainResourceDef().getDomain().getDomainCode()); - serviceGroupRo.setResourceDefUrlSegment(resource.getDomainResourceDef().getResourceDef().getUrlSegment()); - serviceGroupRo.setParticipantIdentifier(resource.getIdentifierValue()); - serviceGroupRo.setParticipantScheme(resource.getIdentifierScheme()); + serviceGroupRo.setId(resource.getDbResource().getId()); + serviceGroupRo.setDomainCode(resource.getDomainCode()); + serviceGroupRo.setDocumentType(resource.getDocumentType()); + serviceGroupRo.setResourceDefUrlSegment(resource.getUrlSegment()); + serviceGroupRo.setParticipantIdentifier(resource.getDbResource().getIdentifierValue()); + serviceGroupRo.setParticipantScheme(resource.getDbResource().getIdentifierScheme()); - resource.getSubresources().forEach(subresource -> { + resource.getDbResource().getSubresources().forEach(subresource -> { ServiceMetadataRO smdro = new ServiceMetadataRO(); smdro.setSubresourceDefUrlSegment(subresource.getSubresourceDef().getUrlSegment()); smdro.setDocumentIdentifier(subresource.getIdentifierValue()); @@ -124,4 +132,10 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr return serviceGroupRo; } + + public ResourceMetadataResult getResourceMetadata() { + List<String> domainCodes = domainDao.getAllDomainCodes(); + List<String> documentTypes = documentDao.getAllDocumentTypes(); + return new ResourceMetadataResult(domainCodes, documentTypes); + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/filters/ResourceFilter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/filters/ResourceFilter.java index 79e0417160192d7395c1e30d15727437fcb0e9f1..d4da3d9c620ba33a5c5d59454c2782af10ce109d 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/filters/ResourceFilter.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/filters/ResourceFilter.java @@ -27,6 +27,7 @@ public class ResourceFilter { private DBUser owner; private DBDomain domain; + private String documentType; public String getIdentifierValueLike() { return identifierValue; @@ -59,4 +60,19 @@ public class ResourceFilter { public void setDomain(DBDomain domain) { this.domain = domain; } + + public String getDomainCode() { + if (domain == null) { + return null; + } + return domain.getDomainCode(); + } + + public String getDocumentType() { + return documentType; + } + + public void setDocumentType(String documentType) { + this.documentType = documentType; + } } diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java index 9be8653f624167a0a0bba10742198ceeca32a48f..cbab7cad2186763c8e2139f64b9c6e33b6a94ed0 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java @@ -62,44 +62,44 @@ class ResourceDaoSearchTest extends AbstractBaseDao { assertEquals(8, allResources.size()); // only one group is public - - List<DBResource> result = testInstance.getPublicResourcesSearch(-1, -1, null, null, null); + List<ResourceDao.DBResourceWrapper> result = testInstance.getPublicResourcesSearch(-1, -1, null, null, null, null, null); assertEquals(1, result.size()); assertResources(result, "1-1-1::pubPubPub"); // user1 (admin) and user2 (viewer) are members of all resources - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser2(), null, null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser2(), null, null, null, null); assertEquals(8, result.size()); - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), null, "pubPub"); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), null, "pubPub", null, null); assertEquals(2, result.size()); - result.forEach(resource -> assertThat(resource.getIdentifierValue(), CoreMatchers.containsString("pubPub"))); + result.forEach(resource -> assertThat(resource.getDbResource().getIdentifierValue(), CoreMatchers.containsString("pubPub"))); - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), "1-1", null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), "1-1", null, null, null); assertEquals(1, result.size()); - result.forEach(resource -> assertThat(resource.getIdentifierScheme(), CoreMatchers.containsString("1-1"))); + result.forEach(resource -> assertThat(resource.getDbResource().getIdentifierScheme(), CoreMatchers.containsString("1-1"))); - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), "1-1", "priv"); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser1(), "1-1", "priv", null, null); assertEquals(0, result.size()); - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser2(), null, null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser2(), null, null, null, null); assertEquals(8, result.size()); // user3 is direct member of private domain - can see only public resource on public groups - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser3(), null, null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser3(), null, null, null, null); assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub"); // user4 is direct member of private group in private domain - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser4(), null, null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser4(), null, null, null, null); assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub", "7-7-7::privPrivPub"); // user5 is direct member of private resource in private group in private domain - result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser5(), null, null); + result = testInstance.getPublicResourcesSearch(-1, -1, testUtilsDao.getUser5(), null, null, null, null); assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub", "7-7-7::privPrivPub", "8-8-8::privPrivPriv"); } - public void assertResources(List<DBResource> result, String... resourceIdentifiers) { - List<String> resultIdentifiers = result.stream().map(val -> val.getIdentifierScheme() + "::" + val.getIdentifierValue()).collect(Collectors.toList()); + public void assertResources(List<ResourceDao.DBResourceWrapper> result, String... resourceIdentifiers) { + List<String> resultIdentifiers = result.stream().map(val -> val.getDbResource().getIdentifierScheme() + "::" + val.getDbResource().getIdentifierValue()).collect(Collectors.toList()); System.out.println(resultIdentifiers); assertArrayEquals(resourceIdentifiers, resultIdentifiers.stream().toArray()); } @@ -110,35 +110,35 @@ class ResourceDaoSearchTest extends AbstractBaseDao { assertEquals(8, allResources.size()); // only one group is public - - Long result = testInstance.getPublicResourcesSearchCount(null, null, null); + Long result = testInstance.getPublicResourcesSearchCount(null, null, null, null, null); assertEquals(1, result.intValue()); // user1 (admin) and user2 (viewer) are members of all resources - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), null, null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), null, null, null, null); assertEquals(8, result.intValue()); - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), null, "pubPub"); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), null, "pubPub", null, null); assertEquals(2, result.intValue()); - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), "1-1", null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), "1-1", null, null, null); assertEquals(1, result.intValue()); - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), "1-1", "priv"); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), "1-1", "priv", null, null); assertEquals(0, result.intValue()); - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser2(), null, null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser2(), null, null, null, null); assertEquals(8, result.intValue()); // user3 is direct member of private domain - can see only public resource on public groups - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser3(), null, null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser3(), null, null, null, null); assertEquals(2, result.intValue()); // user4 is direct member of private group in private domain - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser4(), null, null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser4(), null, null, null, null); assertEquals(3, result.intValue()); // user5 is direct member of private resource in private group in private domain - result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser5(), null, null); + result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser5(), null, null, null, null); assertEquals(4, result.intValue()); } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java index 806dc4554729934e79bc17fce19f2a74e61d024d..9b06aa6109d3390bec5d374b04b4d2499aa9e6f5 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java @@ -132,6 +132,7 @@ public class ResourceConstants { public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_GENERATE = SUB_CONTEXT_PATH_EDIT_DOCUMENT_GET_SUBRESOURCE + URL_PATH_SEPARATOR + PATH_ACTION_GENERATE; // public public static final String CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT = CONTEXT_PATH_PUBLIC + PATH_ACTION_SEARCH; + public static final String CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT_METADATA = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT + "/metadata"; public static final String CONTEXT_PATH_PUBLIC_DOMAIN = CONTEXT_PATH_PUBLIC + PATH_RESOURCE_TYPE_DOMAIN; public static final String CONTEXT_PATH_PUBLIC_APPLICATION = CONTEXT_PATH_PUBLIC + "application"; public static final String CONTEXT_PATH_PUBLIC_USER = CONTEXT_PATH_PUBLIC + "user"; @@ -167,6 +168,7 @@ public class ResourceConstants { public static final String PARAM_QUERY_DOMAIN_CODE = "domainCode"; public static final String PARAM_QUERY_USER = "user"; public static final String PARAM_QUERY_PROPERTY = "property"; + public static final String PARAM_QUERY_DOCUMENT_TYPE = "documentType"; private ResourceConstants() { } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java index b53cddeacf4c9de485b77740a5fa6ff35384028b..6d9b814db7ec094997e546401b62aa238b392b2a 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java @@ -18,8 +18,8 @@ */ package eu.europa.ec.edelivery.smp.ui.external; - import eu.europa.ec.edelivery.smp.data.dao.DomainDao; +import eu.europa.ec.edelivery.smp.data.ui.ResourceMetadataResult; import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupSearchRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.logging.SMPLogger; @@ -45,7 +45,7 @@ import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*; * @since 4.1 */ @RestController -@RequestMapping(path = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT) +@RequestMapping(produces = MimeTypeUtils.APPLICATION_JSON_VALUE) public class SearchResource { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SearchResource.class); @@ -58,7 +58,7 @@ public class SearchResource { this.domainDao = domainDao; } - @GetMapping(produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + @GetMapping(path = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT) public ServiceResult<ServiceGroupSearchRO> getServiceGroupList( @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page, @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize, @@ -66,24 +66,32 @@ public class SearchResource { @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType, @RequestParam(value = PARAM_QUERY_PARTC_ID, required = false) String participantIdentifier, @RequestParam(value = PARAM_QUERY_PARTC_SCHEME, required = false) String participantScheme, - @RequestParam(value = PARAM_QUERY_DOMAIN_CODE, required = false) String domainCode) { + @RequestParam(value = PARAM_QUERY_DOMAIN_CODE, required = false) String domainCode, + @RequestParam(value = PARAM_QUERY_DOCUMENT_TYPE, required = false) String documentType) { String participantIdentifierDecoded = decodeUrlToUTF8(participantIdentifier); String participantSchemeDecoded = decodeUrlToUTF8(participantScheme); String domainCodeDecoded = decodeUrlToUTF8(domainCode); + String documentTypeDecoded = decodeUrlToUTF8(documentType); - LOG.info("Search for page: {}, page size: {}, part. id: {}, part sch: {}, domain {}", page, pageSize, participantIdentifierDecoded, - participantSchemeDecoded, domainCodeDecoded); + LOG.info("Search for page: {}, page size: {}, part. id: {}, part sch: {}, domain: {}, document type: {}", page, pageSize, participantIdentifierDecoded, + participantSchemeDecoded, domainCodeDecoded, documentTypeDecoded); ResourceFilter sgf = new ResourceFilter(); sgf.setIdentifierValueLike(participantIdentifierDecoded); sgf.setIdentifierSchemeLike(participantSchemeDecoded); // add domain search parameter sgf.setDomain(domainDao.validateDomainCode(domainCodeDecoded)); + sgf.setDocumentType(documentTypeDecoded); return uiServiceGroupService.getTableList(page, pageSize, orderBy, orderType, sgf); } + @GetMapping(path = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT_METADATA) + public ResourceMetadataResult serviceMetadataResultList() { + return uiServiceGroupService.getResourceMetadata(); + } + private String decodeUrlToUTF8(String value) { if (StringUtils.isBlank(value)) { return null;