org.optaplanner.examples.conferencescheduling.persistence.ConferenceSchedulingCfpDevoxxImporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of optaplanner-examples Show documentation
Show all versions of optaplanner-examples Show documentation
OptaPlanner solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the examples which demonstrate how to use it in a normal Java application.
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* 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 org.optaplanner.examples.conferencescheduling.persistence;
import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import org.apache.commons.lang3.tuple.Pair;
import org.optaplanner.examples.conferencescheduling.domain.ConferenceParametrization;
import org.optaplanner.examples.conferencescheduling.domain.ConferenceSolution;
import org.optaplanner.examples.conferencescheduling.domain.Room;
import org.optaplanner.examples.conferencescheduling.domain.Speaker;
import org.optaplanner.examples.conferencescheduling.domain.Talk;
import org.optaplanner.examples.conferencescheduling.domain.TalkType;
import org.optaplanner.examples.conferencescheduling.domain.Timeslot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Import an instance of a Devoxx Conference from an API created from https://github.com/nicmarti/cfp-devoxx
*/
public class ConferenceSchedulingCfpDevoxxImporter {
private static final Logger LOGGER = LoggerFactory.getLogger(ConferenceSchedulingCfpDevoxxImporter.class);
private static final String ZONE_ID = "Europe/Paris";
private static final String[] SMALL_ROOMS_TYPE_NAMES = {"lab", "bof"};
private static final String[] LARGE_ROOMS_TYPE_NAMES = {"tia", "uni", "conf", "Deep Dive",
"Opening Keynote", "Closing Keynote", "Quickie Sessions", "quick"};
private static final String[] IGNORED_TALK_TYPES = {"ignite", "key"};
private static final String[] IGNORED_ROOM_IDS = {"ExhibitionHall"};
private static final String[] IGNORED_SPEAKER_NAMES = {"Devoxx Partner"};
private String conferenceBaseUrl;
private Map talkTypeNameToTalkTypeMap;
private Map roomIdToRoomMap;
private Map speakerNameToSpeakerMap;
private Map talkCodeToTalkMap;
private Set talkUrlSet;
private Set trackIdSet;
private ConferenceSolution solution;
private Map timeslotTalkTypeToTotalMap = new HashMap<>();
private Map talkTalkTypeToTotalMap = new HashMap<>();
public ConferenceSchedulingCfpDevoxxImporter(String conferenceBaseUrl) {
this.conferenceBaseUrl = conferenceBaseUrl;
}
public ConferenceSolution importSolution() {
solution = new ConferenceSolution();
solution.setId(0L);
solution.setConferenceName(getConferenceName());
ConferenceParametrization parametrization = new ConferenceParametrization();
parametrization.setId(0L);
solution.setParametrization(parametrization);
importTalkTypeList();
importTrackIdSet();
importRoomList();
importSpeakerList();
importTalkList();
importTimeslotList();
for (TalkType talkType : solution.getTalkTypeList()) {
LOGGER.info(talkType.getName()
+ ": Timeslots Total is " + (timeslotTalkTypeToTotalMap.get(talkType.getName()) == null ? 0 : timeslotTalkTypeToTotalMap.get(talkType.getName()))
+ ", Talks Total is " + (talkTalkTypeToTotalMap.get(talkType.getName()) == null ? 0 : talkTalkTypeToTotalMap.get(talkType.getName()))
);
}
return solution;
}
private String getConferenceName() {
LOGGER.debug("Sending a request to: " + conferenceBaseUrl);
JsonObject conferenceObject = readJson(conferenceBaseUrl, JsonReader::readObject);
return conferenceObject.getString("eventCode");
}
private void importTalkTypeList() {
this.talkTypeNameToTalkTypeMap = new HashMap<>();
List talkTypeList = new ArrayList<>();
String proposalTypeUrl = conferenceBaseUrl + "/proposalTypes";
LOGGER.debug("Sending a request to: " + proposalTypeUrl);
JsonObject rootObject = readJson(proposalTypeUrl, JsonReader::readObject);
JsonArray talkTypeArray = rootObject.getJsonArray("proposalTypes");
for (int i = 0; i < talkTypeArray.size(); i++) {
JsonObject talkTypeObject = talkTypeArray.getJsonObject(i);
String talkTypeName = talkTypeObject.getString("id");
if (talkTypeNameToTalkTypeMap.keySet().contains(talkTypeName)) {
LOGGER.warn("Duplicate talk type in " + proposalTypeUrl
+ " at index " + i + ".");
continue;
}
TalkType talkType = new TalkType((long) i, talkTypeName);
talkType.setCompatibleRoomSet(new HashSet<>());
talkType.setCompatibleTimeslotSet(new HashSet<>());
talkTypeList.add(talkType);
talkTypeNameToTalkTypeMap.put(talkTypeName, talkType);
}
solution.setTalkTypeList(talkTypeList);
}
private void importTrackIdSet() {
this.trackIdSet = new HashSet<>();
String tracksUrl = conferenceBaseUrl + "/tracks";
LOGGER.debug("Sending a request to: " + tracksUrl);
JsonObject rootObject = readJson(tracksUrl, JsonReader::readObject);
JsonArray tracksArray = rootObject.getJsonArray("tracks");
for (int i = 0; i < tracksArray.size(); i++) {
trackIdSet.add(tracksArray.getJsonObject(i).getString("id"));
}
}
private void importRoomList() {
this.roomIdToRoomMap = new HashMap<>();
List roomList = new ArrayList<>();
String roomsUrl = conferenceBaseUrl + "/rooms/";
LOGGER.debug("Sending a request to: " + roomsUrl);
JsonObject rootObject = readJson(roomsUrl, JsonReader::readObject);
JsonArray roomArray = rootObject.getJsonArray("rooms");
for (int i = 0; i < roomArray.size(); i++) {
JsonObject roomObject = roomArray.getJsonObject(i);
String id = roomObject.getString("id");
int capacity = roomObject.getInt("capacity");
if (!Arrays.asList(IGNORED_ROOM_IDS).contains(id)) {
Room room = new Room((long) i);
room.setName(id);
room.setCapacity(capacity);
room.setTalkTypeSet(getTalkTypeSetForCapacity(capacity));
for (TalkType talkType : room.getTalkTypeSet()) {
talkType.getCompatibleRoomSet().add(room);
}
room.setTagSet(new HashSet<>());
room.setUnavailableTimeslotSet(new HashSet<>());
roomList.add(room);
roomIdToRoomMap.put(id, room);
}
}
roomList.sort(Comparator.comparing(Room::getName));
solution.setRoomList(roomList);
}
private void importSpeakerList() {
this.speakerNameToSpeakerMap = new HashMap<>();
this.talkUrlSet = new HashSet<>();
List speakerList = new ArrayList<>();
String speakersUrl = conferenceBaseUrl + "/speakers";
LOGGER.debug("Sending a request to: " + speakersUrl);
JsonArray speakerArray = readJson(speakersUrl, JsonReader::readArray);
for (int i = 0; i < speakerArray.size(); i++) {
String speakerUrl = speakerArray.getJsonObject(i).getJsonArray("links").getJsonObject(0).getString("href");
LOGGER.debug("Sending a request to: " + speakerUrl);
JsonObject speakerObject = readJson(speakerUrl, JsonReader::readObject);
String speakerId = speakerObject.getString("uuid");
String speakerName = speakerObject.getString("firstName") + " " + speakerObject.getString("lastName");
if (Arrays.asList(IGNORED_SPEAKER_NAMES).contains(speakerName)) {
continue;
}
Speaker speaker = new Speaker((long) i);
speaker.setName(speakerName);
speaker.withPreferredRoomTagSet(new HashSet<>())
.withPreferredTimeslotTagSet(new HashSet<>())
.withProhibitedRoomTagSet(new HashSet<>())
.withProhibitedTimeslotTagSet(new HashSet<>())
.withRequiredRoomTagSet(new HashSet<>())
.withRequiredTimeslotTagSet(new HashSet<>())
.withUnavailableTimeslotSet(new HashSet<>())
.withUndesiredRoomTagSet(new HashSet<>())
.withUndesiredTimeslotTagSet(new HashSet<>());
speakerList.add(speaker);
if (speakerNameToSpeakerMap.keySet().contains(speakerName)) {
throw new IllegalStateException("Speaker (" + speakerName + ") with id (" + speakerId
+ ") already exists in the speaker list");
}
speakerNameToSpeakerMap.put(speakerName, speaker);
JsonArray speakerTalksArray = speakerObject.getJsonArray("acceptedTalks");
for (int j = 0; j < speakerTalksArray.size(); j++) {
String talkUrl = speakerTalksArray.getJsonObject(j).getJsonArray("links").getJsonObject(0).getString("href");
talkUrlSet.add(talkUrl);
}
}
speakerList.sort(Comparator.comparing(Speaker::getName));
solution.setSpeakerList(speakerList);
}
/* TODO: Uncomment this when the REST api exposes the talks
private void importTalkList() {
this.talkCodeToTalkMap = new HashMap<>();
List talkList = new ArrayList<>();
Long talkId = 0L;
for (String talkUrl : this.talkUrlSet) {
LOGGER.debug("Sending a request to: " + talkUrl);
JsonObject talkObject = readJson(talkUrl, JsonReader::readObject);
String code = talkObject.getString("id");
String title = talkObject.getString("title");
String talkTypeName = talkObject.getString("talkType");
Set themeTrackSet = new HashSet<>(Arrays.asList(talkObject.getString("trackId")));
if (!trackIdSet.containsAll(themeTrackSet)) {
throw new IllegalStateException("The talk (" + title + ") with id (" + code
+ ") contains trackId + (" + trackIdSet + ") that doesn't exist in the trackIdSet.");
}
String languageg = talkObject.getString("lang");
List speakerList = talkObject.getJsonArray("speakers").stream()
.map(speakerJsonValue -> {
JsonReader jsonReader = Json.createReader(new StringReader(speakerJsonValue.toString()));
JsonObject speakerJsonObject = jsonReader.readObject();
String speakerName = speakerJsonObject.getString("name");
Speaker speaker = speakerNameToSpeakerMap.get(speakerName);
if (speaker == null) {
*/
/* throw new IllegalStateException("The talk (" + title + ") with id (" + code
+ ") contains a speaker (" + speakerName + ", " + speakerJsonObject.getJsonObject("link").getString("href")
+ ") that doesn't exist in speaker list.");*//*
//TODO: Temporary workaround until the missing speakers issue is fuxed, once fixed uncomment the throw block above and delete this
LOGGER.warn("The talk (" + code + ": " + title + ", " + talkUrl
+ ") has a speaker (" + speakerName + ", " + speakerJsonObject.getJsonObject("link").getString("href")
+ ") that doesn't exist in speaker list.");
String speakerUrl = speakerJsonObject.getJsonObject("link").getString("href");
LOGGER.debug("Sending a request to: " + speakerUrl);
JsonObject speakerObject = readJson(speakerUrl, JsonReader::readObject);
String speakerId = speakerObject.getString("uuid");
speaker = new Speaker((long) solution.extractSpeakerList().size());
speaker.setName(speakerName);
speaker.withPreferredRoomTagSet(new HashSet<>())
.withPreferredTimeslotTagSet(new HashSet<>())
.withProhibitedRoomTagSet(new HashSet<>())
.withProhibitedTimeslotTagSet(new HashSet<>())
.withRequiredRoomTagSet(new HashSet<>())
.withRequiredTimeslotTagSet(new HashSet<>())
.withUnavailableTimeslotSet(new HashSet<>())
.withUndesiredRoomTagSet(new HashSet<>())
.withUndesiredTimeslotTagSet(new HashSet<>());
if (speakerNameToSpeakerMap.keySet().contains(speakerName)) {
throw new IllegalStateException("Speaker (" + speakerName + ") with id (" + speakerId
+ ") already exists in the speaker list");
}
speakerNameToSpeakerMap.put(speakerName, speaker);
solution.extractSpeakerList().add(speaker);
}
return speaker;
})
.collect(Collectors.toList());
Talk talk = createTalk(talkId++, code, title, talkTypeName, themeTrackSet, languageg, speakerList);
talkCodeToTalkMap.put(code, talk);
talkList.add(talk);
}
solution.setTalkList(talkList);
}
*/
private void importTalkList() {
this.talkCodeToTalkMap = new HashMap<>();
List talkList = new ArrayList<>();
Long talkId = 0L;
String talksPath = getClass().getResource("devoxxBE").toString();
String[] confFiles = {"BOF", "Conf14Sept2018", "DeepDive", "HandsOnLabs", "Quickies", "ToolsInAction"};
for (String confType : confFiles) {
LOGGER.debug("Sending a request to: " + talksPath + "/" + confType + ".json");
JsonArray talksArray = readJson(talksPath + "/" + confType + ".json", JsonReader::readObject)
.getJsonObject("approvedTalks").getJsonArray("talks");
for (int i = 0; i < talksArray.size(); i++) {
JsonObject talkObject = talksArray.getJsonObject(i);
String code = talkObject.getString("id");
String title = talkObject.getString("title").substring(5);
String talkTypeName = talkObject.getJsonObject("talkType").getString("id");
Set themeTrackSet = extractThemeTrackSet(talkObject, code, title);
String language = talkObject.getString("lang");
int audienceLevel = Integer.parseInt(talkObject.getString("audienceLevel").replaceAll("[^0-9]", ""));
List speakerList = extractSpeakerList(confType, talkObject, code, title);
Set contentTagSet = extractContentTagSet(talkObject);
String state = talkObject.getJsonObject("state").getString("code");
if (!Arrays.asList(IGNORED_TALK_TYPES).contains(code) && !state.equals("declined")) {
Talk talk = createTalk(talkId++, code, title, talkTypeName, themeTrackSet, language, speakerList,
audienceLevel, contentTagSet);
talkCodeToTalkMap.put(code, talk);
talkList.add(talk);
talkTalkTypeToTotalMap.merge(talkTypeName, 1, Integer::sum);
}
}
}
solution.setTalkList(talkList);
}
private Set extractThemeTrackSet(JsonObject talkObject, String code, String title) {
Set themeTrackSet = new HashSet<>(Arrays.asList(talkObject.getJsonObject("track").getString("id")));
if (!trackIdSet.containsAll(themeTrackSet)) {
throw new IllegalStateException("The talk (" + title + ") with id (" + code
+ ") contains trackId + (" + trackIdSet + ") that doesn't exist in the trackIdSet.");
}
return themeTrackSet;
}
private List extractSpeakerList(String confType, JsonObject talkObject, String code, String title) {
List speakerList = new ArrayList<>();
String mainSpeakerName = talkObject.getString("mainSpeaker");
if (Arrays.asList(IGNORED_SPEAKER_NAMES).contains(mainSpeakerName)) {
return speakerList;
}
speakerList.add(getSpeakerOrCreateOneIfNull(confType, code, title, mainSpeakerName));
if (talkObject.containsKey("secondarySpeaker")) {
String secondarySpeakerName = talkObject.getString("secondarySpeaker");
speakerList.add(getSpeakerOrCreateOneIfNull(confType, code, title, secondarySpeakerName));
}
if (talkObject.containsKey("otherSpeakers")) {
JsonArray otherSpeakersArray = talkObject.getJsonArray("otherSpeakers");
for (JsonValue otherSpeakerName : otherSpeakersArray) {
speakerList.add(getSpeakerOrCreateOneIfNull(confType, code, title,
otherSpeakerName.toString().replaceAll("\"", "")));
}
}
return speakerList;
}
private Speaker getSpeakerOrCreateOneIfNull(String confType, String code, String title, String speakerName) {
Speaker speaker = speakerNameToSpeakerMap.get(speakerName);
if (speaker == null) {
LOGGER.warn("The talk (" + code + ": " + title + ") of type ( " + confType
+ ") has a speaker (" + speakerName + ") that doesn't exist in speaker list.");
speaker = new Speaker((long) solution.getSpeakerList().size());
speaker.setName(speakerName);
speaker.withPreferredRoomTagSet(new HashSet<>())
.withPreferredTimeslotTagSet(new HashSet<>())
.withProhibitedRoomTagSet(new HashSet<>())
.withProhibitedTimeslotTagSet(new HashSet<>())
.withRequiredRoomTagSet(new HashSet<>())
.withRequiredTimeslotTagSet(new HashSet<>())
.withUnavailableTimeslotSet(new HashSet<>())
.withUndesiredRoomTagSet(new HashSet<>())
.withUndesiredTimeslotTagSet(new HashSet<>());
if (speakerNameToSpeakerMap.keySet().contains(speakerName)) {
throw new IllegalStateException("Speaker (" + speakerName + ") already exists in the speaker list");
}
speakerNameToSpeakerMap.put(speakerName, speaker);
solution.getSpeakerList().add(speaker);
}
return speaker;
}
private Set extractContentTagSet(JsonObject talkObject) {
if (talkObject.containsKey("tags")) {
return talkObject.getJsonArray("tags").stream()
.map(JsonObject.class::cast)
.filter(tagObject -> !tagObject.getString("value").isEmpty())
.map(tagObject -> tagObject.getString("value"))
.collect(Collectors.toSet());
}
return new HashSet<>();
}
private Talk createTalk(Long talkId, String code, String title, String talkTypeName, Set themeTrackSet,
String languageg, List speakerList, int audienceLevel, Set contentTagSet) {
Talk talk = new Talk(talkId);
talk.setCode(code);
talk.setTitle(title);
if (talkTypeNameToTalkTypeMap.get(talkTypeName) == null) {
throw new IllegalStateException("The talk (" + title + ") with id (" + code
+ ") has a talkType (" + talkTypeName + ") that doesn't exist in the talkType list.");
}
talk.setTalkType(talkTypeNameToTalkTypeMap.get(talkTypeName));
talk.withThemeTrackTagSet(themeTrackSet)
.withLanguage(languageg)
.withSpeakerList(speakerList)
.withAudienceLevel(audienceLevel)
.withAudienceTypeSet(new HashSet<>())
.withContentTagSet(contentTagSet)
.withPreferredRoomTagSet(new HashSet<>())
.withPreferredTimeslotTagSet(new HashSet<>())
.withProhibitedRoomTagSet(new HashSet<>())
.withProhibitedTimeslotTagSet(new HashSet<>())
.withRequiredRoomTagSet(new HashSet<>())
.withRequiredTimeslotTagSet(new HashSet<>())
.withSectorTagSet(new HashSet<>())
.withUndesiredRoomTagSet(new HashSet<>())
.withUndesiredTimeslotTagSet(new HashSet<>())
.withMutuallyExclusiveTalksTagSet(new HashSet<>())
.withPrerequisiteTalksCodesSet(new HashSet<>());
//TODO specific for DeovxxBE, remove it
if (talk.getContentTagSet().contains("Devoxx Sponsor")) {
talk.getMutuallyExclusiveTalksTagSet().add("Devoxx Sponsor");
}
return talk;
}
private void importTimeslotList() {
List timeslotList = new ArrayList<>();
Map> timeslotToAvailableRoomsMap = new HashMap<>();
Map, Timeslot> startAndEndTimeToTimeslotMap = new HashMap<>();
Long timeSlotId = 0L;
String schedulesUrl = conferenceBaseUrl + "/schedules/";
LOGGER.debug("Sending a request to: " + schedulesUrl);
JsonArray daysArray = readJson(schedulesUrl, JsonReader::readObject).getJsonArray("links");
for (int i = 0; i < daysArray.size(); i++) {
JsonObject dayObject = daysArray.getJsonObject(i);
String dayUrl = dayObject.getString("href");
LOGGER.debug("Sending a request to: " + dayUrl);
JsonArray daySlotsArray = readJson(dayUrl, JsonReader::readObject).getJsonArray("slots");
for (int j = 0; j < daySlotsArray.size(); j++) {
JsonObject timeslotObject = daySlotsArray.getJsonObject(j);
LocalDateTime startDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeslotObject.getJsonNumber("fromTimeMillis").longValue()),
ZoneId.of(ZONE_ID));
LocalDateTime endDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeslotObject.getJsonNumber("toTimeMillis").longValue()),
ZoneId.of(ZONE_ID));
Room room = roomIdToRoomMap.get(timeslotObject.getString("roomId"));
if (room == null) {
throw new IllegalStateException("The timeslot (" + timeslotObject.getString("slotId") + ") has a roomId (" + timeslotObject.getString("roomId")
+ ") that does not exist in the rooms list");
}
// Assuming slotId is of format: tia_room6_monday_12_.... take only "tia"
String talkTypeName = timeslotObject.getString("slotId").split("_")[0];
TalkType timeslotTalkType = talkTypeNameToTalkTypeMap.get(talkTypeName);
if (Arrays.asList(IGNORED_TALK_TYPES).contains(talkTypeName)) {
continue;
}
Timeslot timeslot;
if (startAndEndTimeToTimeslotMap.keySet().contains(Pair.of(startDateTime, endDateTime))) {
timeslot = startAndEndTimeToTimeslotMap.get(Pair.of(startDateTime, endDateTime));
timeslotToAvailableRoomsMap.get(timeslot).add(room);
if (timeslotTalkType != null) {
timeslot.getTalkTypeSet().add(timeslotTalkType);
}
} else {
timeslot = new Timeslot(timeSlotId++);
timeslot.withStartDateTime(startDateTime)
.withEndDateTime(endDateTime)
.withTalkTypeSet(timeslotTalkType == null ? new HashSet<>() : new HashSet<>(Arrays.asList(timeslotTalkType)));
timeslot.setTagSet(new HashSet<>());
timeslotList.add(timeslot);
timeslotToAvailableRoomsMap.put(timeslot, new ArrayList<>(Arrays.asList(room)));
startAndEndTimeToTimeslotMap.put(Pair.of(startDateTime, endDateTime), timeslot);
}
if (!timeslotObject.isNull("talk")) {
scheduleTalk(timeslotObject, room, timeslot);
}
for (TalkType talkType : timeslot.getTalkTypeSet()) {
talkType.getCompatibleTimeslotSet().add(timeslot);
}
timeslotTalkTypeToTotalMap.merge(talkTypeName, 1, Integer::sum);
}
}
for (Room room : solution.getRoomList()) {
room.setUnavailableTimeslotSet(timeslotList.stream()
.filter(timeslot -> !timeslotToAvailableRoomsMap.get(timeslot).contains(room))
.collect(Collectors.toSet()));
}
solution.setTimeslotList(timeslotList);
}
private Set getTalkTypeSetForCapacity(int capacity) {
Set talkTypeSet = new HashSet<>();
List typeNames = new ArrayList<>();
if (capacity < 100) {
typeNames.addAll(Arrays.asList(SMALL_ROOMS_TYPE_NAMES));
} else {
typeNames.addAll(Arrays.asList(LARGE_ROOMS_TYPE_NAMES));
}
for (String talkTypeName : typeNames) {
TalkType talkType = talkTypeNameToTalkTypeMap.get(talkTypeName);
if (talkType != null) {
talkTypeSet.add(talkType);
}
}
return talkTypeSet;
}
private void scheduleTalk(JsonObject timeslotObject, Room room, Timeslot timeslot) {
Talk talk = talkCodeToTalkMap.get(timeslotObject.getJsonObject("talk").getString("id"));
if (talk == null) {
throw new IllegalStateException("The timeslot (" + timeslotObject.getString("slotId")
+ ") has a talk (" + timeslotObject.getJsonObject("talk").getString("id")
+ ") that does not exist in the talk list");
}
if (talk.isPinnedByUser()) {
throw new IllegalStateException("The timeslot (" + timeslotObject.getString("slotId")
+ ") has a talk (" + timeslotObject.getJsonObject("talk").getString("id")
+ ") that is already pinned by user at another timeslot (" + talk.getTimeslot().toString() + ").");
}
talk.setRoom(room);
talk.setTimeslot(timeslot);
talk.setPinnedByUser(true);
}
private R readJson(String url, Function mapper) {
try (InputStream inputStream = new ConnectionFollowRedirects(url).getInputStream()) {
JsonReader jsonReader = Json.createReader(inputStream);
return mapper.apply(jsonReader);
} catch (IOException e) {
throw new IllegalStateException(
"Import failed on URL (" + url + ").", e);
}
}
}