lt.emasina.resthub.server.factory.DataFactory.java Source code

Java tutorial

Introduction

Here is the source code for lt.emasina.resthub.server.factory.DataFactory.java

Source

/*
 * #%L
 * server
 * %%
 * Copyright (C) 2012 - 2015 valdasraps
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */
package lt.emasina.resthub.server.factory;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.inject.Singleton;

import lombok.extern.log4j.Log4j;
import lt.emasina.resthub.model.MdColumn;
import lt.emasina.resthub.server.cache.CcLob;
import lt.emasina.resthub.server.cache.CcCount;
import lt.emasina.resthub.server.cache.CcData;
import lt.emasina.resthub.server.exception.ClientErrorException;
import lt.emasina.resthub.server.exception.ServerErrorException;
import lt.emasina.resthub.server.handler.LobHandler;
import lt.emasina.resthub.server.handler.CountHandler;
import lt.emasina.resthub.server.handler.DataHandler;
import lt.emasina.resthub.server.handler.PagedHandler;
import lt.emasina.resthub.server.query.Query;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.BlobType;
import org.hibernate.type.CalendarType;
import org.hibernate.type.ClobType;
import org.hibernate.type.StringType;
import org.hibernate.type.TextType;
import org.hibernate.type.WrapperBinaryType;
import org.restlet.data.Status;

/**
 * DataFactory
 * @author valdo
 */
@Singleton
@Log4j
public class DataFactory {

    private static final String START_ROW_PARAM = "START_ROW___";
    private static final String NUM_ROWS_PARAM = "NUMBER_OF_ROWS___";

    public CcData getData(final Session session, final DataHandler handler) throws Exception {
        final Query q = handler.getQuery();
        final SQLQuery query = getPagedSQLQuery(session, handler);

        for (MdColumn c : q.getColumns()) {
            switch (c.getType()) {
            case BLOB:
                query.addScalar(c.getName(), new BlobType());
                break;
            case CLOB:
                query.addScalar(c.getName(), new ClobType());
                break;
            case DATE:
                query.addScalar(c.getName(), new CalendarType());
                break;
            case NUMBER:
                query.addScalar(c.getName(), new BigDecimalType());
                break;
            case STRING:
                query.addScalar(c.getName(), new StringType());
                break;
            }
        }

        if (log.isDebugEnabled()) {
            log.debug(query.getQueryString());
        }

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<CcData> loopRows = executor.submit(new Callable<CcData>() {

            @Override
            @SuppressWarnings("unchecked")
            public CcData call() throws Exception {
                CcData cc = new CcData();
                for (Object o : query.list()) {
                    cc.addRow(q, o);
                }
                return cc;
            };
        });

        try {

            return loopRows.get(q.getTimeOut(), TimeUnit.SECONDS);

        } catch (ExecutionException | InterruptedException ex) {
            throw ex;
        } catch (TimeoutException ex) {
            throw new ServerErrorException(Status.SERVER_ERROR_GATEWAY_TIMEOUT, ex);
        }

    }

    public CcLob getLob(final Session session, final LobHandler handler) throws Exception {
        final Query q = handler.getQuery();
        final SQLQuery query = getPagedSQLQuery(session, handler);

        final MdColumn c = handler.getMdColumn();
        switch (c.getType()) {
        case BLOB:
            query.addScalar(c.getName(), new WrapperBinaryType());
            break;
        case CLOB:
            query.addScalar(c.getName(), new TextType());
            break;
        default:
            throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST,
                    "Column %d (%s) expected to be LOB found %s", handler.getColumn(), c.getName(),
                    c.getType().name());
        }

        if (log.isDebugEnabled()) {
            log.debug(query.getQueryString());
        }

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<CcLob> fetchData = executor.submit(new Callable<CcLob>() {

            @Override
            @SuppressWarnings("unchecked")
            public CcLob call() throws Exception {
                CcLob cc = new CcLob();
                Object o = query.uniqueResult();
                if (o != null) {
                    switch (c.getType()) {
                    case CLOB:
                        cc.setValue((String) o);
                        break;
                    case BLOB:
                        cc.setValue((Byte[]) o);
                        break;
                    }
                }
                return cc;
            };
        });

        try {

            return fetchData.get(q.getTimeOut(), TimeUnit.SECONDS);

        } catch (ExecutionException | InterruptedException ex) {
            throw ex;
        } catch (TimeoutException ex) {
            throw new ServerErrorException(Status.SERVER_ERROR_GATEWAY_TIMEOUT, ex);
        }

    }

    private SQLQuery getPagedSQLQuery(final Session session, final PagedHandler<?, ?> handler) throws SQLException {
        final Query q = handler.getQuery();

        Integer perPage = handler.getPerPage();
        Integer page = handler.getPage();
        if (page == null || perPage == null) {
            perPage = q.getRowsLimit();
            page = 1;
        }

        Integer startRow = perPage * (page - 1) + 1;

        if (handler instanceof LobHandler) {
            startRow = startRow + ((LobHandler) handler).getRow();
            perPage = 1;
        }

        StringBuilder sb = new StringBuilder();
        sb.append("select * from " + "  (select ROWNUM ROW_NUMBER___, A.* from (");

        sb.append(q.getSql()).append(") A").append("  where ROWNUM < (:").append(START_ROW_PARAM).append(" + :")
                .append(NUM_ROWS_PARAM).append(") ").append(") where ROW_NUMBER___ >= :").append(START_ROW_PARAM);

        String sql = sb.toString();
        final SQLQuery query = session.createSQLQuery(sql);

        handler.applyParameters(query);

        query.setInteger(START_ROW_PARAM, startRow);
        query.setInteger(NUM_ROWS_PARAM, perPage);

        return query;
    }

    public CcCount getCount(Session session, CountHandler handler) throws SQLException {
        final Query q = handler.getQuery();

        StringBuilder sb = new StringBuilder();
        sb.append("select count(*) from (").append(handler.getQuery().getSql()).append(") ");

        String sql = sb.toString();

        final SQLQuery query = session.createSQLQuery(sql);

        handler.applyParameters(query);
        if (log.isDebugEnabled()) {
            log.debug(query.getQueryString());
        }

        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<CcCount> func = executor.submit(new Callable<CcCount>() {

            @Override
            public CcCount call() throws Exception {
                CcCount cc = new CcCount();
                cc.setValue(((BigDecimal) query.uniqueResult()).longValue());
                return cc;
            }

        });

        try {

            return func.get(q.getTimeOut(), TimeUnit.SECONDS);

        } catch (ExecutionException | InterruptedException ex) {
            throw new ServerErrorException(Status.SERVER_ERROR_INTERNAL, ex);
        } catch (TimeoutException ex) {
            throw new ServerErrorException(Status.SERVER_ERROR_GATEWAY_TIMEOUT, ex);
        }
    }

}