001/* 
002 * JKNIV, SQLegance keeping queries maintainable.
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.classification;
021
022import java.sql.ResultSet;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.HashSet;
026import java.util.LinkedHashMap;
027import java.util.List;
028import java.util.Map;
029import java.util.Set;
030
031import net.sf.jkniv.reflect.beans.CapitalNameFactory;
032import net.sf.jkniv.reflect.beans.Capitalize;
033import net.sf.jkniv.reflect.beans.ObjectProxy;
034import net.sf.jkniv.reflect.beans.ObjectProxyFactory;
035import net.sf.jkniv.whinstone.classification.Transformable.TransformableType;
036
037/**
038 * Create group of objects with a tabular result {@code <R>}.
039 * 
040 * @param <T> type of grouped objects
041 * @param <R> The driver result of a query like {@link ResultSet}
042 * 
043 * @author alisson
044 */
045public class GroupingBy<T, R> implements Groupable<T, R>
046{
047    private static final Capitalize CAPITAL_GETTER = CapitalNameFactory.getInstanceOfGetter();
048    private final Transformable<R>  transform;
049    private final Map<String, T>    grouped;
050    private final List<String>      keys;
051    private final Class<T>          type;
052    
053    public GroupingBy(List<String> keys, Class<T> type, Transformable.TransformableType transformableType)
054    {
055        this.grouped = new LinkedHashMap<String, T>();
056        this.keys = keys;
057        this.type = type;
058        if (transformableType == TransformableType.MAP)
059            this.transform = (Transformable<R>) new MapTransform();
060        //else if (transformableType == TransformableType.RESULT_SET)
061        //    this.transform = (Transformable<R>) new ResultSetTransform();
062        else
063            this.transform = (Transformable<R>) new ObjectTransform();
064    }
065    
066    public GroupingBy(List<String> keys, Class<T> type, Transformable<R> transform)
067    {
068        this.grouped = new LinkedHashMap<String, T>();
069        this.keys = keys;
070        this.type = type;
071        this.transform = transform;
072    }
073    
074    /* (non-Javadoc)
075     * @see net.sf.jkniv.sqlegance.classifier.Groupable#classifier(R)
076     */
077    @Override
078    @SuppressWarnings({ "rawtypes" })
079    public void classifier(R row)
080    {
081        ObjectProxy<R> rowProxy = ObjectProxyFactory.of(row);
082        StringBuilder keySb = new StringBuilder();
083        for (String k : this.keys)
084        {
085            Object keyValue = null;
086            if (row instanceof Map)
087                keyValue = ((Map) row).get(k);
088            else
089                keyValue = rowProxy.invoke(CAPITAL_GETTER.does(k));
090            
091            if (keyValue != null)
092                keySb.append(keyValue.toString());
093        }
094        String key = keySb.toString();
095        T object = grouped.get(key);
096        if (object == null)
097        {
098            object = transform.transform(row, type);
099            grouped.put(key, object);
100        }
101        else
102        {
103            //System.out.println("   ROW -> " + row);
104            //System.out.println("OBJECT -> " + object);
105            transform.transform(row, object);
106        }
107    }
108    
109    /* (non-Javadoc)
110     * @see net.sf.jkniv.sqlegance.classifier.Groupable#asCollection()
111     */
112    @Override
113    public Collection<T> asCollection()
114    {
115        return grouped.values();
116    }
117    
118    /* (non-Javadoc)
119     * @see net.sf.jkniv.sqlegance.classifier.Groupable#asList()
120     */
121    @Override
122    public List<T> asList()
123    {
124        return new ArrayList<T>(grouped.values());
125    }
126    
127    /* (non-Javadoc)
128     * @see net.sf.jkniv.sqlegance.classifier.Groupable#asSet()
129     */
130    @Override
131    public Set<T> asSet()
132    {
133        return new HashSet<T>(grouped.values());
134    }
135    
136}