All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wadpam.gaelic.tree.CrudLeaf Maven / Gradle / Ivy

The newest version!
/*
 * INSERT COPYRIGHT HERE
 */

package com.wadpam.gaelic.tree;

import com.wadpam.gaelic.GaelicServlet;
import com.wadpam.gaelic.Node;
import com.wadpam.gaelic.converter.BaseConverter;
import com.wadpam.gaelic.crud.CrudService;
import com.wadpam.gaelic.exception.BadRequestException;
import com.wadpam.gaelic.exception.MethodNotAllowedException;
import com.wadpam.gaelic.exception.NotFoundException;
import com.wadpam.gaelic.json.JCursorPage;
import com.wadpam.gaelic.json.JKey;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author sosandstrom
 */
public class CrudLeaf> extends LeafAdapter {
    
    public static final int STATUS_OK = 200;
    public static final int STATUS_CREATED = 201;
    
    public static final int ERR_OFFSET_PAGE = 1;
    public static final int ERR_OFFSET_DETAILS = 2;
    public static final int ERR_OFFSET_METHOD = 3;
    public static final int ERR_OFFSET_DELETE_ALL = 4;
    
    public static final String REQUEST_ATTR_FILENAME = "com.wadpam.gaelic.CrudFilename";
    public static final String REQUEST_PARAM_EXPECTS = "_expects";
    
    private static final TreeSet SUPPORTED_METHODS = new TreeSet(
            Arrays.asList(METHOD_DELETE, METHOD_GET, METHOD_POST));
    
    private final Class domainClass;
    private final Class idClass;
    
    protected S service;
    
    protected BaseConverter converter;

    public CrudLeaf(Class domainClass, Class idClass, Class jsonClass) {
        super(jsonClass, domainClass.getSimpleName());
        this.domainClass = domainClass;
        this.idClass = idClass;
    }
    
    public void addInnerObjects(HttpServletRequest request, 
            HttpServletResponse response,
            String domain,
            J jEntity) {
        addInnerObjects(request, response, domain, 
                Arrays.asList(jEntity));
    }

    /** This implementation does nothing, please override */
    public void addInnerObjects(HttpServletRequest request, 
            HttpServletResponse response,
            String domain,
            Iterable jEntity) {
        // do nothing
    }
    
    // Convert iterable
    public Collection convertWithInner(HttpServletRequest request, HttpServletResponse response,
            String domain, Iterable from) {
        if (null == from)
            return new ArrayList();

        // basic conversion first
        final Collection returnValue = converter.convertDomains(from);

        // then add inner objects batch-style
        addInnerObjects(request, response, domain, returnValue);
        
        return returnValue;
    }

    @Override
    protected void createResource(HttpServletRequest request, HttpServletResponse response, JKey jKey, J body) throws ServletException, IOException {
        final T domain = converter.convertJson(body);
        
        if (null != domain) {
            final String id = service.create(domain);
            if ("302".equals(request.getParameter(REQUEST_PARAM_EXPECTS))) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
            else {
                final J responseBody = converter.convertDomain(domain);
                setResponseBody(request, STATUS_CREATED, responseBody);
            }
        }
    }
    
    protected void delete(HttpServletRequest request, HttpServletResponse response,
            String id) {
        service.delete(null, id);
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        final String id = getId(request);
        LOG.debug("doDelete {}", id);
        
        // GET details or page?
        if (null != id) {
            delete(request, response, id);
        }
        else {
            throw new BadRequestException(getErrorBaseCode()+ERR_OFFSET_DELETE_ALL, toString(), null);
        }
    }

    @Override
    protected void getResourceByKey(HttpServletRequest request, HttpServletResponse response, JKey jKey) throws ServletException, IOException {

        // schema-based manager forms
        if ("manager.html".equals(jKey.getId())) {
            final String fwdPath = "/internal/bootstrap-schema.html";
            forward(request, response, fwdPath);
            return;
        }
        
        // schema AJAX method
        if ("schema".equals(jKey.getId())) {
            getSchema(request, response);
            return;
        }

        T domain = service.get(jKey.getParentKey(), getId(jKey.getId()));
        if (null != domain) {
            J body = converter.convertDomain(domain);
            setResponseBody(request, 200, body);
        }
        else {
            throw new NotFoundException(getErrorBaseCode()+ERR_OFFSET_DETAILS, toString(), null);
        }
    }
    
    
    
    protected int getErrorBaseCode() {
        return GaelicServlet.ERROR_CODE_CRUD_BASE;
    }
    
    protected String getId(HttpServletRequest request) {
        final String filename = (String) request.getAttribute(REQUEST_ATTR_FILENAME);
        return getId(filename);
    }
    
    protected String getId(final String filename) {
//        ID id = null;
//        
//        if (null != filename) {
//            // if ID is Long, parse filename
//            if (Long.class.equals(idClass)) {
//                try {
//                    Long l = Long.parseLong(filename);
//                    id = (ID) l;
//                }
//                catch (NumberFormatException notLong) {
//                    throw new BadRequestException(GaelicServlet.ERROR_CODE_ID_LONG, filename, null);
//                }
//            }
//            else {
//                id = (ID) filename;
//            }
//        }
//        
//        return id;
        return filename;
    }
    
    @Override
    protected void getResourcesPage(HttpServletRequest request, HttpServletResponse response,
            JKey parentKey, int pageSize, String cursorKey) throws ServletException, IOException {
        
        final JCursorPage page = service.getPage(parentKey, pageSize, cursorKey);
        final JCursorPage body = converter.convertDomainPage(page);
        
        setResponseBody(request, 200, body);
    }
    
    protected void getSchema(HttpServletRequest request, HttpServletResponse response) {
        final TreeMap body = new TreeMap();
        body.put("tableName", service.getTableName());
        body.put("primaryKeyName", service.getPrimaryKeyColumnName());
        body.put("primaryKeyType", getType(service.getPrimaryKeyColumnName(), service.getPrimaryKeyColumnClass()));
        final TreeMap columns = new TreeMap();
        body.put("columns", columns);
        
        Class value;
        for (Map.Entry entry : service.getTypeMap().entrySet()) {
            columns.put(entry.getKey(), getType(entry.getKey(), entry.getValue()));
        }
        
        setResponseBody(request, 200, body);
    }
    
//    @Override
//    public Node getServingNode(HttpServletRequest request, LinkedList pathList, final int pathIndex) {
//        return isServingNode(request, pathList, pathIndex, supportedMethods(), getErrorBaseCode()) ? this : null;
//    }
//    
    public static boolean isServingNode(HttpServletRequest request, 
            LinkedList pathList, final int pathIndex,
            final Set supportedMethods, int errorBaseCode) {
        final String method = request.getMethod();
        LOG.trace("   mapping {} {} for {} ({})", new Object[] {
            method, request.getRequestURI(), pathIndex, pathList.size()
        });
        
            
        // support '' and /
        if (pathIndex == pathList.size() || 
                (pathIndex == pathList.size()-1 && pathList.getLast().isEmpty())) {
            if (supportedMethods.contains(method)) {
                return true;
            }
            else {
                throw new MethodNotAllowedException(errorBaseCode + ERR_OFFSET_METHOD, 
                        method, null, supportedMethods);
            }
        }

        // support /{id} and /{id}/ 
        if ((pathIndex == pathList.size()-1) ||
                (pathIndex == pathList.size()-2 && pathList.getLast().isEmpty())) {

            request.setAttribute(REQUEST_ATTR_FILENAME, pathList.get(pathIndex));
            if (supportedMethods.contains(method)) {
                return true;
            }
            else {
                throw new MethodNotAllowedException(errorBaseCode + ERR_OFFSET_METHOD, 
                        method, null, supportedMethods);
            }
        }
        
        return false;
    }
    
    
    public static String getType(String key, Class value) {
        if (Long.class.equals(value) ||
                Integer.class.equals(value) ||
                Short.class.equals(value) ||
                Byte.class.equals(value)) {
            return "number";
        }
        else if (String.class.equals(value)) {
            return "email".equals(key) ? "email" : "text";
        }
        else if (Boolean.class.equals(value)) {
            return "boolean";
        }
        else if (Date.class.equals(value)) {
            return "datetime";
        }
        return value.getSimpleName();
    }
    
    /**
     * Override to implement a read-only Leaf.
     * @return the supported HTTP methods for this CrudLeaf
     */
    protected Set supportedMethods() {
        return SUPPORTED_METHODS;
    }

    @Override
    protected void updateResource(HttpServletRequest request, HttpServletResponse response, JKey jKey, J body) throws ServletException, IOException {
        final T domain = converter.convertJson(body);
        
        if (null != domain && null != jKey.getId()) {
            service.update(domain);
            if ("302".equals(request.getParameter(REQUEST_PARAM_EXPECTS))) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
            else {
                final J responseBody = converter.convertDomain(domain);
                setResponseBody(request, STATUS_OK, responseBody);
            }
        }
    }
    
    protected J convertWithInner(HttpServletRequest request, HttpServletResponse response,
            String domain, T from) {
        final J to = converter.convertDomain(from);
        addInnerObjects(request, response, domain, to);
        return to;
    }

    public BaseConverter getConverter() {
        return converter;
    }

    public void setConverter(BaseConverter converter) {
        this.converter = converter;
    }

    public S getService() {
        return service;
    }
    
    public void setService(S service) {
        this.service = service;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy