Java tutorial
/*************************************************************************** Copyright (c) 2016, EPAM SYSTEMS INC 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. ****************************************************************************/ package com.epam.dlab.backendapi.dao; import com.epam.dlab.backendapi.util.DateRemoverUtil; import com.epam.dlab.dto.*; import com.epam.dlab.dto.exploratory.ExploratoryStatusDTO; import com.epam.dlab.exceptions.DlabException; import com.epam.dlab.exceptions.ResourceNotFoundException; import com.google.inject.Singleton; import com.mongodb.client.result.UpdateResult; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.bson.conversions.Bson; import java.util.*; import java.util.stream.Collectors; import static com.epam.dlab.backendapi.dao.MongoCollections.USER_INSTANCES; import static com.epam.dlab.backendapi.dao.SchedulerJobDAO.SCHEDULER_DATA; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Projections.*; import static com.mongodb.client.model.Updates.set; import static org.apache.commons.lang3.StringUtils.EMPTY; /** * DAO for user exploratory. */ @Slf4j @Singleton public class ExploratoryDAO extends BaseDAO { public static final String COMPUTATIONAL_RESOURCES = "computational_resources"; static final String EXPLORATORY_ID = "exploratory_id"; static final String EXPLORATORY_NAME = "exploratory_name"; static final String UPTIME = "up_time"; private static final String COMPUTATIONAL_NAME = "computational_name"; private static final String EXPLORATORY_URL = "exploratory_url"; private static final String EXPLORATORY_URL_DESC = "description"; private static final String EXPLORATORY_URL_URL = "url"; private static final String EXPLORATORY_USER = "exploratory_user"; private static final String EXPLORATORY_PASS = "exploratory_pass"; private static final String EXPLORATORY_PRIVATE_IP = "private_ip"; public static final String EXPLORATORY_NOT_FOUND_MSG = "Exploratory for user %s with name %s not found"; public ExploratoryDAO() { log.info("{} is initialized", getClass().getSimpleName()); } static Bson exploratoryCondition(String user, String exploratoryName) { return and(eq(USER, user), eq(EXPLORATORY_NAME, exploratoryName)); } private Bson exploratoryStatusCondition(String user, UserInstanceStatus... exploratoryStatuses) { return and(eq(USER, user), in(STATUS, statusList(exploratoryStatuses))); } private static Bson runningExploratoryCondition(String user, String exploratoryName) { return and(eq(USER, user), and(eq(EXPLORATORY_NAME, exploratoryName), eq(STATUS, UserInstanceStatus.RUNNING.toString()))); } static Bson runningExploratoryAndComputationalCondition(String user, String exploratoryName, String computationalName) { return and(eq(USER, user), and(eq(EXPLORATORY_NAME, exploratoryName), eq(STATUS, UserInstanceStatus.RUNNING.toString()), eq(COMPUTATIONAL_RESOURCES + "." + COMPUTATIONAL_NAME, computationalName), eq(COMPUTATIONAL_RESOURCES + "." + STATUS, UserInstanceStatus.RUNNING.toString()))); } /** * Finds and returns the list of user resources. * * @param user name * @return list of user resources */ public Iterable<Document> findExploratory(String user) { return find(USER_INSTANCES, eq(USER, user), fields( exclude(ExploratoryLibDAO.EXPLORATORY_LIBS, ExploratoryLibDAO.COMPUTATIONAL_LIBS, SCHEDULER_DATA))); } /** * Finds and returns the unique id for exploratory. * * @param user user name. * @param exploratoryName the name of exploratory. */ public String fetchExploratoryId(String user, String exploratoryName) { return findOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), fields(include(EXPLORATORY_ID), excludeId())).orElse(new Document()) .getOrDefault(EXPLORATORY_ID, EMPTY).toString(); } /** * Finds and returns the status of exploratory. * * @param user user name. * @param exploratoryName the name of exploratory. */ public UserInstanceStatus fetchExploratoryStatus(String user, String exploratoryName) { return UserInstanceStatus.of(findOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), fields(include(STATUS), excludeId())).orElse(new Document()).getOrDefault(STATUS, EMPTY) .toString()); } /** * Finds and returns the info of all user's running notebooks. * * @param user user name. */ public List<UserInstanceDTO> fetchRunningExploratoryFields(String user) { return getUserInstances(and(eq(USER, user), eq(STATUS, UserInstanceStatus.RUNNING.toString())), false); } /** * Finds and returns the info of all user's notebooks whose status is present among predefined ones. * * @param user user name. * @param computationalFieldsRequired true/false. * @param statuses array of statuses. */ public List<UserInstanceDTO> fetchUserExploratoriesWhereStatusIn(String user, boolean computationalFieldsRequired, UserInstanceStatus... statuses) { final List<String> statusList = statusList(statuses); return getUserInstances(and(eq(USER, user), in(STATUS, statusList)), computationalFieldsRequired); } /** * Finds and returns the info of all user's notebooks whose status or status of affiliated computational resource * is present among predefined ones. * * @param user user name. * @param exploratoryStatuses array of exploratory statuses. * @param computationalStatuses array of computational statuses. */ public List<UserInstanceDTO> fetchUserExploratoriesWhereStatusIn(String user, List<UserInstanceStatus> exploratoryStatuses, UserInstanceStatus... computationalStatuses) { final List<String> exploratoryStatusList = statusList(exploratoryStatuses); final List<String> computationalStatusList = statusList(computationalStatuses); return getUserInstances(and(eq(USER, user), or(in(STATUS, exploratoryStatusList), in(COMPUTATIONAL_RESOURCES + "." + STATUS, computationalStatusList))), false); } /** * Finds and returns the info of all user's notebooks whose status is absent among predefined ones. * * @param user user name. * @param statuses array of statuses. */ public List<UserInstanceDTO> fetchUserExploratoriesWhereStatusNotIn(String user, UserInstanceStatus... statuses) { final List<String> statusList = statusList(statuses); return getUserInstances(and(eq(USER, user), not(in(STATUS, statusList))), false); } private List<UserInstanceDTO> getUserInstances(Bson condition, boolean computationalFieldsRequired) { return stream(getCollection(USER_INSTANCES).find(condition) .projection(computationalFieldsRequired ? null : fields(exclude(COMPUTATIONAL_RESOURCES)))) .map(d -> convertFromDocument(d, UserInstanceDTO.class)).collect(Collectors.toList()); } /** * Finds and returns the info about all exploratories in database. **/ public List<UserInstanceDTO> getInstances() { return stream(getCollection(USER_INSTANCES).find()).map(d -> convertFromDocument(d, UserInstanceDTO.class)) .collect(Collectors.toList()); } /** * Finds and returns the info of exploratory (without info about computational resources). * * @param user user name. * @param exploratoryName the name of exploratory. */ public UserInstanceDTO fetchExploratoryFields(String user, String exploratoryName) { return getExploratory(user, exploratoryName).orElseThrow(() -> new ResourceNotFoundException( String.format(EXPLORATORY_NOT_FOUND_MSG, user, exploratoryName))); } /** * Checks if exploratory exists. * * @param user user name. * @param exploratoryName the name of exploratory. */ public boolean isExploratoryExist(String user, String exploratoryName) { return getExploratory(user, exploratoryName).isPresent(); } private Optional<UserInstanceDTO> getExploratory(String user, String exploratoryName) { return findOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), fields(exclude(COMPUTATIONAL_RESOURCES)), UserInstanceDTO.class); } /** * Finds and returns the info of running exploratory with running cluster. * * @param user user name. * @param exploratoryName name of exploratory. * @param computationalName name of cluster */ public UserInstanceDTO fetchExploratoryFields(String user, String exploratoryName, String computationalName) { Optional<UserInstanceDTO> opt = findOne(USER_INSTANCES, runningExploratoryAndComputationalCondition(user, exploratoryName, computationalName), UserInstanceDTO.class); if (opt.isPresent()) { return opt.get(); } throw new DlabException(String.format("Running notebook %s with running cluster %s not found for user %s", exploratoryName, computationalName, user)); } /** * Finds and returns the info of running exploratory. * * @param user user name. * @param exploratoryName name of exploratory. */ public UserInstanceDTO fetchRunningExploratoryFields(String user, String exploratoryName) { return findOne(USER_INSTANCES, runningExploratoryCondition(user, exploratoryName), fields(exclude(COMPUTATIONAL_RESOURCES)), UserInstanceDTO.class) .orElseThrow(() -> new DlabException( String.format("Running exploratory instance for user %s with name %s not found.", user, exploratoryName))); } /** * Inserts the info about notebook into Mongo database. * * @param dto the info about notebook */ public void insertExploratory(UserInstanceDTO dto) { insertOne(USER_INSTANCES, dto); } /** * Updates the status of exploratory in Mongo database. * * @param dto object of exploratory status info. * @return The result of an update operation. */ public UpdateResult updateExploratoryStatus(StatusEnvBaseDTO<?> dto) { return updateOne(USER_INSTANCES, exploratoryCondition(dto.getUser(), dto.getExploratoryName()), set(STATUS, dto.getStatus())); } /** * Updates the status for all user's corresponding exploratories in Mongo database. * * @param newExploratoryStatus new status for exploratories. * @param user user name. * @param oldExploratoryStatuses old statuses of exploratories. */ public void updateStatusForExploratories(UserInstanceStatus newExploratoryStatus, String user, UserInstanceStatus... oldExploratoryStatuses) { updateMany(USER_INSTANCES, exploratoryStatusCondition(user, oldExploratoryStatuses), set(STATUS, newExploratoryStatus.toString())); } /** * Updates status for single exploratory in Mongo database. * * @param user user. * @param exploratoryName name of exploratory. * @param newStatus new status of exploratory. * @return The result of an update operation. */ public UpdateResult updateStatusForExploratory(String user, String exploratoryName, UserInstanceStatus newStatus) { return updateOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), set(STATUS, newStatus.toString())); } /** * Updates the scheduler's data for exploratory in Mongo database. * * @param user user. * @param exploratoryName name of exploratory. * @param dto object of scheduler data. * @return The result of an update operation. */ public UpdateResult updateSchedulerDataForUserAndExploratory(String user, String exploratoryName, SchedulerJobDTO dto) { return updateOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), set(SCHEDULER_DATA, Objects.isNull(dto) ? null : convertToBson(dto))); } /** * Updates the requirement for reuploading key for all user's corresponding exploratories in Mongo database. * * @param user user name. * @param reuploadKeyRequired true/false. * @param exploratoryStatuses statuses of exploratory. */ public void updateReuploadKeyForExploratories(String user, boolean reuploadKeyRequired, UserInstanceStatus... exploratoryStatuses) { updateMany(USER_INSTANCES, exploratoryStatusCondition(user, exploratoryStatuses), set(REUPLOAD_KEY_REQUIRED, reuploadKeyRequired)); } /** * Updates the requirement for reuploading key for single exploratory in Mongo database. * * @param user user name. * @param exploratoryName exploratory's name * @param reuploadKeyRequired true/false. */ public void updateReuploadKeyForExploratory(String user, String exploratoryName, boolean reuploadKeyRequired) { updateOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), set(REUPLOAD_KEY_REQUIRED, reuploadKeyRequired)); } /** * Updates the info of exploratory in Mongo database. * * @param dto object of exploratory status info. * @return The result of an update operation. */ @SuppressWarnings("serial") public UpdateResult updateExploratoryFields(ExploratoryStatusDTO dto) { Document values = new Document(STATUS, dto.getStatus()).append(UPTIME, dto.getUptime()); if (dto.getInstanceId() != null) { values.append(INSTANCE_ID, dto.getInstanceId()); } if (dto.getErrorMessage() != null) { values.append(ERROR_MESSAGE, DateRemoverUtil.removeDateFormErrorMessage(dto.getErrorMessage())); } if (dto.getExploratoryId() != null) { values.append(EXPLORATORY_ID, dto.getExploratoryId()); } if (dto.getResourceUrl() != null) { values.append(EXPLORATORY_URL, dto.getResourceUrl().stream().map(url -> { LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put(EXPLORATORY_URL_DESC, url.getDescription()); map.put(EXPLORATORY_URL_URL, url.getUrl()); return map; }).collect(Collectors.toList())); } else if (dto.getPrivateIp() != null) { UserInstanceDTO inst = fetchExploratoryFields(dto.getUser(), dto.getExploratoryName()); if (!inst.getPrivateIp().equals(dto.getPrivateIp()) && inst.getResourceUrl() != null) { // IP was // changed values.append(EXPLORATORY_URL, inst.getResourceUrl().stream() .map(url -> replaceIp(dto.getPrivateIp(), inst, url)).collect(Collectors.toList())); } } if (dto.getPrivateIp() != null) { values.append(EXPLORATORY_PRIVATE_IP, dto.getPrivateIp()); } if (dto.getExploratoryUser() != null) { values.append(EXPLORATORY_USER, dto.getExploratoryUser()); } if (dto.getExploratoryPassword() != null) { values.append(EXPLORATORY_PASS, dto.getExploratoryPassword()); } return updateOne(USER_INSTANCES, exploratoryCondition(dto.getUser(), dto.getExploratoryName()), new Document(SET, values)); } public void updateExploratoryIp(String user, String ip, String exploratoryName) { UserInstanceDTO inst = fetchExploratoryFields(user, exploratoryName); if (!inst.getPrivateIp().equals(ip)) { Document values = new Document(); values.append(EXPLORATORY_PRIVATE_IP, ip); if (inst.getResourceUrl() != null) { values.append(EXPLORATORY_URL, inst.getResourceUrl().stream().map(url -> replaceIp(ip, inst, url)) .collect(Collectors.toList())); } updateOne(USER_INSTANCES, exploratoryCondition(user, exploratoryName), new Document(SET, values)); } } private Map<String, String> replaceIp(String ip, UserInstanceDTO inst, ResourceURL url) { Map<String, String> map = new LinkedHashMap<>(); map.put(EXPLORATORY_URL_DESC, url.getDescription()); map.put(EXPLORATORY_URL_URL, url.getUrl().replace(inst.getPrivateIp(), ip)); return map; } }