siddur.solidtrust.image.ImageController.java Source code

Java tutorial

Introduction

Here is the source code for siddur.solidtrust.image.ImageController.java

Source

package siddur.solidtrust.image;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.log4j.Logger;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;

import siddur.solidtrust.FileSystemUtil;
import siddur.solidtrust.FreePersister;
import siddur.solidtrust.SolidtrustConstants;
import siddur.solidtrust.entity.AccessItem;
import siddur.solidtrust.entity.ImageInfo;
import siddur.solidtrust.entity.ImageProduct;
import siddur.solidtrust.image.netcar.NetCarService;
import siddur.solidtrust.site.ProductAPI.Product;

@Controller
public class ImageController {

    private final Logger log4j = Logger.getLogger(ImageController.class);
    private final LinkedBlockingQueue<DeferredResult<Object>> suspendedImageRequests = new LinkedBlockingQueue<DeferredResult<Object>>(
            20);

    @PersistenceContext
    private EntityManager em;

    @Autowired
    private ImageProductService ipService;

    @Autowired
    private ImageFetcher imgFetcher;

    @Autowired
    private FreePersister free;

    @Autowired
    private CustomSearchExtractor extractor;

    @Autowired
    private NetCarService netCarService;

    @RequestMapping(value = "/image/search")
    @Transactional(readOnly = true)
    public String search(@RequestParam(value = "key", required = false) String key,
            @RequestParam(value = "type", required = false, defaultValue = "1") int type,
            @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageIndex, Model model)
            throws Exception {
        int pageSize = 8;
        if (type == 1) {
            //Search by keywords
            if (!StringUtils.isEmpty(key)) {
                FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
                QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
                        .forEntity(ImageProduct.class).get();
                Query query = qb.keyword().onFields("brand", "type", "arrangement", "buildYear")
                        .matching(key.toLowerCase()).createQuery();
                FullTextQuery persistenceQuery = fullTextEntityManager.createFullTextQuery(query,
                        ImageProduct.class);

                persistenceQuery.setMaxResults(pageSize);
                persistenceQuery.setFirstResult((pageIndex - 1) * pageSize);
                @SuppressWarnings("unchecked")
                List<ImageProduct> ips = persistenceQuery.getResultList();
                Pageable pageable = new PageRequest(pageIndex - 1, pageSize);
                Page<ImageProduct> page = new PageImpl<ImageProduct>(ips, pageable,
                        persistenceQuery.getResultSize());
                model.addAttribute("page", page);
            }
        } else if (type == 2) {
            //Search by license plate
            if (key != null) {
                ImageProduct ip = findImagesByLicensePlate(key);
                model.addAttribute("ip", ip);
            }
        }

        model.addAttribute("key", key);
        return "image/search";
    }

    @RequestMapping(value = "/image/manage")
    @Transactional(readOnly = true)
    public String manage(@RequestParam(value = "type", required = false, defaultValue = "0") int type,
            @RequestParam(value = "daterange", required = false) String daterange,
            @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageIndex, Model model)
            throws Exception {
        int pageSize = 8;
        Pageable pageable = new PageRequest(pageIndex - 1, pageSize);
        Page<ImageProduct> page = null;
        if (type == 0) {
            List<ImageProduct> list = em.createQuery("from ImageProduct", ImageProduct.class)
                    .setFirstResult((pageIndex - 1) * pageSize).setMaxResults(pageSize).getResultList();
            long count = em.createQuery("select count(ip) from ImageProduct ip", Long.class).getSingleResult();
            page = new PageImpl<ImageProduct>(list, pageable, count);
        } else if (type == 1) {
            if (daterange.equals("")) {
                type = 0;
            } else {
                model.addAttribute("daterange", daterange);
                String[] dates = daterange.split(" - ");
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                Date from = formatter.parse(dates[0]);
                Date to = formatter.parse(dates[1]);
                to = DateUtils.addDays(to, 1);
                List<ImageProduct> list = em
                        .createQuery("from ImageProduct ip where ip.createdAt between :from and :to",
                                ImageProduct.class)
                        .setParameter("from", from).setParameter("to", to)
                        .setFirstResult((pageIndex - 1) * pageSize).setMaxResults(pageSize).getResultList();

                long count = em.createQuery(
                        "select count(ip) from ImageProduct ip where ip.createdAt between :from and :to",
                        Long.class).setParameter("from", from).setParameter("to", to).getSingleResult();
                page = new PageImpl<ImageProduct>(list, pageable, count);
            }
        }

        if (page != null)
            model.addAttribute("page", page);
        model.addAttribute("type", type);
        return "image/manage";
    }

    @Transactional(readOnly = false)
    @RequestMapping(value = "/image/order/{id}")
    public @ResponseBody int order(@PathVariable(value = "id") int id, @RequestParam(value = "srcIndex") int src,
            @RequestParam(value = "tgtIndex") int tgt) {
        ImageProduct ip = em.find(ImageProduct.class, id);
        String srcUrl = getImage(ip, src);
        String tgtUrl = getImage(ip, tgt);
        setImage(ip, srcUrl, tgt);
        setImage(ip, tgtUrl, src);
        em.persist(ip);
        return 1;
    }

    @Transactional(readOnly = false)
    @RequestMapping(value = "/image/del/{id}")
    public @ResponseBody int delete(@PathVariable(value = "id") int id, Model model) throws Exception {
        ImageProduct ip = em.find(ImageProduct.class, id);
        em.remove(ip);
        log4j.info("Removed ImageProduct with ID:" + id);
        return 1;
    }

    @Transactional(readOnly = false)
    @RequestMapping(value = "/image/save")
    public @ResponseBody String save(@RequestParam(value = "index") int index,
            @RequestParam(value = "imageProductId") int imageProductId,
            @RequestParam(value = "url", required = false) String url,
            @RequestParam(value = "file", required = false) MultipartFile file, Model model) throws Exception {
        ImageInfo image = null;
        if (!StringUtils.isEmpty(url)) {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            try {
                image = extractor.persist(url, httpclient);
            } finally {
                httpclient.close();
            }
        } else if (file != null) {
            image = extractor.persist(file);
        }
        if (image != null) {
            String filename = image.getUuid();
            ImageProduct ip = em.find(ImageProduct.class, imageProductId);
            setImage(ip, filename, index);
            em.persist(ip);

            return filename;
        }
        return "";
    }

    @RequestMapping(value = "/images/{filename:.+}")
    public void serveImage(HttpServletRequest req, HttpServletResponse resp,
            @PathVariable("filename") String filename, @RequestParam(value = "s", required = false) String scope)
            throws IOException {
        String filepath = filename;
        if (scope != null) {
            filepath = scope + "/" + filepath;
        }
        //404
        File f = new File(FileSystemUtil.getImageDir(), filepath);
        if (!f.exists()) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        //304
        long lastModifiedTimestamp = f.lastModified();
        long ifModifiedSince = req.getDateHeader("If-Modified-Since");
        boolean notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000));
        if (notModified) {
            resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        } else {
            resp.setDateHeader("Last-Modified", lastModifiedTimestamp);
        }

        //length
        resp.setContentLength((int) f.length());

        //content type
        resp.setContentType("image/jpg");

        //response
        FileCopyUtils.copy(new FileInputStream(f), resp.getOutputStream());
    }

    @RequestMapping(value = "/api/images")
    public @ResponseBody DeferredResult<Object> findCarImages(final @RequestParam("id") String id,
            HttpServletRequest request) {
        final String ip = request.getRemoteHost();
        final String username = request.getAttribute(SolidtrustConstants.CLIENT_ID) + "";
        final int port = request.getLocalPort();
        final String address = request.getLocalAddr();

        final DeferredResult<Object> result = new DeferredResult<>(2000L, "no data");
        log4j.info("Id=" + id + " ,Remaining: " + suspendedImageRequests.remainingCapacity());
        try {
            suspendedImageRequests.add(result);
        } catch (Exception e1) {
            result.setResult("Image service is overload");
            return result;
        }
        result.onCompletion(new Runnable() {

            @Override
            public void run() {
                suspendedImageRequests.remove(result);
            }
        });

        new Thread(new Runnable() {

            @Override
            public void run() {
                AccessItem ai = new AccessItem();
                ai.setIp(ip);
                ai.setUsername(username);
                ai.setService(Product.IMAGES.getId());
                ai.setRequest(id);

                ImageProduct ip = null;
                try {
                    ip = findImagesByLicensePlate(id);
                } catch (Exception e) {
                    ai.setStatus(-1);
                    log4j.error(e.getMessage(), e);
                    ai.setResponse(e.getMessage());
                    free.save(ai);
                    return;
                }

                if (ip == null) {
                    ai.setStatus(-1);
                    ai.setResponse("Not found:" + id);
                    free.save(ai);
                    return;
                }

                ai.setResponse(ip.getId() + "");
                free.save(ai);

                ImageProduct resp = addPrefix(port, address, ip);
                result.setResult(resp);

            }
        }).start();

        return result;
    }

    @RequestMapping(value = "/api/images1")
    public @ResponseBody Object findCarImages1(final @RequestParam("id") String id, HttpServletRequest request) {
        final int port = request.getLocalPort();
        final String address = request.getLocalAddr();

        String username = request.getAttribute(SolidtrustConstants.CLIENT_ID) + "";
        AccessItem ai = new AccessItem();
        ai.setIp(request.getRemoteHost());
        ai.setUsername(username);
        ai.setService(Product.IMAGES.getId());
        ai.setRequest(id);

        ImageProduct ip = null;
        try {
            ip = findImagesByLicensePlate(id, false);
            ai.setResponse(ip.getImage1());
        } catch (Exception e) {
        }

        if (ip == null) {
            ai.setStatus(-1);
            free.save(ai);
            return "no data";
        }
        free.save(ai);

        String portStr = port == 80 ? "" : ":" + port;
        String prex = "http://" + address + portStr + "/solidtrust/images/";
        ImageProduct resp = new ImageProduct();
        resp.setArrangement(ip.getArrangement());
        resp.setBrand(ip.getBrand());
        resp.setType(ip.getType());
        resp.setBuildYear(ip.getBuildYear());
        if (ip.getImage1() != null) {
            resp.setImage1(prex + ip.getImage1());
        }
        if (ip.getImage2() != null) {
            resp.setImage2(prex + ip.getImage2());
        }
        if (ip.getImage3() != null) {
            resp.setImage3(prex + ip.getImage3());
        }
        if (ip.getImage4() != null) {
            resp.setImage4(prex + ip.getImage4());
        }
        return resp;
    }

    @RequestMapping(value = "/api/images2")
    public @ResponseBody Object findCarImages(final String brand, final String model, final String build,
            HttpServletRequest request) {
        final String ip = request.getRemoteHost();
        final String username = request.getAttribute(SolidtrustConstants.CLIENT_ID) + "";
        final int port = request.getLocalPort();
        final String address = request.getLocalAddr();
        AccessItem ai = new AccessItem();
        ai.setIp(ip);
        ai.setUsername(username);
        ai.setService(Product.IMAGES2.getId());
        ai.setRequest("Brand=" + brand + ", Model=" + model + ", Build=" + build);

        log4j.info("Brand=" + brand + ", Model=" + model + ", Build=" + build + " ,Remaining: "
                + suspendedImageRequests.remainingCapacity());
        try {
            ImageProduct imageProduct = netCarService.search(brand, model, build);
            ai.setResponse(imageProduct.getImage1());
            free.save(ai);
            return addPrefix(port, address, imageProduct);
        } catch (Exception e) {
            log4j.error(e.getMessage(), e);
            ai.setResponse(e.getMessage());
            free.save(ai);
        }
        return "no data";
    }

    private ImageProduct addPrefix(int port, String address, ImageProduct ip) {
        String portStr = port == 80 ? "" : ":" + port;
        String prex = "http://" + address + portStr + "/solidtrust/images/";
        ImageProduct resp = new ImageProduct();
        resp.setArrangement(ip.getArrangement());
        resp.setBrand(ip.getBrand());
        resp.setType(ip.getType());
        resp.setBuildYear(ip.getBuildYear());
        if (ip.getImage1() != null) {
            resp.setImage1(prex + ip.getImage1());
        }
        if (ip.getImage2() != null) {
            resp.setImage2(prex + ip.getImage2());
        }
        if (ip.getImage3() != null) {
            resp.setImage3(prex + ip.getImage3());
        }
        if (ip.getImage4() != null) {
            resp.setImage4(prex + ip.getImage4());
        }
        return resp;
    }

    private ImageProduct findImagesByLicensePlate(String id) throws Exception {
        return findImagesByLicensePlate(id, true);
    }

    private ImageProduct findImagesByLicensePlate(String id, boolean google) throws Exception {
        //convert azure car into image product
        ImageProduct ip = ipService.findImageProduct(id);
        if (ip == null) {
            return null;
        }

        //find image product in db
        ImageProduct db = ipService.findTheSame(ip);
        if (db != null) {
            ip = db;
        } else {
            //fetch image from netcarshow
            if (netCarService.search(ip)) {
                free.save(ip);
                log4j.info("Successfully fetch from NetCarShow: " + ip);
                return ip;
            }
            if (google) {
                searchByGoogleEngine(ip);
            }
        }
        return ip;
    }

    private void searchByGoogleEngine(ImageProduct ip) throws Exception {
        List<ImageInfo> images = null;
        //fetch image from google
        String q = buildQuery(ip);
        log4j.info("query: " + q);
        try {
            images = imgFetcher.fetch(URLEncoder.encode(q, "iso-8859-1"), 10, 3);
        } catch (Throwable e) {
            log4j.warn(e.getMessage(), e);
        }

        String lastQ = buildInteriorQuery(q);
        log4j.info("query interior: " + lastQ);
        List<ImageInfo> lasts = null;
        try {
            lasts = imgFetcher.fetch(URLEncoder.encode(lastQ, "iso-8859-1"), 4, 1);
        } catch (ResultException e) {
            log4j.warn(e.getMessage(), e);
        }
        if (lasts.size() > 0) {
            images.add(3, lasts.get(0));
        }

        for (ImageInfo ii : images) {
            ii.setName(q);
            free.save(ii);
        }

        int size = images.size();
        if (size >= 1) {
            ip.setImage1(images.get(0).getUuid());
        }
        if (size >= 2) {
            ip.setImage2(images.get(1).getUuid());
        }
        if (size >= 3) {
            ip.setImage3(images.get(2).getUuid());
        }
        if (size >= 4) {
            ip.setImage4(images.get(3).getUuid());
        }

        free.save(ip);
    }

    private String getImage(ImageProduct ip, int index) {
        if (index == 0) {
            return ip.getImage1();
        }
        if (index == 1) {
            return ip.getImage2();
        }
        if (index == 2) {
            return ip.getImage3();
        }
        if (index == 3) {
            return ip.getImage4();
        }
        return null;
    }

    private void setImage(ImageProduct ip, String img, int index) {
        if (index == 0) {
            ip.setImage1(img);
        }
        if (index == 1) {
            ip.setImage2(img);
        }
        if (index == 2) {
            ip.setImage3(img);
        }
        if (index == 3) {
            ip.setImage4(img);
        }
    }

    private String buildQuery(ImageProduct ip) {
        return ip.getBrand() + " " + ip.getType() + " " + ip.getArrangement() + " " + ip.getBuildYear();
    }

    private String buildInteriorQuery(String query) {
        return query + " interior interior interior interior";
    }

}