001/* 
002 * JKNIV, whinstone one contract to access your database.
003 * 
004 * Copyright (C) 2017, the original author or authors.
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License.
010 * 
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 * 
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with this library; if not, write to the Free Software Foundation, Inc., 
018 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
019 */
020package net.sf.jkniv.whinstone.couchdb.commands;
021
022import java.io.IOException;
023import java.sql.Statement;
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.List;
027
028import org.apache.http.client.methods.CloseableHttpResponse;
029import org.apache.http.client.methods.HttpPost;
030import org.apache.http.impl.client.CloseableHttpClient;
031import org.apache.http.impl.client.HttpClients;
032import org.apache.http.util.EntityUtils;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036import net.sf.jkniv.sqlegance.RepositoryException;
037import net.sf.jkniv.whinstone.Queryable;
038import net.sf.jkniv.whinstone.couchdb.CouchDbResult;
039import net.sf.jkniv.whinstone.couchdb.HttpBuilder;
040
041@SuppressWarnings({"unchecked", "rawtypes"})
042public class FindCommand extends AbstractCommand implements CouchCommand
043{
044    private static final Logger LOG = LoggerFactory.getLogger(FindCommand.class);
045    private static final Logger LOGSQL = net.sf.jkniv.whinstone.couchdb.LoggerFactory.getLogger();
046    private HttpBuilder httpBuilder;
047    private Queryable queryable;
048    
049    public FindCommand(HttpBuilder httpBuilder, Queryable queryable)
050    {
051        super();
052        this.queryable = queryable;
053        this.httpBuilder = httpBuilder;
054    }
055    
056    
057    @Override
058    public <T> T execute()
059    {
060        String json = null;
061        CloseableHttpResponse response = null;
062        CouchDbResult answer = null;
063        List list = Collections.emptyList();
064        try
065        {
066            CloseableHttpClient httpclient = HttpClients.createDefault();
067            HttpPost httpPost = httpBuilder.newFind(body);
068            printRequest(httpPost);
069            response = httpclient.execute(httpPost);
070            json = EntityUtils.toString(response.getEntity());
071            printResponse(response, json);
072
073            int statusCode = response.getStatusLine().getStatusCode();
074            if (isOk(statusCode))
075            {
076                JsonMapper.setCurrentQuery(queryable);
077                answer = JsonMapper.MAPPER.readerFor(CouchDbResultImpl.class).readValue(json);
078                if(CouchDbResult.class.isAssignableFrom(queryable.getReturnType()))
079                {
080                    list = new ArrayList();
081                    list.add(answer);
082                }
083                else
084                    list = answer.getRows();
085                setBookmark(answer.getBookmark(), queryable);
086                if(queryable.isPaging())
087                    queryable.setTotal(Statement.SUCCESS_NO_INFO);
088                else
089                    queryable.setTotal(answer.getTotalRows());
090            }
091            else if (isNotFound(statusCode))
092            {
093                queryable.setTotal(0);
094                // 204 No Content, 304 Not Modified, 205 Reset Content
095                LOGSQL.warn(errorFormat(httpPost, response.getStatusLine(), json));
096            }
097            else
098            {
099                LOG.error(errorFormat(httpPost, response.getStatusLine(), json));
100                throw new RepositoryException(response.getStatusLine().toString());
101            }
102            //commandHandler.postCommit();
103        }
104        catch (Exception e) // ClientProtocolException | JsonParseException | JsonMappingException | IOException
105        {
106            queryable.setTotal(Statement.EXECUTE_FAILED);
107            //commandHandler.postException();
108            handlerException.handle(e);
109        }
110        finally
111        {
112            if (response != null)
113            {
114                try
115                {
116                    response.close();
117                }
118                catch (IOException e)
119                {
120                    handlerException.handle(e);
121                }
122            }
123        }
124        return (T)list;
125    }
126    
127    /*
128    public <T> List<T> transformRows(List<?> listOfMap, Class<T> clazz)
129    {
130        List<Object> docs = new ArrayList();
131        if (listOfMap != null)
132        {
133            for (Object row : listOfMap)
134                docs.add(JsonMapper.mapper((Map) row, clazz));
135        }
136        return (List<T>) docs;
137    }
138    */
139
140    @Override
141    public String getBody()
142    {
143        return this.body;
144    }
145
146    @Override
147    public HttpMethod asGet()
148    {
149        this.method = HttpMethod.GET;
150        return this.method;
151    }
152
153    @Override
154    public HttpMethod asPost()
155    {
156        this.method = HttpMethod.POST;
157        return this.method;
158    }
159}