lt.emasina.resthub.server.handler.Handler.java Source code

Java tutorial

Introduction

Here is the source code for lt.emasina.resthub.server.handler.Handler.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.handler;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import lombok.Getter;
import lombok.ToString;
import lombok.extern.log4j.Log4j;
import lt.emasina.resthub.server.app.BaseResource;
import lt.emasina.resthub.server.cache.CacheStats;
import lt.emasina.resthub.server.cache.CcBase;
import lt.emasina.resthub.server.exception.ClientErrorException;
import lt.emasina.resthub.server.exporter.Exporter;
import lt.emasina.resthub.server.factory.CacheFactory;
import lt.emasina.resthub.server.factory.ResourceFactory;
import lt.emasina.resthub.server.query.Query;
import lt.emasina.resthub.server.query.QueryParameter;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.apache.commons.lang.builder.HashCodeBuilder;

import org.hibernate.SQLQuery;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.DateType;
import org.hibernate.type.StringType;
import org.json.JSONArray;
import org.json.JSONException;
import org.restlet.data.Form;
import org.restlet.data.Status;
import org.restlet.resource.ResourceException;

/**
 * QueryHandler
 * @param <C>
 * @param <E>
 * @author valdo
 */
@Log4j
@ToString(of = "query")
public abstract class Handler<C extends CcBase<?>, E extends Exporter<C>> {

    @Inject
    private CacheFactory ccf;

    @Inject
    protected ResourceFactory rf;

    @Getter
    private final Query query;

    @Getter
    private final Map<QueryParameter, Object> parameters = new HashMap<>();

    @Getter
    private final String queryString;

    public Handler(Query query, Form form) throws ResourceException {
        this.query = query;
        this.queryString = form.getQueryString();
        for (QueryParameter p : query.getParameters()) {

            String name = p.getName();
            String svalue = form.getFirstValue(name, true);

            switch (p.getType()) {

            case DATE:
                parameters.put(p, readParameterValue(Date.class, p, svalue));
                break;

            case NUMBER:
                parameters.put(p, readParameterValue(BigDecimal.class, p, svalue));
                break;

            case STRING:
                parameters.put(p, readParameterValue(String.class, p, svalue));
                break;

            case CLOB:
            case BLOB:
                throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST,
                        String.format("LOBs are not supported as parameters: %s", name));

            }

        }

        if (log.isDebugEnabled()) {
            for (QueryParameter qp : parameters.keySet()) {
                log.debug(qp.toString(parameters.get(qp)));
            }
        }

    }

    private static <T> Object readParameterValue(Class<T> clazz, QueryParameter param, String svalue)
            throws ResourceException {
        if (svalue == null) {
            return null;
        } else {
            try {
                if (param.getArray()) {
                    JSONArray ja = new JSONArray(svalue);
                    List<T> a = new ArrayList<>();
                    for (int i = 0; i < ja.length(); i++) {
                        a.add(BaseResource.convertValue(clazz, ja.getString(i)));
                    }
                    return a.toArray();
                } else {
                    return BaseResource.convertValue(clazz, svalue);
                }
            } catch (JSONException ex) {
                throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST, ex);
            }
        }
    }

    public void applyParameters(SQLQuery query) throws SQLException {
        for (Map.Entry<QueryParameter, Object> e : parameters.entrySet()) {

            QueryParameter p = e.getKey();
            Object value = e.getValue();
            String name = p.getSqlName();

            if (value != null && p.getArray()) {

                switch (p.getType()) {
                case DATE:
                    query.setParameterList(name, (Object[]) value, new DateType());
                    break;
                case NUMBER:
                    query.setParameterList(name, (Object[]) value, new BigDecimalType());
                    break;
                case STRING:
                    query.setParameterList(name, (Object[]) value, new StringType());
                    break;
                case CLOB:
                case BLOB:
                    throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST,
                            String.format("LOBs are not supported as parameters: %s", name));
                }

            } else {

                switch (p.getType()) {
                case DATE:
                    query.setDate(name, (Date) value);
                    break;
                case NUMBER:
                    query.setBigDecimal(name, (BigDecimal) value);
                    break;
                case STRING:
                    query.setString(name, (String) value);
                    break;
                case CLOB:
                case BLOB:
                    throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST,
                            String.format("LOBs are not supported as parameters: %s", name));
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    public C getCached() {
        if (query.isCacheable()) {
            Cache cache = ccf.get(query);
            if (cache == null) {

                if (log.isDebugEnabled()) {
                    log.debug(String.format("Cache for %s not found", this));
                }

            } else {

                if (log.isDebugEnabled()) {
                    log.debug(String.format("Cache for %s found", this));
                }

                if (cache.isKeyInCache(getId())) {

                    Element el = cache.get(getId());
                    boolean expired = (el == null || el.isExpired());

                    if (log.isDebugEnabled()) {

                        log.debug(String.format("Element %d found in %s cache (expired = %s)", getId(),
                                query.getQid(), expired));
                    }

                    if (el != null && !expired) {
                        return (C) el.getObjectValue();
                    }

                } else {

                    if (log.isDebugEnabled()) {
                        log.debug(String.format("Element %d not found in %s cache", getId(), query.getQid()));
                    }

                }
            }

        }

        return (C) null;

    }

    public void setCached(C data) {
        if (query.isCacheable()) {
            Cache cache = ccf.get(query);
            if (cache != null) {

                cache.put(new Element(getId(), data));

                if (query.getHitCount() > 0 && !query.isEternal()) {
                    CacheStats cs = getCacheStats();
                    ccf.createCacheJob(this, cs.getExpTime());
                }

                if (log.isDebugEnabled()) {
                    log.debug(String.format("Element %s put into %s cache", getId(), query.getQid()));
                }

            }
        }
    }

    public CacheStats getCacheStats() {
        CacheStats cs = new CacheStats();

        if (query.isCacheable()) {
            Cache cache = ccf.get(query);
            if (cache != null) {
                if (cache.isKeyInCache(getId())) {
                    Element el = cache.get(getId());
                    cs.setExpired(el == null || el.isExpired());

                    if (el != null && !cs.isExpired()) {
                        cs.setLastUpdate(el.getLastUpdateTime());
                        cs.setExpTime(el.getExpirationTime());
                        cs.setHitCount(el.getHitCount());
                    }
                }
            }
        }
        return cs;
    }

    private Integer id = null;

    public final Integer getId() {
        if (id == null) {
            HashCodeBuilder hcb = new HashCodeBuilder(17, 37).append(this.getClass())
                    .append(getQuery().getQid().getId());

            for (Object part : getIdParts()) {
                hcb.append(part);
            }

            for (Map.Entry<QueryParameter, Object> e : getParameters().entrySet()) {
                hcb.append(e.getKey().getName());
                hcb.append(e.getValue());
            }

            this.id = hcb.toHashCode();
        }
        return id;
    }

    protected abstract List getIdParts();

    public abstract E createExporter();

}