package org.cbir.retrieval.service;
/*
* Copyright (c) 2009-2015. Authors: see NOTICE file.
*
* 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.
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import retrieval.client.RetrievalClient;
import retrieval.config.ConfigClient;
import retrieval.config.ConfigServer;
import retrieval.server.RetrievalServer;
import retrieval.storage.Storage;
import retrieval.storage.exception.AlreadyIndexedException;
import retrieval.storage.exception.NoValidPictureException;
import retrieval.storage.exception.PictureTooHomogeneous;
import retrieval.storage.exception.TooMuchIndexRequestException;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
/**
* Service class for managing retrieval server.
*/
@Service
@Transactional
public class RetrievalService {
public static final String DEFAULT_TEST_STORAGE = "default";
public static final String DEFAULT_STORAGE = "dev";
public static final String OTHER_STORAGE = "abc";
private final Logger log = LoggerFactory.getLogger(RetrievalService.class);
@Inject
private Environment env;
@Inject
private StoreImageService storeImageService;
@Autowired
ServletContext servletContext;
public RetrievalServer initRetrievalServer() throws Exception{
log.info("Init retrieval server");
RetrievalServer server = null;
String envir = "";
if(env.getActiveProfiles().length>0) {
envir = env.getActiveProfiles()[0];
log.info("profile is "+ Arrays.toString(env.getActiveProfiles()) +" => " +envir);
if (envir.equals("dev")) {
server = buildRetrievalServerForDev();
} else if (envir.equals("prod")) {
server = buildRetrievalServerForProd();
} else {
server = buildRetrievalServerForTest();
}
} else server = buildRetrievalServerForTest();
log.info("server "+ server);
log.info("storages "+ server.getStorageList());
if(server.getStorageList()==null || server.getStorageList().isEmpty()) {
server.createStorage(DEFAULT_TEST_STORAGE);
}
servletContext.setAttribute("server",server);
servletContext.setAttribute("client",buildRetrievalClient(server));
return server;
}
public RetrievalServer getRetrievalServer() {
return (RetrievalServer)servletContext.getAttribute("server");
}
public RetrievalClient getRetrievalClient() {
return (RetrievalClient)servletContext.getAttribute("client");
}
public RetrievalServer buildRetrievalServerForTest() throws Exception {
ConfigServer configServer = new ConfigServer(env.getProperty("retrieval.config.server"));
configServer.setStoreName(env.getProperty("retrieval.store.name"));
RetrievalServer server = new RetrievalServer(configServer,"cbir",false);
server.createStorage(DEFAULT_TEST_STORAGE);
return server;
}
public RetrievalServer buildRetrievalServerForDev() throws Exception {
ConfigServer configServer = new ConfigServer(env.getProperty("retrieval.config.server"));
configServer.setStoreName(env.getProperty("retrieval.store.name"));
RetrievalServer server = new RetrievalServer(configServer,"cbir",false);
if(configServer.getStoreName().equals("MEMORY")) {
server.createStorage(DEFAULT_TEST_STORAGE);
server.createStorage(OTHER_STORAGE);
Map<String, String> properties = new TreeMap<>();
properties.put("date", new Date().toString());
indexPicture(server.getStorage(DEFAULT_TEST_STORAGE), ImageIO.read(new File("testdata/images/crop1.jpg")), 1l, new HashMap<>(properties));
indexPicture(server.getStorage(DEFAULT_TEST_STORAGE), ImageIO.read(new File("testdata/images/crop2.jpg")), 2l, new HashMap<>(properties));
indexPicture(server.getStorage(DEFAULT_TEST_STORAGE), ImageIO.read(new File("testdata/images/crop3.jpg")), 3l, new HashMap<>(properties));
indexPicture(server.getStorage(OTHER_STORAGE), ImageIO.read(new File("testdata/images/crop4.jpg")), 4l, new HashMap<>(properties));
}
return server;
}
public RetrievalServer buildRetrievalServerForProd() throws Exception {
ConfigServer configServer = new ConfigServer(env.getProperty("retrieval.config.server"));
configServer.setStoreName(env.getProperty("retrieval.store.name"));
return new RetrievalServer(configServer,"cbir",false);
}
private void indexPicture(Storage storage,BufferedImage image,Long id, Map<String,String> properties) throws NoValidPictureException, AlreadyIndexedException, PictureTooHomogeneous, IOException {
Long realId = storage.indexPicture(image,id,properties);
storeImageService.saveIndexImage(realId,image);
}
private void indexPictureAsync(Storage storage,BufferedImage image,Long id, Map<String,String> properties) throws NoValidPictureException, AlreadyIndexedException, PictureTooHomogeneous, IOException, TooMuchIndexRequestException {
Long realId = storage.addToIndexQueue(image, id, properties);
storeImageService.saveIndexImage(realId,image);
}
public RetrievalClient buildRetrievalClient(RetrievalServer server) throws Exception {
return new RetrievalClient(new ConfigClient(env.getProperty("retrieval.config.client")),server);
}
public void reset() throws Exception {
initRetrievalServer();
}
public void indexDataset(RetrievalServer server,Path dataset) throws Exception {
if(Files.exists(dataset)) {
int nbstorage = 4;
for(int i=1;i<=nbstorage;i++) {
server.createStorage(i+"");
}
long id = 0;
Files.walk(dataset).forEach(filePath -> {
try {
if (Files.isRegularFile(filePath) && !Files.isHidden(filePath)) {
log.info("Process file: "+filePath);
String filename = filePath.getFileName().toString().split("\\.")[0];
try {
indexPictureAsync(
server.getStorage(String.valueOf(new Random().nextInt(nbstorage) + 1)),
ImageIO.read(filePath.toFile()), Long.parseLong(filename), new HashMap<>());
} catch (NoValidPictureException | PictureTooHomogeneous | AlreadyIndexedException | IOException | TooMuchIndexRequestException e) {
log.error(e.toString());
}
}
} catch (IOException e) {
log.error(e.toString());
}
});
} else throw new IOException("Path "+dataset.toAbsolutePath() +" does not exists");
}
}