-
Lars Johansson authored
Have ability to include names with indirectly referenced structure.
Lars Johansson authoredHave ability to include names with indirectly referenced structure.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
NamesService.java 46.72 KiB
/*
* 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.service;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import org.openepics.names.repository.DeviceGroupRepository;
import org.openepics.names.repository.DeviceTypeRepository;
import org.openepics.names.repository.DisciplineRepository;
import org.openepics.names.repository.IDeviceGroupRepository;
import org.openepics.names.repository.IDeviceTypeRepository;
import org.openepics.names.repository.IDisciplineRepository;
import org.openepics.names.repository.INameRepository;
import org.openepics.names.repository.ISubsystemRepository;
import org.openepics.names.repository.ISystemGroupRepository;
import org.openepics.names.repository.ISystemRepository;
import org.openepics.names.repository.NameRepository;
import org.openepics.names.repository.SubsystemRepository;
import org.openepics.names.repository.SystemGroupRepository;
import org.openepics.names.repository.SystemRepository;
import org.openepics.names.repository.model.DeviceGroup;
import org.openepics.names.repository.model.DeviceType;
import org.openepics.names.repository.model.Discipline;
import org.openepics.names.repository.model.Name;
import org.openepics.names.repository.model.Structure;
import org.openepics.names.repository.model.Subsystem;
import org.openepics.names.repository.model.System;
import org.openepics.names.repository.model.SystemGroup;
import org.openepics.names.rest.beans.FieldName;
import org.openepics.names.rest.beans.Status;
import org.openepics.names.rest.beans.element.NameElement;
import org.openepics.names.rest.beans.element.NameElementCommand;
import org.openepics.names.rest.beans.response.ResponsePageNameElements;
import org.openepics.names.util.EssNamingConvention;
import org.openepics.names.util.ExceptionUtil;
import org.openepics.names.util.HolderIRepositories;
import org.openepics.names.util.HolderRepositories;
import org.openepics.names.util.HolderStructures;
import org.openepics.names.util.NameElementUtil;
import org.openepics.names.util.NameUtil;
import org.openepics.names.util.TextUtil;
import org.openepics.names.util.ValidateNameElementUtil;
import org.openepics.names.util.ValidateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Lists;
/**
* This class provides names services.
*
* @author Lars Johansson
*/
@Service
public class NamesService {
// note
// handling of system structure, device structure
// parent system structure uuid (system group, system, subsystem) - ability to find structure
// parent device structure uuid (device type)
// holder
// HolderIRepositories and HolderSystemDeviceStructure may or may not be used for preparation of what to return
// latest
// automatically not show names that do not come into play
// = automatically exclude (approved and not latest)
// otherwise refer to history
// namecommand
// cud - create update delete
private static final Logger LOGGER = Logger.getLogger(NamesService.class.getName());
private static final String UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE = "Update after APPROVE structure change";
private HolderIRepositories holderIRepositories;
private HolderRepositories holderRepositories;
// convenience, also part of holderRepositories
private NameRepository nameRepository;
private EssNamingConvention namingConvention;
@Autowired
public NamesService(
INameRepository iNameRepository,
ISystemGroupRepository iSystemGroupRepository,
ISystemRepository iSystemRepository,
ISubsystemRepository iSubsystemRepository,
IDisciplineRepository iDisciplineRepository,
IDeviceGroupRepository iDeviceGroupRepository,
IDeviceTypeRepository iDeviceTypeRepository,
NameRepository nameRepository,
SystemGroupRepository systemGroupRepository,
SystemRepository systemRepository,
SubsystemRepository subsystemRepository,
DisciplineRepository disciplineRepository,
DeviceGroupRepository deviceGroupRepository,
DeviceTypeRepository deviceTypeRepository) {
this.namingConvention = new EssNamingConvention();
this.holderIRepositories = new HolderIRepositories(
iNameRepository,
iSystemGroupRepository,
iSystemRepository,
iSubsystemRepository,
iDisciplineRepository,
iDeviceGroupRepository,
iDeviceTypeRepository);
this.holderRepositories = new HolderRepositories(
nameRepository,
systemGroupRepository,
systemRepository,
subsystemRepository,
disciplineRepository,
deviceGroupRepository,
deviceTypeRepository);
this.nameRepository = nameRepository;
}
@Transactional
public List<NameElement> createNames(List<NameElementCommand> nameElementCommands, String username) {
// validation outside method
// transaction
// for each name element
// create name, latest, with data
// handle name element for created name
// no notify
// return name elements for created names
// initiate holder of system and device structure content, for performance reasons
HolderStructures holderStructures = new HolderStructures(holderIRepositories);
Date when = new Date();
final List<NameElement> createdNameElements = Lists.newArrayList();
for (NameElementCommand nameElementCommand : nameElementCommands) {
NameElement createdNameElement = createName(nameElementCommand, when, username, holderStructures);
createdNameElements.add(createdNameElement);
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.CREATE_NAME, TextUtil.ELEMENT_IN, nameElementCommand));
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.CREATE_NAME, TextUtil.ELEMENT_OUT, createdNameElement));
}
}
LOGGER.log(Level.INFO,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_NUMBER_ELEMENTS_IN_OUT,
"Create names",
nameElementCommands.size(),
createdNameElements.size()));
return createdNameElements;
}
@Transactional(propagation = Propagation.MANDATORY)
public NameElement createName(NameElementCommand nameElementCommand, Date when, String username, HolderStructures holderStructures) {
// validation outside method
// transaction
// support a current transaction, throw an exception if none exists
// attributes
// find
// prepare
// create - approved, latest, not deleted, uuid
// return name element for created name
//
// attributes
// parentSystemStructure, parentDeviceStructure, index, description, comment
UUID parentSystemStructure = nameElementCommand.getParentSystemStructure();
UUID parentDeviceStructure = nameElementCommand.getParentDeviceStructure();
String index = nameElementCommand.getIndex();
String description = nameElementCommand.getDescription();
String comment = nameElementCommand.getComment();
// find
// system structure - system group, system, subsystem - one of the three expected to be non-null, other two expected to be null
// device structure - device type - may be null
SystemGroup systemGroup = holderIRepositories.systemGroupRepository().findLatestByUuid(parentSystemStructure.toString());
System system = holderIRepositories.systemRepository().findLatestByUuid(parentSystemStructure.toString());
Subsystem subsystem = holderIRepositories.subsystemRepository().findLatestByUuid(parentSystemStructure.toString());
DeviceType deviceType = null;
if (parentDeviceStructure != null) {
deviceType = holderIRepositories.deviceTypeRepository().findLatestByUuid(parentDeviceStructure.toString());
}
String derivedName = null;
if (systemGroup != null) {
derivedName = NameUtil.getName(systemGroup, deviceType, index, holderStructures);
} else if (system != null) {
derivedName = NameUtil.getName(system, deviceType, index, holderStructures);
} else if (subsystem != null) {
derivedName = NameUtil.getName(subsystem, deviceType, index, holderStructures);
}
// create
Name name = new Name(UUID.randomUUID(),
systemGroup != null ? systemGroup.getUuid() : null,
system != null ? system.getUuid() : null,
subsystem != null ? subsystem.getUuid() : null,
parentDeviceStructure,
index, derivedName, namingConvention.equivalenceClassRepresentative(derivedName),
description, Status.APPROVED, Boolean.TRUE, Boolean.FALSE,
when, username, comment);
nameRepository.createName(name);
return NameElementUtil.getNameElement(name);
}
// ----------------------------------------------------------------------------------------------------
public ResponsePageNameElements readNames(Boolean deleted,
String uuid, String name, String systemStructure, String deviceStructure, String index, String description, String who,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
return readNames(deleted,
uuid, name, systemStructure, deviceStructure, index, description, who,
Boolean.FALSE, orderBy, isAsc, offset, limit);
}
public ResponsePageNameElements readNames(Boolean deleted,
String uuid, String name, String systemStructure, String deviceStructure, String index, String description, String who,
Boolean includeHistory, FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read names
// return name elements for names
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "deleted", deleted));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "uuid", uuid));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "name", name));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "systemStructure", systemStructure));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "deviceStructure", deviceStructure));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "index", index));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "description", description));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "who", who));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "includeHistory", includeHistory));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "orderBy", orderBy));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "isAsc", isAsc));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "offset", offset));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "limit", limit));
}
List<Name> names = null;
Long totalCount = null;
if (Boolean.TRUE.equals(includeHistory)) {
names = nameRepository.readNamesHistory(uuid, name, null, systemStructure, deviceStructure, index, description, who, orderBy, isAsc, offset, limit);
totalCount = nameRepository.countNamesHistory(uuid, name, null, systemStructure, deviceStructure, index, description, who);
} else {
names = nameRepository.readNames(deleted, uuid, name, null, systemStructure, deviceStructure, index, description, who, includeHistory, orderBy, isAsc, offset, limit);
totalCount = nameRepository.countNames(deleted, uuid, name, null, systemStructure, deviceStructure, index, description, who, includeHistory);
}
// one name entry will give one name element
// history does not affect totalCount, sorting, pagination
final List<NameElement> nameElements = NameElementUtil.getNameElements(names);
ResponsePageNameElements response = new ResponsePageNameElements(nameElements, totalCount, nameElements.size(), offset, limit);
LOGGER.log(Level.FINE,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_RESPONSE,
TextUtil.READ_NAMES,
response.toString()));
return response;
}
public ResponsePageNameElements readNames(String uuid) {
// validation outside method
// read uuid or name
// return name elements
// caller to handle name element(s)
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "uuid", uuid));
final List<NameElement> nameElements = Lists.newArrayList();
try {
UUID.fromString(uuid);
Name latestByUuid = holderIRepositories.nameRepository().findLatestByUuid(uuid);
if (latestByUuid != null) {
nameElements.add(NameElementUtil.getNameElement(latestByUuid));
return new ResponsePageNameElements(nameElements, Long.valueOf(nameElements.size()), nameElements.size(), -1, -1);
}
} catch (IllegalArgumentException e) {
return readNames(false,
null, uuid, null, null, null, null, null,
null, null, null, null);
}
return new ResponsePageNameElements(nameElements, Long.valueOf(nameElements.size()), nameElements.size(), -1, -1);
}
public ResponsePageNameElements readNamesSystemStructure(String mnemonicPath, Boolean deleted,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read mnemonic path
// return name elements
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_SYSTEM_STRUCTURE, "mnemonicPath", mnemonicPath));
return readNames(deleted,
null, null, mnemonicPath, null, null, null, null,
orderBy, isAsc, offset, limit);
}
public ResponsePageNameElements readNamesDeviceStructure(String mnemonicPath, Boolean deleted,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read mnemonic path
// return name elements
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_DEVICE_STRUCTURE, "mnemonicPath", mnemonicPath));
return readNames(deleted,
null, null, null,mnemonicPath, null, null, null,
orderBy, isAsc, offset, limit);
}
public ResponsePageNameElements readNamesHistory(
String uuid, String name, String systemStructure, String deviceStructure, String index, String description, String who,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read history for name
// return name elements for names
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "uuid", uuid));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "name", name));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "systemStructure", systemStructure));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "deviceStructure", deviceStructure));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "index", index));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "description", description));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "who", who));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "orderBy", orderBy));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "isAsc", isAsc));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "offset", offset));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "limit", limit));
}
return readNames(null,
uuid, name, systemStructure, deviceStructure, index, description, who,
Boolean.TRUE, orderBy, isAsc, offset, limit);
}
public ResponsePageNameElements readNamesHistory(String uuid,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read history for name
// return name elements for names
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_HISTORY, "uuid", uuid));
return readNames(null,
uuid, null, null, null, null, null, null,
Boolean.TRUE, orderBy, isAsc, offset, limit);
}
public ResponsePageNameElements readNamesLegacy(String name,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read legacy names
// return name elements for names
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "name", name));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "orderBy", orderBy));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "isAsc", isAsc));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "offset", offset));
LOGGER.log(Level.FINE, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES, "limit", limit));
}
List<Name> names = nameRepository.readNamesLegacy(name, orderBy, isAsc, offset, limit);
Long totalCount = nameRepository.countNamesLegacy(name);
final List<NameElement> nameElements = NameElementUtil.getNameElements(names);
ResponsePageNameElements response = new ResponsePageNameElements(nameElements, totalCount, nameElements.size(), offset, limit);
LOGGER.log(Level.FINE,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_RESPONSE,
TextUtil.READ_NAMES,
response.toString()));
return response;
}
public ResponsePageNameElements readNamesStructure(String uuid, Boolean includeIndirect,
FieldName orderBy, Boolean isAsc, Integer offset, Integer limit) {
// validation outside method
// read by structure uuid
// return name elements
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_STRUCTURE, "uuid", uuid));
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.READ_NAMES_STRUCTURE, "includeIndirect", includeIndirect));
// note
// approved, latest
// may need to have deleted parameter
// may solve with queries like
// and n.deleted in (false, true)
// there are different kinds of references to structure ids for names
// direct and indirect
// use INameRepository
// directly
// findLatestBySystemGroupUuid(String)
// findLatestBySystemUuid(String)
// findLatestBySubsystemUuid(String)
// findLatestByDeviceTypeUuid(String)
// indirectly
// findLatestBySystemGroupUuidThroughSystem(String)
// findLatestBySystemGroupUuidThroughSubsystem(String)
// findLatestBySystemUuidThroughSubsystem(String)
// findLatestByDisciplineUuidThroughDeviceType(String)
// findLatestByDeviceGroupUuidThroughDeviceType(String)
// not have - no name refers directly to discipline uuid, device group uuid
// findLatestByDisciplineUuid(String)
// findLatestByDisciplineUuidThroughDeviceGroup(String)
// findLatestByDeviceGroupUuid(String)
// go through all structures and see if / where uuid is found
// system structure and device structure
// uuid in 0 or 1 of kind of structure
// negligible impact on performance for going through different structures
// pagination
// separate pagination when result may be from multiple read operations
// read operations should not contain pagination in such cases
// IS THERE NEED TO MAKE SURE NAMES NOT FOUND AND ADDED TWICE ( OR MORE ) TO RESULT ?
// is java.util.Set is used, then ordering and pagination will be messy
// for start, not consider this
// read - directly
List<Name> names = holderIRepositories.nameRepository().findLatestBySystemGroupUuid(uuid);
names.addAll(holderIRepositories.nameRepository().findLatestBySystemUuid(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestBySubsystemUuid(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestByDeviceTypeUuid(uuid));
if (Boolean.TRUE.equals(includeIndirect)) {
// indirectly - additional read
names.addAll(holderIRepositories.nameRepository().findLatestBySystemGroupUuidThroughSystem(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestBySystemGroupUuidThroughSubsystem(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestBySystemUuidThroughSubsystem(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestByDisciplineUuidThroughDeviceType(uuid));
names.addAll(holderIRepositories.nameRepository().findLatestByDeviceGroupUuidThroughDeviceType(uuid));
}
// pagination
Long totalCount = Long.valueOf(names.size());
final List<NameElement> nameElements = paginate(NameElementUtil.getNameElements(names), offset, limit);
ResponsePageNameElements response = new ResponsePageNameElements(nameElements, totalCount, nameElements.size(), offset, limit);
LOGGER.log(Level.FINE,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_RESPONSE,
TextUtil.READ_NAMES_STRUCTURE,
response.toString()));
return response;
}
private List<NameElement> paginate(List<NameElement> list, Integer offset, Integer limit) {
// intended as pagination when list may contain result from multiple read operations
// read operations should not contain pagination in such cases
if (offset == null || limit == null) {
return list;
}
List<NameElement> listPagination = Lists.newArrayList();
int offsetItems = offset * limit;
int availableItems = list.size() - offsetItems;
if (availableItems > 0) {
for (int i = offsetItems; i < Math.min(offsetItems+availableItems, offsetItems+limit); i++) {
listPagination.add(list.get(i));
}
}
return listPagination;
}
// ----------------------------------------------------------------------------------------------------
public Boolean existsName(String name) {
// validation outside method
// read exists
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.EXISTS_NAME, "name", name));
List<Name> names = nameRepository.readNames(false,
null, name, null, null, null, null, null, null);
return !names.isEmpty();
}
public Boolean isLegacyName(String name) {
// validation outside method
// read names
// note
// legacy - name exists but either parent does not exist (latest, not deleted, by uuid)
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.IS_LEGACY_NAME, "name", name));
List<Name> names = nameRepository.readNames(false, null, name, null, null, null, null, null, null);
ExceptionUtil.validateConditionDataNotFoundException(ValidateUtil.isSize(names, 1), "name not found", name, null);
Name toBeChecked = names.get(0);
// system structure
if (toBeChecked.getSystemGroupUuid() != null) {
// system group
SystemGroup systemGroup = holderIRepositories.systemGroupRepository().findLatestNotDeletedByUuid(toBeChecked.getSystemGroupUuid().toString());
if (systemGroup == null) {
return Boolean.TRUE;
}
} else if (toBeChecked.getSystemUuid() != null) {
// system
// system group
org.openepics.names.repository.model.System system = holderIRepositories.systemRepository().findLatestNotDeletedByUuid(toBeChecked.getSystemUuid().toString());
if (system == null) {
return Boolean.TRUE;
}
SystemGroup systemGroup = holderIRepositories.systemGroupRepository().findLatestNotDeletedByUuid(system.getParentUuid().toString());
if (systemGroup == null) {
return Boolean.TRUE;
}
} else if (toBeChecked.getSubsystemUuid() != null) {
// subsystem
// system
// system group
Subsystem subsystem = holderIRepositories.subsystemRepository().findLatestNotDeletedByUuid(toBeChecked.getSubsystemUuid().toString());
if (subsystem == null) {
return Boolean.TRUE;
}
org.openepics.names.repository.model.System system = holderIRepositories.systemRepository().findLatestNotDeletedByUuid(subsystem.getParentUuid().toString());
if (system == null) {
return Boolean.TRUE;
}
SystemGroup systemGroup = holderIRepositories.systemGroupRepository().findLatestNotDeletedByUuid(system.getParentUuid().toString());
if (systemGroup == null) {
return Boolean.TRUE;
}
}
// device structure
if (toBeChecked.getDeviceTypeUuid() != null) {
// device type
// device group
// discipline
DeviceType deviceType = holderIRepositories.deviceTypeRepository().findLatestNotDeletedByUuid(toBeChecked.getDeviceTypeUuid().toString());
if (deviceType == null) {
return Boolean.TRUE;
}
DeviceGroup deviceGroup = holderIRepositories.deviceGroupRepository().findLatestNotDeletedByUuid(deviceType.getParentUuid().toString());
if (deviceGroup == null) {
return Boolean.TRUE;
}
Discipline discipline = holderIRepositories.disciplineRepository().findLatestNotDeletedByUuid(deviceGroup.getParentUuid().toString());
if (discipline == null) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
public Boolean isValidToCreateName(String name) {
// validation outside method
// validate data - not exists
LOGGER.log(Level.FINE, () -> MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.IS_VALID_TO_CREATE_NAME, "name", name));
// initiate holder of system and device structure content, for performance reasons
// note false to not include deleted entries
HolderStructures holderStructures = new HolderStructures(holderIRepositories, false);
ValidateNameElementUtil.validateNameDataCreate(name, namingConvention, holderRepositories, holderStructures);
return Boolean.TRUE;
}
// ----------------------------------------------------------------------------------------------------
public void validateNamesCreate(NameElementCommand nameElement) {
validateNamesCreate(nameElement, new HolderStructures(holderIRepositories));
}
public void validateNamesCreate(NameElementCommand nameElement, HolderStructures holderStructures) {
// validate name element
// input
// input itself
// data
// data itself
// relative other data
// validate input
ValidateNameElementUtil.validateNameElementInputCreate(nameElement);
// validate data
ValidateNameElementUtil.validateNameElementDataCreate(nameElement, namingConvention, holderIRepositories, nameRepository, holderStructures);
}
public void validateNamesCreate(List<NameElementCommand> nameElements) {
// initiate holder of system and device structure content, for performance reasons
HolderStructures holderStructures = new HolderStructures(holderIRepositories);
for (NameElementCommand nameElement : nameElements) {
validateNamesCreate(nameElement, holderStructures);
}
}
public void validateNamesUpdate(NameElementCommand nameElement) {
validateNamesUpdate(nameElement, new HolderStructures(holderIRepositories));
}
public void validateNamesUpdate(NameElementCommand nameElement, HolderStructures holderStructures) {
// validate name element
// input
// input itself
// data
// data itself
// relative other data
// validate input
ValidateNameElementUtil.validateNameElementInputUpdate(nameElement);
// validate data
ValidateNameElementUtil.validateNameElementDataUpdate(nameElement, namingConvention, holderIRepositories, nameRepository, holderStructures);
}
public void validateNamesUpdate(List<NameElementCommand> nameElements) {
// initiate holder of system and device structure content, for performance reasons
HolderStructures holderStructures = new HolderStructures(holderIRepositories);
for (NameElementCommand nameElement : nameElements) {
validateNamesUpdate(nameElement, holderStructures);
}
}
public void validateNamesDelete(NameElementCommand nameElement) {
validateNamesDelete(nameElement, new HolderStructures(holderIRepositories));
}
public void validateNamesDelete(NameElementCommand nameElement, HolderStructures holderStructures) {
// validate name element
// input
// input itself
// data
// data itself
// relative other data
// validate input
ValidateNameElementUtil.validateNameElementInputDelete(nameElement);
// validate data
ValidateNameElementUtil.validateNameElementDataDelete(nameElement, namingConvention, holderIRepositories, nameRepository, holderStructures);
}
public void validateNamesDelete(List<NameElementCommand> nameElements) {
// initiate holder of system and device structure content, for performance reasons
HolderStructures holderStructures = new HolderStructures(holderIRepositories);
for (NameElementCommand nameElement : nameElements) {
validateNamesDelete(nameElement, holderStructures);
}
}
// ----------------------------------------------------------------------------------------------------
@Transactional
public List<NameElement> updateNames(List<NameElementCommand> nameElementCommands, String username) {
// validation outside method
// transaction
// for each name element
// attributes
// find
// update name to not latest
// find
// insert name to latest, not deleted, with data
// handle name element for updated name
// no notify
// return name elements for updated names
//
// attributes
// uuid, parentSystemStructure, parentDeviceStructure, index, description, comment
// initiate holder of system and device structure content, for performance reasons
HolderStructures holderStructures = new HolderStructures(holderIRepositories);
Date when = new Date();
final List<NameElement> updatedNameElements = Lists.newArrayList();
for (NameElementCommand nameElementCommand : nameElementCommands) {
// update not latest, not deleted
// create latest, not deleted
UUID uuid = nameElementCommand.getUuid();
UUID parentSystemStructure = nameElementCommand.getParentSystemStructure();
UUID parentDeviceStructure = nameElementCommand.getParentDeviceStructure();
String index = nameElementCommand.getIndex();
String description = nameElementCommand.getDescription();
String comment = nameElementCommand.getComment();
Name name = holderIRepositories.nameRepository().findLatestByUuid(uuid.toString());
if (name == null) {
continue;
}
// skip if name element has same content as name
// proceed without fail
if (NameElementUtil.hasSameContent(nameElementCommand, name, holderIRepositories, holderStructures)) {
continue;
}
// update
name.setLatest(Boolean.FALSE);
nameRepository.updateName(name);
// find out system group, system, subsystem
// one of the three expected to be non-null, other two expected to be null
SystemGroup systemGroup = holderIRepositories.systemGroupRepository().findLatestByUuid(parentSystemStructure.toString());
System system = holderIRepositories.systemRepository().findLatestByUuid(parentSystemStructure.toString());
Subsystem subsystem = holderIRepositories.subsystemRepository().findLatestByUuid(parentSystemStructure.toString());
DeviceType deviceType = null;
if (parentDeviceStructure != null) {
deviceType = holderIRepositories.deviceTypeRepository().findLatestByUuid(parentDeviceStructure.toString());
}
String derivedName = null;
if (systemGroup != null) {
derivedName = NameUtil.getName(systemGroup, deviceType, index, holderStructures);
} else if (system != null) {
derivedName = NameUtil.getName(system, deviceType, index, holderStructures);
} else if (subsystem != null) {
derivedName = NameUtil.getName(subsystem, deviceType, index, holderStructures);
}
// create
name = new Name(uuid,
systemGroup != null ? systemGroup.getUuid() : null,
system != null ? system.getUuid() : null,
subsystem != null ? subsystem.getUuid() : null,
parentDeviceStructure,
index, derivedName, namingConvention.equivalenceClassRepresentative(derivedName),
description, Status.APPROVED, Boolean.TRUE, Boolean.FALSE,
when, username, comment);
nameRepository.createName(name);
NameElement updatedNameElement = NameElementUtil.getNameElement(name);
updatedNameElements.add(updatedNameElement);
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.UPDATE_NAME, TextUtil.ELEMENT_IN, nameElementCommand));
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.UPDATE_NAME, TextUtil.ELEMENT_OUT, updatedNameElement));
}
}
LOGGER.log(Level.INFO,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_NUMBER_ELEMENTS_IN_OUT,
"Update names",
nameElementCommands.size(),
updatedNameElements.size()));
return updatedNameElements;
}
@Transactional(propagation = Propagation.MANDATORY)
public List<NameElement> updateNames(Structure previousStructure, Structure structure, String username) {
// validation outside method
// transaction
// support a current transaction, throw an exception if none exists
// find out names referenced by structure
// not for device group
// sg, sys, sys-sub, sg:di-dt-idx, sys:di-dt-idx, sys-sub:di-dt-idx
// prepare name element commands
// update names - re-calculate names
// return name elements for updated names
List<NameElement> updatedNameElements = Lists.newArrayList();
if (previousStructure != null
&& structure != null
&& !StringUtils.equals(structure.getMnemonic(), previousStructure.getMnemonic())
&& !StringUtils.isEmpty(structure.getMnemonic())) {
List<Name> names = null;
List<NameElementCommand> nameElements = Lists.newArrayList();
UUID parentSystemStructure = null;
if (previousStructure instanceof SystemGroup && structure instanceof SystemGroup) {
// find
// prepare
names = holderIRepositories.nameRepository().findLatestBySystemGroupUuid(structure.getUuid().toString());
for (Name name : names) {
nameElements.add(
new NameElementCommand(
name.getUuid(), name.getSystemGroupUuid(), name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
} else if (previousStructure instanceof System && structure instanceof System) {
// find
// prepare
names = holderIRepositories.nameRepository().findLatestBySystemUuid(structure.getUuid().toString());
for (Name name : names) {
nameElements.add(
new NameElementCommand(
name.getUuid(), name.getSystemUuid(), name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
names = holderIRepositories.nameRepository().findLatestBySystemUuidThroughSubsystem(structure.getUuid().toString());
for (Name name : names) {
nameElements.add(
new NameElementCommand(
name.getUuid(), name.getSubsystemUuid(), name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
} else if (previousStructure instanceof Subsystem && structure instanceof Subsystem) {
// find
// prepare
names = holderIRepositories.nameRepository().findLatestBySubsystemUuid(structure.getUuid().toString());
for (Name name : names) {
nameElements.add(
new NameElementCommand(
name.getUuid(), name.getSubsystemUuid(), name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
} else if (previousStructure instanceof Discipline && structure instanceof Discipline) {
// find
// prepare
names = holderIRepositories.nameRepository().findLatestByDisciplineUuidThroughDeviceType(structure.getUuid().toString());
for (Name name : names) {
parentSystemStructure = name.getSubsystemUuid() != null
? name.getSubsystemUuid()
: name.getSystemUuid() != null
? name.getSystemUuid()
: name.getSystemGroupUuid() != null
? name.getSystemGroupUuid()
: null;
nameElements.add(
new NameElementCommand(
name.getUuid(), parentSystemStructure, name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
} else if (previousStructure instanceof DeviceType && structure instanceof DeviceType) {
// find
// prepare
names = holderIRepositories.nameRepository().findLatestByDeviceTypeUuid(structure.getUuid().toString());
for (Name name : names) {
parentSystemStructure = name.getSubsystemUuid() != null
? name.getSubsystemUuid()
: name.getSystemUuid() != null
? name.getSystemUuid()
: name.getSystemGroupUuid() != null
? name.getSystemGroupUuid()
: null;
nameElements.add(
new NameElementCommand(
name.getUuid(), parentSystemStructure, name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getDescription(), UPDATE_AFTER_APPROVE_STRUCTURE_CHANGE));
}
}
// update names
// use active transaction or, if not available, throw exception
updatedNameElements = updateNames(nameElements, username);
}
return updatedNameElements;
}
// ----------------------------------------------------------------------------------------------------
@Transactional
public List<NameElement> deleteNames(List<NameElementCommand> nameElementCommands, String username) {
// validation outside method
// transaction
// for each name element
// attributes
// find
// update name to not latest
// insert name to latest, deleted
// handle name element for deleted name
// no notify
// return name elements for deleted names
//
// attributes
// uuid, comment
Date when = new Date();
final List<NameElement> deletedNameElements = Lists.newArrayList();
for (NameElementCommand nameElementCommand : nameElementCommands) {
UUID uuid = nameElementCommand.getUuid();
String comment = nameElementCommand.getComment();
Name name = holderIRepositories.nameRepository().findLatestByUuid(uuid.toString());
if (name == null) {
continue;
}
name.setLatest(Boolean.FALSE);
nameRepository.updateName(name);
name = new Name(uuid,
name.getSystemGroupUuid(),
name.getSystemUuid(),
name.getSubsystemUuid(),
name.getDeviceTypeUuid(),
name.getInstanceIndex(), name.getConventionName(), name.getConventionNameEquivalence(),
name.getDescription(), Status.APPROVED, Boolean.TRUE, Boolean.TRUE,
when, username, comment);
nameRepository.createName(name);
NameElement deletedNameElement = NameElementUtil.getNameElement(name);
deletedNameElements.add(deletedNameElement);
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.DELETE_NAME, TextUtil.ELEMENT_IN, nameElementCommand));
LOGGER.log(Level.FINER, MessageFormat.format(TextUtil.DESCRIPTION_NAME_VALUE, TextUtil.DELETE_NAME, TextUtil.ELEMENT_OUT, deletedNameElement));
}
}
LOGGER.log(Level.INFO,
() -> MessageFormat.format(
TextUtil.DESCRIPTION_NUMBER_ELEMENTS_IN_OUT,
"Delete names",
nameElementCommands.size(),
deletedNameElements.size()));
return deletedNameElements;
}
}