Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • simonrose/naming-backend
  • anderslindh1/naming-backend
  • andersharrisson/naming-backend
3 results
Show changes
Showing
with 879 additions and 243 deletions
......@@ -16,38 +16,29 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.util.response;
package org.openepics.names.exception;
/**
* This class is used to ensure response to request origin are handled in a uniform way.
* Exception class to assist in handling of service layer exceptions.
*
* @author Lars Johansson
*/
public class ResponseBoolean extends Response {
private Boolean response = null;
public ResponseBoolean() {
super("", "");
}
public ResponseBoolean(Boolean response) {
this();
this.response = response;
}
public ResponseBoolean(Boolean response, String message) {
super(message, "");
this.response = response;
}
public ResponseBoolean(Boolean response, String message, String details) {
super(message, details);
this.response = response;
}
public Boolean getResponse() {
return this.response;
public class InputNotCorrectException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = -1951806640288908108L;
/**
* Public constructor.
*
* @param message message
* @param details details
* @param field field
*/
public InputNotCorrectException(String message, String details, String field) {
super(message, details, field, null);
}
}
/*
* Copyright (C) 2022 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception;
/**
* Exception class to assist in handling of service layer exceptions.
*
* @author Lars Johansson
*/
public class InputNotEmptyException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = 8537254593583337762L;
/**
* Public constructor.
*
* @param message message
* @param details details
* @param field field
*/
public InputNotEmptyException(String message, String details, String field) {
super(message, details, field, null);
}
}
/*
* Copyright (C) 2022 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception;
/**
* Exception class to assist in handling of service layer exceptions.
*
* @author Lars Johansson
*/
public class InputNotValidException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = -2652292043931691939L;
/**
* Public constructor.
*
* @param message message
* @param details details
* @param field field
*/
public InputNotValidException(String message, String details, String field) {
super(message, details, field, null);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
* Copyright (C) 2022 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -16,47 +16,46 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.util;
import org.springframework.http.HttpStatus;
package org.openepics.names.exception;
/**
* Exception class to assist in handling of service layer exceptions.
*
* @author Lars Johansson
*/
public class ServiceHttpStatusException extends RuntimeException {
public class ServiceException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 5346696855950320329L;
private static final long serialVersionUID = -5521814109184738596L;
private final HttpStatus httpStatus;
private final String details;
private final String userFriendly;
private final String field;
/**
* Public constructor.
*
* @param httpStatus http status
* @param message message
* @param cause cause
*/
public ServiceHttpStatusException(HttpStatus httpStatus, String message, String details, String userFriendly, Throwable cause) {
super(message, cause);
this.httpStatus = httpStatus;
this.details = details;
this.userFriendly = userFriendly;
public ServiceException(String message) {
super(message);
this.details = null;
this.field = null;
}
/**
* Return http status of exception.
* Public constructor.
*
* @return http status
* @param message message
* @param details details
* @param field field
* @param cause cause
*/
public HttpStatus getHttpStatus() {
return httpStatus;
public ServiceException(String message, String details, String field, Throwable cause) {
super(message, cause);
this.details = details;
this.field = field;
}
/**
......@@ -69,12 +68,12 @@ public class ServiceHttpStatusException extends RuntimeException {
}
/**
* Return user friendly of exception.
* Return field of exception.
*
* @return user friendly
* @return field
*/
public String getUserFriendly() {
return userFriendly;
public String getField() {
return field;
}
}
......@@ -16,15 +16,27 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.rest.controller;
import java.util.logging.Level;
import java.util.logging.Logger;
package org.openepics.names.exception.handler;
import org.apache.commons.lang3.StringUtils;
import org.openepics.names.util.ExceptionUtil;
import org.openepics.names.util.ServiceHttpStatusException;
import org.openepics.names.util.response.Response;
import org.openepics.names.exception.DataConflictException;
import org.openepics.names.exception.DataDeletedException;
import org.openepics.names.exception.DataExistException;
import org.openepics.names.exception.DataNotAvailableException;
import org.openepics.names.exception.DataNotCorrectException;
import org.openepics.names.exception.DataNotFoundException;
import org.openepics.names.exception.DataNotValidException;
import org.openepics.names.exception.InputNotAvailableException;
import org.openepics.names.exception.InputNotCorrectException;
import org.openepics.names.exception.InputNotEmptyException;
import org.openepics.names.exception.InputNotValidException;
import org.openepics.names.exception.ServiceException;
import org.openepics.names.exception.security.AuthenticationException;
import org.openepics.names.exception.security.EntityNotFoundException;
import org.openepics.names.exception.security.RemoteException;
import org.openepics.names.exception.security.UnauthorizedException;
import org.openepics.names.rest.beans.response.Response;
import org.openepics.names.util.TextUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
......@@ -34,33 +46,73 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
/**
* Global exception handler to ensure exceptions are communicated to request origin in a uniform way.
*
* <br/><br/>
* Note
* <ul>
* <li>400 {@link HttpStatus#BAD_REQUEST}</li>
* <li>401 {@link HttpStatus#UNAUTHORIZED}</li>
* <li>403 {@link HttpStatus#FORBIDDEN}</li>
* <li>404 {@link HttpStatus#NOT_FOUND}</li>
* <li>409 {@link HttpStatus#CONFLICT}</li>
* <li>422 {@link HttpStatus#UNPROCESSABLE_ENTITY}</li>
* <li>500 {@link HttpStatus#INTERNAL_SERVER_ERROR}</li>
* <li>503 {@link HttpStatus#SERVICE_UNAVAILABLE}</li>
* </ul>
*
* @author Lars Johansson
*/
@RestControllerAdvice
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
// note
// no logging here
private static final Logger LOGGER = Logger.getLogger(GlobalControllerExceptionHandler.class.getName());
@ExceptionHandler
protected ResponseEntity<Response> handleConflict(RuntimeException ex, WebRequest request) {
LOGGER.log(Level.INFO, "handleConflict, ex.getMessage: " + ex.getMessage());
Response response = new Response("", "");
response.setMessage(ExceptionUtil.OPERATION_COULD_NOT_BE_PERFORMED);
public ResponseEntity<Response> handleConflict(RuntimeException ex, WebRequest request) {
Response response = new Response("", "", "");
response.setMessage(TextUtil.OPERATION_COULD_NOT_BE_PERFORMED);
HttpStatus resultStatus = HttpStatus.INTERNAL_SERVER_ERROR;
if (ex instanceof ServiceHttpStatusException) {
if (ex instanceof ServiceException se) {
response.setMessage(StringUtils.trimToEmpty(ex.getMessage()));
response.setDetails(StringUtils.trimToEmpty(((ServiceHttpStatusException) ex).getDetails()));
resultStatus = ((ServiceHttpStatusException) ex).getHttpStatus();
response.setDetails(StringUtils.trimToEmpty(se.getDetails()));
response.setField(StringUtils.trimToEmpty(se.getField()));
// HttpStatus.BAD_REQUEST handled by Spring
if (ex instanceof AuthenticationException) {
resultStatus = HttpStatus.UNAUTHORIZED;
}
if (ex instanceof UnauthorizedException) {
resultStatus = HttpStatus.FORBIDDEN;
}
if (ex instanceof DataNotAvailableException
|| ex instanceof DataNotFoundException
|| ex instanceof EntityNotFoundException) {
resultStatus = HttpStatus.NOT_FOUND;
}
if (ex instanceof DataConflictException
|| ex instanceof DataDeletedException
|| ex instanceof DataExistException
|| ex instanceof DataNotValidException) {
resultStatus = HttpStatus.CONFLICT;
}
if (ex instanceof InputNotAvailableException
|| ex instanceof InputNotCorrectException
|| ex instanceof InputNotEmptyException
|| ex instanceof InputNotValidException
|| ex instanceof DataNotCorrectException) {
resultStatus = HttpStatus.UNPROCESSABLE_ENTITY;
}
if (ex instanceof RemoteException) {
resultStatus = HttpStatus.SERVICE_UNAVAILABLE;
}
}
return new ResponseEntity<>(response, Response.HEADER_JSON, resultStatus);
return new ResponseEntity<>(response, Response.getHeaderJson(), resultStatus);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
import org.openepics.names.exception.ServiceException;
/**
* @author <a href="mailto:imre.toth@ess.eu">Imre Toth</a>
*/
public class AuthenticationException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = -5434486411943794281L;
private static final String ERROR = "Authentication error";
public AuthenticationException(String description) {
super(ERROR, description, null, null);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
import org.openepics.names.exception.ServiceException;
/**
* @author <a href="mailto:imre.toth@ess.eu">Imre Toth</a>
*/
public class EntityNotFoundException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = 564746316436100483L;
private static final String ENTITY_NOT_FOUND = "Entity not found";
public EntityNotFoundException(String entityType, long entityId) {
super(ENTITY_NOT_FOUND, entityType + " (ID: " + entityId + ") not found", null, null);
}
public EntityNotFoundException(String entityType, String name) {
super(ENTITY_NOT_FOUND, entityType + " (name: " + name + ") not found", null, null);
}
public EntityNotFoundException(String message) {
super(ENTITY_NOT_FOUND, message, null, null);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
/**
* @author <a href="mailto:imre.toth@ess.eu">Imre Toth</a>
*/
public class ParseException extends Exception {
/**
*
*/
private static final long serialVersionUID = 7711905654503012121L;
public ParseException() {}
public ParseException(String message) {
super(message);
}
}
/*
* Copyright (C) 2022 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
import org.openepics.names.exception.ServiceException;
/**
* @author <a href="mailto:imre.toth@ess.eu">Imre Toth</a>
*/
public class RemoteException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = -1202935975436997437L;
public RemoteException(String error, String description) {
super(error, description, null, null);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
/**
* @author <a href="mailto:zoltan.runyo@ess.eu">Zoltan Runyo</a>
*/
public class RemoteServiceException extends Exception {
/**
*
*/
private static final long serialVersionUID = 3744513029294293528L;
public RemoteServiceException(String message, Throwable cause) {
super(message, cause);
}
public RemoteServiceException(String message) {
super(message);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.exception.security;
import org.openepics.names.exception.ServiceException;
/**
* @author <a href="mailto:zoltan.runyo@ess.eu">Zoltan Runyo</a>
*/
public class UnauthorizedException extends ServiceException {
/**
*
*/
private static final long serialVersionUID = -3051588358017181877L;
public UnauthorizedException(String description) {
super("Operation forbidden", description, null, null);
}
}
......@@ -35,7 +35,6 @@ import java.util.UUID;
@Entity
public class Device extends Persistable {
private static final long serialVersionUID = 8489649071981076533L;
private String uuid;
protected Device() {}
......@@ -55,8 +54,12 @@ public class Device extends Persistable {
*/
public UUID getUuid() { return UUID.fromString(uuid); }
@Override public boolean equals(Object other) {
return other instanceof Device && ((Device) other).getUuid().equals(getUuid());
@Override
public boolean equals(Object other) {
if (other instanceof Device object) {
return object.getUuid().equals(getUuid());
}
return false;
}
@Override
......
......@@ -40,8 +40,6 @@ import java.util.Date;
@Table(name = "devicerevision")
public class DeviceRevision extends Persistable {
private static final long serialVersionUID = -7697708696131775826L;
@JoinColumn(name = "device_id")
private @ManyToOne Device device;
......@@ -221,10 +219,6 @@ public class DeviceRevision extends Persistable {
}
public boolean supersede(DeviceRevision other) {
// TODO: fix this...(when new revision are be created instead of updating old ones)
// return other == null
// || getId() > other.getId()
// || getId() == other.getId() && other.getStatus().isPending() && !getStatus().isPending();
return other == null
|| getId() > other.getId();
}
......
......@@ -41,11 +41,6 @@ import java.util.UUID;
@Table(name = "namepart")
public class NamePart extends Persistable {
/**
*
*/
private static final long serialVersionUID = 1674808840579429369L;
private String uuid;
@Column(name = "nameparttype")
......@@ -78,7 +73,10 @@ public class NamePart extends Persistable {
public NamePartType getNamePartType() { return namePartType; }
@Override public boolean equals(Object other) {
return other instanceof NamePart && ((NamePart) other).getUuid().equals(getUuid());
if (other instanceof NamePart object) {
return object.getUuid().equals(getUuid());
}
return false;
}
@Override
......
......@@ -44,11 +44,6 @@ import java.util.Date;
@Table(name = "namepartrevision")
public class NamePartRevision extends Persistable {
/**
*
*/
private static final long serialVersionUID = -8783968098755208875L;
@JoinColumn(name = "namepart_id")
private @ManyToOne NamePart namePart;
......@@ -190,7 +185,6 @@ public class NamePartRevision extends Persistable {
*/
public @Nullable String getMnemonicEqClass() { return mnemonicEqClass; }
//TODO Remove after first deploy!!!
public void setMnemonicEqClass(String mnemonicEqClass) { this.mnemonicEqClass = mnemonicEqClass; }
/**
......
......@@ -39,11 +39,6 @@ import java.util.Objects;
@Table(name = "useraccount")
public class UserAccount extends Persistable {
/**
*
*/
private static final long serialVersionUID = -6026728360254460697L;
private String username;
@Enumerated(EnumType.STRING) private Role role;
......@@ -78,7 +73,10 @@ public class UserAccount extends Persistable {
}
@Override public boolean equals(Object other) {
return other instanceof UserAccount && ((UserAccount) other).getUsername().equals(getUsername());
if (other instanceof UserAccount object) {
return object.getUsername().equals(getUsername());
}
return false;
}
@Override public String toString(){
......
......@@ -18,7 +18,6 @@
package org.openepics.names.old.nameviews;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -34,12 +33,7 @@ import org.openepics.names.old.model.DeviceRevision;
* @author Lars Johansson
*
*/
public class NameViewProvider implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6916728601880286405L;
public class NameViewProvider {
private NameRevisions nameRevisions;
......
/*
* Copyright (C) 2024 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.repository;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.openepics.names.repository.model.AuditName;
import org.openepics.names.repository.model.NameStructure;
import org.openepics.names.util.RepositoryUtil;
import org.springframework.stereotype.Repository;
/**
* Handle audit name information in JPA.
*
* @author Lars Johansson
*/
@Repository
public class AuditNameRepository {
@PersistenceContext
private EntityManager em;
/**
* Count audit names.
*
* @param uuid uuid
* @return count of audit names
*/
public Long countAuditNames(String uuid) {
// where
// uuid
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<AuditName> from = cq.from(AuditName.class);
cq.where(cb.and(preparePredicatesAuditNames(cb, cq, from,
uuid).toArray(new Predicate[0])));
cq.select(cb.count(from));
return em.createQuery(cq).getSingleResult();
}
/**
* Find audit names.
*
* @param uuid uuid
* @return list of audit names
*/
public List<AuditName> readAuditNames(String uuid,
Integer offset, Integer limit) {
// where
// uuid
// order
// processed asc
// paging
// offset, limit
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<AuditName> cq = cb.createQuery(AuditName.class);
Root<AuditName> from = cq.from(AuditName.class);
cq.where(cb.and(preparePredicatesAuditNames(cb, cq, from,
uuid).toArray(new Predicate[0])));
cq.select(from);
cq.orderBy(cb.asc(from.get(NameStructure.FIELD_REQUESTED)));
TypedQuery<AuditName> query = em.createQuery(cq);
if (offset != null && limit != null) {
query.setFirstResult(offset * limit);
query.setMaxResults(limit);
}
return query.getResultList();
}
/**
* Prepare predicates for audit names.
*
* @param cb criteria builder
* @param cq criteria query
* @param from criteria query root
* @param uuid uuid
* @return list of predicates
*/
private List<Predicate> preparePredicatesAuditNames(CriteriaBuilder cb, CriteriaQuery cq, Root<AuditName> from,
String uuid) {
List<Predicate> predicates = new ArrayList<>();
if (!StringUtils.isEmpty(uuid)) {
predicates.add(cb.and(cb.equal(from.get(NameStructure.FIELD_UUID), RepositoryUtil.preparePattern(uuid))));
}
return predicates;
}
/**
* Persist audit name into persistence context.
*
* @param auditName audit name
*/
public void createAuditName(AuditName auditName) {
em.persist(auditName);
}
}
/*
* Copyright (C) 2024 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.openepics.names.repository;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.openepics.names.repository.model.AuditStructure;
import org.openepics.names.rest.beans.Type;
import org.openepics.names.util.RepositoryUtil;
import org.springframework.stereotype.Repository;
/**
* Handle audit structure information in JPA.
*
* @author Lars Johansson
*/
@Repository
public class AuditStructureRepository {
@PersistenceContext
private EntityManager em;
/**
* Count audit structures.
*
* @param type type
* @param uuid uuid
* @return count of audit structures
*/
public Long countAuditStructures(Type type, String uuid) {
// where
// type
// uuid
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<AuditStructure> from = cq.from(AuditStructure.class);
cq.where(cb.and(preparePredicatesAuditStructures(cb, cq, from,
type, uuid).toArray(new Predicate[0])));
cq.select(cb.count(from));
return em.createQuery(cq).getSingleResult();
}
/**
* Find audit structures.
*
* @param type type
* @param uuid uuid
* @return list of structures
*/
public List<AuditStructure> readAuditStructures(Type type, String uuid,
Integer offset, Integer limit) {
// where
// type
// uuid
// order
// processed asc
// paging
// offset, limit
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<AuditStructure> cq = cb.createQuery(AuditStructure.class);
Root<AuditStructure> from = cq.from(AuditStructure.class);
cq.where(cb.and(preparePredicatesAuditStructures(cb, cq, from,
type, uuid).toArray(new Predicate[0])));
cq.select(from);
cq.orderBy(cb.asc(from.get(AuditStructure.FIELD_PROCESSED)));
TypedQuery<AuditStructure> query = em.createQuery(cq);
if (offset != null && limit != null) {
query.setFirstResult(offset * limit);
query.setMaxResults(limit);
}
return query.getResultList();
}
/**
* Prepare predicates for audit structures.
*
* @param cb criteria builder
* @param cq criteria query
* @param from criteria query root
* @param type type
* @param uuid uuid
* @return list of predicates
*/
private List<Predicate> preparePredicatesAuditStructures(CriteriaBuilder cb, CriteriaQuery cq, Root<AuditStructure> from,
Type type, String uuid) {
List<Predicate> predicates = new ArrayList<>();
if (type != null) {
predicates.add(cb.and(cb.equal(from.get(AuditStructure.FIELD_AUDIT_TABLE), type.name().toLowerCase())));
}
if (!StringUtils.isEmpty(uuid)) {
predicates.add(cb.and(cb.equal(from.get(AuditStructure.FIELD_UUID), RepositoryUtil.preparePattern(uuid))));
}
return predicates;
}
/**
* Persist audit structure into persistence context.
*
* @param auditStructure audit structure
*/
public void createAuditStructure(AuditStructure auditStructure) {
em.persist(auditStructure);
}
}
/*
* Copyright (C) 2021 European Spallation Source ERIC.
* Copyright (C) 2024 European Spallation Source ERIC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -26,13 +26,18 @@ import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.openepics.names.repository.model.DeviceGroup;
import org.openepics.names.repository.model.NameStructure;
import org.openepics.names.repository.model.Persistable;
import org.openepics.names.repository.model.Structure;
import org.openepics.names.rest.beans.FieldStructure;
import org.openepics.names.rest.beans.Status;
import org.openepics.names.util.RepositoryUtil;
import org.springframework.stereotype.Repository;
/**
......@@ -43,42 +48,28 @@ import org.springframework.stereotype.Repository;
@Repository
public class DeviceGroupRepository {
private static final String PERCENT = "%";
@PersistenceContext
private EntityManager em;
/**
* Count device groups.
*
* @param statuses statuses
* @param deleted deleted
* @param queryFields query fields
* @param queryValues query values
* @return count of device groups
*/
public Long countDeviceGroups(
Status[] statuses, Boolean deleted, FieldStructure[] queryFields, String[] queryValues) {
return countDeviceGroups(statuses, deleted, queryFields, queryValues, Boolean.FALSE);
}
/**
* Count device groups.
*
* @param statuses statuses
* @param deleted deleted
* @param queryFields query fields
* @param queryValues query values
* @param includeHistory include history
* @param uuid uuid
* @param parentUuid parent uuid
* @param mnemonic mnemonic
* @param mnemonicEquivalence mnemonic equivalence
* @param mnemonicPath mnemonic path
* @param description description
* @param who who
* @return count of device groups
*/
public Long countDeviceGroups(
Status[] statuses, Boolean deleted, FieldStructure[] queryFields, String[] queryValues, Boolean includeHistory) {
public Long countDeviceGroups(Boolean deleted,
String uuid, String parentUuid, String mnemonic, String mnemonicEquivalence, String mnemonicPath, String description, String who) {
// note
// use of function for mnemonic path
// where
// statuses
// deleted
// queryFields, queryValues
......@@ -86,7 +77,8 @@ public class DeviceGroupRepository {
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<DeviceGroup> from = cq.from(DeviceGroup.class);
cq.where(cb.and(preparePredicatesDeviceGroups(cb, from, statuses, deleted, queryFields, queryValues, includeHistory).toArray(new Predicate[0])));
cq.where(cb.and(preparePredicatesDeviceGroups(cb, cq, from, deleted,
uuid, parentUuid, mnemonic, mnemonicEquivalence, mnemonicPath, description, who).toArray(new Predicate[0])));
cq.select(cb.count(from));
return em.createQuery(cq).getSingleResult();
......@@ -95,67 +87,48 @@ public class DeviceGroupRepository {
/**
* Find device groups.
*
* @param status status
* @param deleted deleted
* @param queryField query field
* @param queryValue query value
* @param uuid uuid
* @param parentUuid parent uuid
* @param mnemonic mnemonic
* @param mnemonicEquivalence mnemonic equivalence
* @param mnemonicPath mnemonic path
* @param description description
* @param who who
* @return list of device groups
*/
public List<DeviceGroup> readDeviceGroups(
Status status, Boolean deleted, FieldStructure queryField, String queryValue) {
public List<DeviceGroup> readDeviceGroups(Boolean deleted,
String uuid, String parentUuid, String mnemonic, String mnemonicEquivalence, String mnemonicPath, String description, String who) {
return readDeviceGroups(
status != null ? new Status[] {status} : null,
deleted,
queryField != null ? new FieldStructure[] {queryField} : null,
queryValue != null ? new String[] {queryValue} : null,
Boolean.FALSE,
return readDeviceGroups(deleted,
uuid, parentUuid, mnemonic, mnemonicEquivalence, mnemonicPath, description, who,
null, null, null, null);
}
/**
* Find device groups.
*
* @param statuses statuses
* @param deleted deleted
* @param queryFields query fields
* @param queryValues query values
* @param orderBy order by
* @param isAsc is ascending
* @param offset offset
* @param limit limit
* @return list of device groups
*/
public List<DeviceGroup> readDeviceGroups(
Status[] statuses, Boolean deleted, FieldStructure[] queryFields, String[] queryValues,
FieldStructure orderBy, Boolean isAsc, Integer offset, Integer limit) {
return readDeviceGroups(
statuses, deleted, queryFields, queryValues, Boolean.FALSE,
orderBy, isAsc, offset, limit);
}
/**
* Find device groups.
*
* @param statuses statuses
* @param deleted deleted
* @param queryFields query fields
* @param queryValues query values
* @param includeHistory include history
* @param uuid uuid
* @param parentUuid parent uuid
* @param mnemonic mnemonic
* @param mnemonicEquivalence mnemonic equivalence
* @param mnemonicPath mnemonic path
* @param description description
* @param who who
* @param orderBy order by
* @param isAsc is ascending
* @param offset offset
* @param limit limit
* @return list of device groups
*/
public List<DeviceGroup> readDeviceGroups(
Status[] statuses, Boolean deleted, FieldStructure[] queryFields, String[] queryValues, Boolean includeHistory,
public List<DeviceGroup> readDeviceGroups(Boolean deleted,
String uuid, String parentUuid, String mnemonic, String mnemonicEquivalence, String mnemonicPath, String description, String who,
FieldStructure orderBy, Boolean isAsc, Integer offset, Integer limit) {
// note
// use of function for mnemonic path
// where
// statuses
// deleted
// queryFields, queryValues
// order
......@@ -167,38 +140,16 @@ public class DeviceGroupRepository {
CriteriaQuery<DeviceGroup> cq = cb.createQuery(DeviceGroup.class);
Root<DeviceGroup> from = cq.from(DeviceGroup.class);
cq.where(cb.and(preparePredicatesDeviceGroups(cb, from, statuses, deleted, queryFields, queryValues, includeHistory).toArray(new Predicate[0])));
cq.where(cb.and(preparePredicatesDeviceGroups(cb, cq, from, deleted,
uuid, parentUuid, mnemonic, mnemonicEquivalence, mnemonicPath, description, who).toArray(new Predicate[0])));
cq.select(from);
if (orderBy != null) {
Expression<String> exp = orderBy(from, orderBy);
if (BooleanUtils.toBoolean(isAsc)) {
if (FieldStructure.NAME.equals(orderBy)) {
cq.orderBy(cb.asc(from.get("name")));
} else if (FieldStructure.MNEMONIC.equals(orderBy)) {
cq.orderBy(cb.asc(from.get("mnemonic")));
} else if (FieldStructure.MNEMONICEQUIVALENCE.equals(orderBy)) {
cq.orderBy(cb.asc(from.get("mnemonic_equivalence")));
} else if (FieldStructure.MNEMONICPATH.equals(orderBy)) {
cq.orderBy(cb.asc(cb.function("get_mnemonic_path_devicegroup", String.class, from.get("uuid"))));
} else if (FieldStructure.DESCRIPTION.equals(orderBy)) {
cq.orderBy(cb.asc(from.get("description")));
} else {
cq.orderBy(cb.asc(from.get("convention_name")));
}
cq.orderBy(cb.asc(exp));
} else {
if (FieldStructure.NAME.equals(orderBy)) {
cq.orderBy(cb.desc(from.get("name")));
} else if (FieldStructure.MNEMONIC.equals(orderBy)) {
cq.orderBy(cb.desc(from.get("mnemonic")));
} else if (FieldStructure.MNEMONICEQUIVALENCE.equals(orderBy)) {
cq.orderBy(cb.desc(from.get("mnemonic_equivalence")));
} else if (FieldStructure.MNEMONICPATH.equals(orderBy)) {
cq.orderBy(cb.desc(cb.function("get_mnemonic_path_devicegroup", String.class, from.get("uuid"))));
} else if (FieldStructure.DESCRIPTION.equals(orderBy)) {
cq.orderBy(cb.desc(from.get("description")));
} else {
cq.orderBy(cb.desc(from.get("name")));
}
cq.orderBy(cb.desc(exp));
}
}
......@@ -215,89 +166,83 @@ public class DeviceGroupRepository {
* Prepare predicates for device groups.
*
* @param cb criteria builder
* @param cq criteria query
* @param from criteria query root
* @param statuses statuses
* @param deleted deleted
* @param queryFields query fields
* @param queryValues query values
* @param includeHistory include history
* @param uuid uuid
* @param parentUuid parent uuid
* @param mnemonic mnemonic
* @param mnemonicEquivalence mnemonic equivalence
* @param mnemonicPath mnemonic path
* @param description description
* @param who who
* @return list of predicates
*/
private List<Predicate> preparePredicatesDeviceGroups(
CriteriaBuilder cb, Root<DeviceGroup> from,
Status[] statuses, Boolean deleted, FieldStructure[] queryFields, String[] queryValues, Boolean includeHistory) {
private List<Predicate> preparePredicatesDeviceGroups(CriteriaBuilder cb, CriteriaQuery cq, Root<DeviceGroup> from, Boolean deleted,
String uuid, String parentUuid, String mnemonic, String mnemonicEquivalence, String mnemonicPath, String description, String who) {
List<Predicate> predicates = new ArrayList<>();
if (!Boolean.TRUE.equals(includeHistory)) {
// exclude (approved and not latest)
Predicate predicateApproved = cb.equal(from.get("status"), Status.APPROVED);
Predicate predicateNotLatest = cb.equal(from.get("latest"), Boolean.FALSE);
Predicate predicateExclude = cb.not(cb.and(predicateApproved, predicateNotLatest));
predicates.add(predicateExclude);
}
if (statuses != null) {
List<Predicate> predicatesStatus = new ArrayList<>();
for (Status status : statuses) {
predicatesStatus.add(cb.equal(from.get("status"), status));
}
predicates.add(cb.or((Predicate[]) predicatesStatus.toArray(new Predicate[0])));
}
if (deleted != null) {
predicates.add(cb.equal(from.get("deleted"), deleted));
predicates.add(cb.equal(from.get(NameStructure.FIELD_DELETED), deleted));
}
if (queryFields != null) {
for (int i=0; i<queryFields.length; i++) {
String queryValue = queryValues[i];
// jpa query characters % and _
// remove excess % characters
if (queryValue.startsWith(PERCENT)) {
while (queryValue.startsWith(PERCENT)) {
queryValue = queryValue.substring(1);
}
queryValue = PERCENT + queryValue;
}
if (queryValue.endsWith(PERCENT)) {
while (queryValue.endsWith(PERCENT)) {
queryValue = queryValue.substring(0, queryValue.length()-1);
}
queryValue = queryValue + PERCENT;
}
// prepare pattern
// jpa query characters % and _
// remove excess % characters
switch (queryFields[i]) {
case UUID:
predicates.add(cb.and(cb.equal(from.get("uuid"), queryValue)));
break;
case PARENT:
predicates.add(cb.and(cb.equal(from.get("parent_uuid"), queryValue)));
break;
case NAME:
predicates.add(cb.and(cb.like(from.get("name"), queryValue)));
break;
case MNEMONIC:
predicates.add(cb.and(cb.like(from.get("mnemonic"), queryValue)));
break;
case MNEMONICEQUIVALENCE:
predicates.add(cb.and(cb.like(from.get("mnemonic_equivalence"), queryValue)));
break;
case MNEMONICPATH:
predicates.add(cb.and(cb.like(cb.function("get_mnemonic_path_devicegroup", String.class, from.get("uuid")), queryValue)));
break;
case DESCRIPTION:
predicates.add(cb.and(cb.like(from.get("description"), queryValue)));
break;
default:
continue;
}
}
if (!StringUtils.isEmpty(uuid)) {
predicates.add(cb.and(cb.equal(from.get(NameStructure.FIELD_UUID), RepositoryUtil.preparePattern(uuid))));
}
if (!StringUtils.isEmpty(parentUuid)) {
predicates.add(cb.and(cb.equal(cb.function(DeviceGroup.FUNCTION_GET_PARENT_UUID_DEVICEGROUP, String.class, from.get(Persistable.FIELD_ID)), RepositoryUtil.preparePattern(parentUuid))));
}
if (!StringUtils.isEmpty(mnemonic)) {
predicates.add(cb.and(cb.like(from.get(Structure.FIELD_MNEMONIC), RepositoryUtil.preparePattern(mnemonic))));
}
if (!StringUtils.isEmpty(mnemonicEquivalence)) {
predicates.add(cb.and(cb.like(from.get(Structure.FIELD_MNEMONIC_EQUIVALENCE), RepositoryUtil.preparePattern(mnemonicEquivalence))));
}
if (!StringUtils.isEmpty(mnemonicPath)) {
predicates.add(cb.and(cb.like(cb.function(DeviceGroup.FUNCTION_GET_MNEMONIC_PATH_DEVICEGROUP, String.class, from.get(Persistable.FIELD_ID)), RepositoryUtil.preparePattern(mnemonicPath))));
}
if (!StringUtils.isEmpty(description)) {
predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_DESCRIPTION), RepositoryUtil.preparePattern(description))));
}
if (!StringUtils.isEmpty(who)) {
predicates.add(cb.and(cb.like(from.get(NameStructure.FIELD_PROCESSED_BY), RepositoryUtil.preparePattern(who))));
}
return predicates;
}
/**
* Prepare order by query expression.
*
* @param root root type in the from clause
* @param orderBy field on which to order by
* @return order by query expression
*/
private Expression<String> orderBy(Root<DeviceGroup> root, FieldStructure orderBy) {
if (FieldStructure.UUID.equals(orderBy)) {
return root.get(NameStructure.FIELD_UUID);
} else if (FieldStructure.PARENT.equals(orderBy)) {
return root.get(DeviceGroup.FIELD_PARENT_ID);
} else if (FieldStructure.MNEMONIC.equals(orderBy)) {
return root.get(Structure.FIELD_MNEMONIC);
} else if (FieldStructure.MNEMONICPATH.equals(orderBy)) {
return root.get(Structure.FIELD_MNEMONIC);
} else if (FieldStructure.ORDERING.equals(orderBy)) {
return root.get(Structure.FIELD_ORDERING);
} else if (FieldStructure.DESCRIPTION.equals(orderBy)) {
return root.get(NameStructure.FIELD_DESCRIPTION);
} else if (FieldStructure.WHEN.equals(orderBy)) {
return root.get(NameStructure.FIELD_PROCESSED);
} else {
return root.get(Structure.FIELD_MNEMONIC);
}
}
/**
* Persist device group into persistence context.
*
......