Commit f557a33d authored by Kostis Trantzas's avatar Kostis Trantzas
Browse files

Merge remote-tracking branch 'origin/2026Q2_RC'

parents c68ef029 4a6db36c
Loading
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
FROM ibm-semeru-runtimes:open-17.0.7_7-jdk
# RUN mkdir /opt/shareclasses
RUN mkdir -p /opt/openslice/lib/
COPY target/org.etsi.osl.tmf.api-1.3.0-exec.jar /opt/openslice/lib/
CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.tmf.api-1.3.0-exec.jar"]
COPY target/org.etsi.osl.tmf.api-1.4.0-exec.jar /opt/openslice/lib/
CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.tmf.api-1.4.0-exec.jar"]
EXPOSE 13082
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
	<parent>
		<groupId>org.etsi.osl</groupId>
		<artifactId>org.etsi.osl.main</artifactId>
		<version>2025Q4</version>
		<version>2026Q2</version>
		<relativePath>../org.etsi.osl.main</relativePath>
	</parent>

+9 −0
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ public class ResourceApiRouteBuilder extends RouteBuilder {
	@Value("${CATALOG_RESOURCES_OF_PARTNERS}")
	private String CATALOG_RESOURCES_OF_PARTNERS = "";

	@Value("${CATALOG_GET_RESOURCES_BY_FILTER}")
	private String CATALOG_GET_RESOURCES_BY_FILTER = "";
	

	@Autowired
	private ProducerTemplate template;
@@ -110,6 +113,12 @@ public class ResourceApiRouteBuilder extends RouteBuilder {
		.bean( resourceRepoService, "addOrUpdateResourceByNameCategoryVersion(${header.aname},${header.acategory}, ${header.aversion}, ${body})")
		.marshal().json( JsonLibrary.Jackson)
		.convertBodyTo( String.class );

		from( CATALOG_GET_RESOURCES_BY_FILTER )
		.log(LoggingLevel.DEBUG, log, CATALOG_GET_RESOURCES_BY_FILTER + " message received!")
		.to("log:DEBUG?showBody=true&showHeaders=true")
		.convertBodyTo( String.class )
		.bean( resourceRepoService, "findResourcesByFilter(${body})");
	}
	

+43 −0
Original line number Diff line number Diff line
package org.etsi.osl.tmf.ri639.reposervices;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * Filter DTO for querying resources via the CATALOG_GET_RESOURCES_BY_FILTER JMS route.
 * Example: {"specId":null,"namePattern":null,"vendor":null,"location":null,"status":"AVAILABLE","page":0,"pageSize":20}
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class ResourceFilter {

    private String specId;
    private String namePattern;
    /** Matched against a resource characteristic named "vendor" */
    private String vendor;
    /** Matched against place.name */
    private String location;
    /** Matched against resourceStatus enum value (e.g. "AVAILABLE") */
    private String status;
    private int page = 0;
    private int pageSize = 20;

    public String getSpecId() { return specId; }
    public void setSpecId(String specId) { this.specId = specId; }

    public String getNamePattern() { return namePattern; }
    public void setNamePattern(String namePattern) { this.namePattern = namePattern; }

    public String getVendor() { return vendor; }
    public void setVendor(String vendor) { this.vendor = vendor; }

    public String getLocation() { return location; }
    public void setLocation(String location) { this.location = location; }

    public String getStatus() { return status; }
    public void setStatus(String status) { this.status = status; }

    public int getPage() { return page; }
    public void setPage(int page) { this.page = page; }

    public int getPageSize() { return pageSize; }
    public void setPageSize(int pageSize) { this.pageSize = pageSize; }
}
+128 −41
Original line number Diff line number Diff line
/*-
 * ========================LICENSE_START=================================
 * org.etsi.osl.tmf.api
 * %%
 * Copyright (C) 2019 openslice.io
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */
package org.etsi.osl.tmf.ri639.reposervices;

import java.io.UnsupportedEncodingException;
@@ -25,6 +6,7 @@ import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -57,6 +39,7 @@ import org.etsi.osl.tmf.ri639.model.ResourceCreateNotification;
import org.etsi.osl.tmf.ri639.model.ResourceRelationship;
import org.etsi.osl.tmf.ri639.model.ResourceStateChangeEvent;
import org.etsi.osl.tmf.ri639.model.ResourceStateChangeNotification;
import org.etsi.osl.tmf.ri639.model.ResourceStatusType;
import org.etsi.osl.tmf.ri639.model.ResourceUpdate;
import org.etsi.osl.tmf.ri639.repo.ResourceRepository;
import org.etsi.osl.tmf.sim638.model.Service;
@@ -476,29 +459,24 @@ public class ResourceRepoService {
  @Transactional
  public Resource getResourceEager(String id) {
    
    Resource s = null;
    try(Session session = sessionFactory.openSession()) {
      Transaction tx = session.beginTransaction();
      s = (Resource) session.get(Resource.class, id);
      if (s == null) {
        return this.findByUuid(id);// last resort
      if (id == null || id.equals("")) {
        return null;
      }
    
      Hibernate.initialize(s.getRelatedParty());
      Hibernate.initialize(s.getNote());
      Hibernate.initialize(s.getResourceCharacteristic());
      Hibernate.initialize(s.getResourceSpecification());
      Hibernate.initialize(s.getResourceRelationship());
      Hibernate.initialize(s.getAttachment());
      Hibernate.initialize(s.getActivationFeature());
      Resource r = this.findByUuid(id);;


      tx.commit();
    } catch (Exception e) {
      e.printStackTrace();
      if (r == null) {
        return null;
      }
      Hibernate.initialize(r.getRelatedParty());
      Hibernate.initialize(r.getNote());
      Hibernate.initialize(r.getResourceCharacteristic());
      Hibernate.initialize(r.getResourceSpecification());
      Hibernate.initialize(r.getResourceRelationship());
      Hibernate.initialize(r.getAttachment());
      Hibernate.initialize(r.getActivationFeature());
   
    return s;
      return r;
  }


@@ -575,6 +553,113 @@ public class ResourceRepoService {
  }


  /**
   * Find resources matching the given filter.
   * Returns JSON: {"resources":[...],"totalCount":N,"continuationToken":"<nextPage>" or null}
   * Filter fields: specId, namePattern, vendor (characteristic), location (place.name), status, page, pageSize.
   */
  @Transactional
  public String findResourcesByFilter(String filterJson) throws JsonProcessingException {
    ResourceFilter filter;
    try {
      filter = objectMapper.readValue(filterJson, ResourceFilter.class);
    } catch (Exception e) {
      logger.error("Cannot parse ResourceFilter JSON: " + filterJson, e);
      return emptyBrowseResult();
    }

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    try {
      boolean joinVendorChar = filter.getVendor() != null;

      List<String> conditions = new ArrayList<>();
      Map<String, Object> params = new HashMap<>();

      if (filter.getSpecId() != null) {
        conditions.add("srv.resourceSpecification.uuid = :specId");
        params.put("specId", filter.getSpecId());
      }
      if (filter.getNamePattern() != null) {
        conditions.add("srv.name LIKE :namePattern");
        params.put("namePattern", "%" + filter.getNamePattern() + "%");
      }
      if (joinVendorChar) {
        conditions.add("vendorChar.name = 'vendor' AND vendorChar.value.value = :vendor");
        params.put("vendor", filter.getVendor());
      }
      if (filter.getLocation() != null) {
        conditions.add("srv.place.name LIKE :location");
        params.put("location", "%" + filter.getLocation() + "%");
      }
      if (filter.getStatus() != null) {
        ResourceStatusType statusEnum = ResourceStatusType.fromValue(filter.getStatus().toLowerCase());
        if (statusEnum != null) {
          conditions.add("srv.resourceStatus = :status");
          params.put("status", statusEnum);
        } else {
          logger.warn("Unknown resourceStatus filter value: " + filter.getStatus());
        }
      }

      String whereClause = conditions.isEmpty() ? "" : "WHERE " + String.join(" AND ", conditions) + " ";
      String joinClause = joinVendorChar ? "JOIN srv.resourceCharacteristic vendorChar " : "";

      // COUNT query for totalCount
      String countHql = "SELECT COUNT(DISTINCT srv) FROM RIResource srv " + joinClause + whereClause;
      org.hibernate.query.Query<Long> countQuery = session.createQuery(countHql, Long.class);
      params.forEach(countQuery::setParameter);
      long totalCount = countQuery.uniqueResult();

      // Data query with pagination
      String dataHql = "SELECT DISTINCT srv FROM RIResource srv " + joinClause + whereClause + "ORDER BY srv.name ASC";
      org.hibernate.query.Query<Resource> query = session.createQuery(dataHql, Resource.class);
      params.forEach(query::setParameter);

      int pageSize = filter.getPageSize() > 0 ? filter.getPageSize() : 20;
      int page = filter.getPage() >= 0 ? filter.getPage() : 0;
      query.setFirstResult(page * pageSize);
      query.setMaxResults(pageSize);

      List<Resource> resources = query.list();

      List<Map<String, Object>> resourceList = new ArrayList<>();
      for (Resource r : resources) {
        Hibernate.initialize(r.getResourceCharacteristic());
        Hibernate.initialize(r.getResourceSpecification());
        Map<String, Object> entry = new LinkedHashMap<>();
        entry.put("id", r.getUuid());
        entry.put("@type", r.getType());
        entry.put("name", r.getName());
        entry.put("category", r.getCategory());
        entry.put("description", r.getDescription());
        entry.put("resourceStatus", r.getResourceStatus() != null ? r.getResourceStatus().toString() : null);
        if (r.getResourceSpecification() != null) {
          entry.put("resourceSpecificationId", r.getResourceSpecification().getUuid());
          entry.put("resourceSpecificationName", r.getResourceSpecification().getName());
        }
        resourceList.add(entry);
      }

      boolean hasMore = (long) (page + 1) * pageSize < totalCount;
      String continuationToken = hasMore ? String.valueOf(page + 1) : null;

      Map<String, Object> browseResult = new LinkedHashMap<>();
      browseResult.put("resources", resourceList);
      browseResult.put("totalCount", totalCount);
      browseResult.put("continuationToken", continuationToken);

      tx.commit();
      return objectMapper.writeValueAsString(browseResult);
    } catch (Exception e) {
      logger.error("Error querying resources by filter", e);
      tx.rollback();
      return emptyBrowseResult();
    } finally {
      session.close();
    }
  }

  @Transactional
  public Resource addOrUpdateResourceByNameCategoryVersion(String aName, String aCategory,
      String aVersion, ResourceCreate aesourceCreate) {
@@ -606,6 +691,8 @@ public class ResourceRepoService {
    return result;
  }


  private String emptyBrowseResult() {
    return "{\"resources\":[],\"totalCount\":0,\"continuationToken\":null}";
  }

}
Loading