Author: bpoussin Date: 2012-08-24 16:50:51 +0200 (Fri, 24 Aug 2012) New Revision: 258 Url: http://chorem.org/repositories/revision/chorem/258 Log: Evolution #738: Order the linked objects Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/MapWithDefault.java Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/DashboardAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/DashboardAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/DashboardAction.java 2012-08-24 13:33:48 UTC (rev 257) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/DashboardAction.java 2012-08-24 14:50:51 UTC (rev 258) @@ -23,8 +23,16 @@ package org.chorem.webmotion.actions; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.logging.Log; @@ -34,17 +42,20 @@ import org.chorem.entities.Category; import org.chorem.entities.Configuration; import org.chorem.entities.Employee; +import org.chorem.entities.Interval; import org.chorem.entities.Invoice; import org.chorem.entities.Quotation; import org.chorem.entities.QuotationStatus; import org.chorem.entities.Task; import org.chorem.entities.TaskStatus; import org.chorem.entities.Time; +import org.chorem.entities.Touch; import org.chorem.entities.Vacation; import org.chorem.entities.VacationStatus; import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.render.Render; -import org.nuiton.util.ObjectUtil; +import org.nuiton.util.DateUtil; +import org.nuiton.wikitty.entities.Element; import org.nuiton.wikitty.entities.ElementField; import org.nuiton.wikitty.query.WikittyQuery; import org.nuiton.wikitty.query.WikittyQueryMaker; @@ -52,22 +63,6 @@ import org.nuiton.wikitty.query.WikittyQueryResultTreeNode; import org.nuiton.wikitty.query.conditions.Aggregate; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.commons.lang3.StringUtils; -import org.chorem.entities.Interval; -import org.chorem.entities.Touch; -import org.nuiton.util.DateUtil; -import org.nuiton.wikitty.entities.Element; - /** * * @author poussin @@ -84,134 +79,6 @@ static final public String budgetDateFormat = "MM/yyyy"; static final public String summaryDateFormat = "dd/MM/yyyy hh:mm"; - /** - * Permet de decore une map dont toutes les valeurs manquant lorsqu'on les - * demandent sont initialise avec l'objet passe dans le constructeur. - * L'objet initialise est pousse dans la map avant d'etre retourne. - * - * TODO poussin 20120526 move this class to nuiton-utils - * - * @param <K> - * @param <V> - */ - static public class MapWithDefault<K, V> implements Map<K, V>, Cloneable { - protected Map<K, V> map; - protected Object defaultValue; - protected Collection args; - - @Override - public Object clone() throws CloneNotSupportedException { - MapWithDefault result = (MapWithDefault)super.clone(); - // class cast exception if map is not cloneable - result.map = (Map)ObjectUtil.clone((Cloneable)map); - return result; - } - - /** - * L'objet par default utilise est l'objet passe en parametre s'il n'est - * pas clonable ou un clone de l'objet s'il est clonable. - * @param map la map a decore - * @param defaultValue la valeur par default - */ - public MapWithDefault(Map<K, V> map, V defaultValue) { - this.map = map; - this.defaultValue = defaultValue; - } - - /** - * L'objet par defaut est construit via le constructeur de la classe - * passe en parametre prenant les arguments args. - * @param map la map a decore - * @param defaultValue la class de la valeur par defaut - * @param args les arguments du construteur pour la classe - */ - public MapWithDefault(Map<K, V> map, Class<V> defaultValue, Object... args) { - this.map = map; - this.defaultValue = defaultValue; - if (ArrayUtils.isNotEmpty(args)) { - this.args = Arrays.asList(args); - } - } - - /** - * Get new instance of defaultValue if defaultValue is clonable or - * return directly defaultValue otherwize. - * @return - */ - protected V getDefaultValue() { - try { - Object result = defaultValue; - if (defaultValue instanceof Class) { - if (args == null) { - result = ((Class)defaultValue).newInstance(); - } else { - result = ObjectUtil.newInstance(((Class)defaultValue), args, true); - } - } else if (defaultValue instanceof Cloneable) { - result = ObjectUtil.clone(((Cloneable)defaultValue)); - } - return (V)result; - } catch (Exception eee) { - throw new RuntimeException(eee); - } - } - - // on surcharge le get pour creer automatiquement les objets - @Override - public V get(Object key) { - V result = map.get(key); - if (result == null) { - result = getDefaultValue(); - put((K)key, result); - } - return result; - } - - public int size() { - return map.size(); - } - - public boolean isEmpty() { - return map.isEmpty(); - } - - public boolean containsKey(Object key) { - return map.containsKey(key); - } - - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - public V put(K key, V value) { - return map.put(key, value); - } - - public V remove(Object key) { - return map.remove(key); - } - - public void putAll(Map<? extends K, ? extends V> m) { - map.putAll(m); - } - - public void clear() { - map.clear(); - } - - public Set<K> keySet() { - return map.keySet(); - } - - public Collection<V> values() { - return map.values(); - } - - public Set<Entry<K, V>> entrySet() { - return map.entrySet(); - } - } - protected <E> Map<String, List<Attachment>> prepareAttachment(ChoremClient client, Collection<E> ids) { // recherche des attachments de chaque quotation trouvee WikittyQuery attachmentQuery = new WikittyQueryMaker().and() @@ -271,7 +138,7 @@ //////////////////////////////////////////////////////////////////////////// // - // C O N T A C T + // A C C U E I L // //////////////////////////////////////////////////////////////////////////// Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java 2012-08-24 13:33:48 UTC (rev 257) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java 2012-08-24 14:50:51 UTC (rev 258) @@ -23,6 +23,7 @@ package org.chorem.webmotion.actions; import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimaps; import java.io.ByteArrayInputStream; import java.net.MalformedURLException; import java.util.ArrayList; @@ -35,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import org.apache.commons.lang3.ArrayUtils; @@ -148,7 +150,7 @@ */ // depth est un Integer car si c'est un int et qu'il n'existe pas dans les parametres // l'appel plante au lieu de passer 0 comme valeur par defaut - public LinkedHashMultimap<String, Wikitty> searchAsMap(ChoremClient client, String[] extension, String query, Integer depth) { + public Map<String, List<Wikitty>> searchAsMap(ChoremClient client, String[] extension, String query, Integer depth) { if (depth == null) { depth = 0; } @@ -179,11 +181,13 @@ client.findAllByQuery(Wikitty.class, q); // on classe par extension demande les resultats - LinkedHashMultimap<String, Wikitty> map = LinkedHashMultimap.create(); + Map<String, List<Wikitty>> map = + new MapWithDefault<String, List<Wikitty>>( + new TreeMap<String, List<Wikitty>>(), new LinkedList<Wikitty>()); for (Wikitty w : results) { for (WikittyExtension ext : w.getExtensions()) { if (exts.contains(ext)) { - map.put(ext.getName(), w); + map.get(ext.getName()).add(w); } } } @@ -191,16 +195,14 @@ List<String> extExcluded = client.getConfig().getOptionAsList( ChoremConfigOption.CHOREM_EXTENSION_SEARCH_EXCLUSION.key).getOption(); for (String ext : extExcluded) { - map.removeAll(ext); + map.remove(ext); } if (extension != null) { for (String ext : extension) { // The wanted extensions should be present, even without wikitties... - Set<Wikitty> wikitties = map.get(ext); - if (wikitties == null || wikitties.isEmpty() ) { - map.put(ext, null); - } + // just get, create entry + map.get(ext); } } return map; @@ -208,7 +210,7 @@ } public Render search(ChoremClient client, String[] extension, String query) { - LinkedHashMultimap<String, Wikitty> map = searchAsMap(client, extension, query, 1); + Map<String, List<Wikitty>> map = searchAsMap(client, extension, query, 1); return renderView("search.jsp", "result", map); } @@ -245,22 +247,23 @@ // query += " AND ("+extensionRestriction+")"; // } - LinkedHashMultimap<String, Wikitty> map = searchAsMap(client, extension, query, 1); + Map<String, List<Wikitty>> map = searchAsMap(client, extension, query, 1); List<Map<String, String>> result = new ArrayList<Map<String, String>>(map.size()); - for (Map.Entry<String, Wikitty> e : map.entries()) { + for (Map.Entry<String, List<Wikitty>> e : map.entrySet()) { String extName = e.getKey(); - Wikitty value = e.getValue(); - // Avoid potential null value - if (value != null) { - String id = value.getWikittyId(); - String label = value.toString(extName); - Map<String, String> item = new LinkedHashMap<String, String>(); - item.put("extension", extName); - item.put("label", label); - item.put("value", label); - item.put("name", label); - item.put("id", id); - result.add(item); + for (Wikitty value : e.getValue()) { + // Avoid potential null value + if (value != null) { + String id = value.getWikittyId(); + String label = value.toString(extName); + Map<String, String> item = new LinkedHashMap<String, String>(); + item.put("extension", extName); + item.put("label", label); + item.put("value", label); + item.put("name", label); + item.put("id", id); + result.add(item); + } } } return renderJSON(result); @@ -561,7 +564,7 @@ */ public Render searchRelated(ChoremClient client, String id) { String query = id + " AND id != " + id; - LinkedHashMultimap<String, Wikitty> map = searchAsMap(client, null, query, 0); + Map<String, List<Wikitty>> map = searchAsMap(client, null, query, 0); return renderView("search.jsp", "result", map); } Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/MapWithDefault.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/MapWithDefault.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/MapWithDefault.java 2012-08-24 14:50:51 UTC (rev 258) @@ -0,0 +1,148 @@ +package org.chorem.webmotion.actions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import org.apache.commons.lang3.ArrayUtils; +import org.nuiton.util.ObjectUtil; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +/** + * Permet de decore une map dont toutes les valeurs manquant lorsqu'on les + * demandent sont initialise avec l'objet passe dans le constructeur. + * L'objet initialise est pousse dans la map avant d'etre retourne. + * + * TODO poussin 20120526 move this class to nuiton-utils + * + * @param <K> + * @param <V> + */ +public class MapWithDefault<K, V> implements Map<K, V>, Cloneable { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + protected Map<K, V> map; + protected Object defaultValue; + protected Collection args; + + @Override + public Object clone() throws CloneNotSupportedException { + MapWithDefault result = (MapWithDefault) super.clone(); + // class cast exception if map is not cloneable + result.map = (Map) ObjectUtil.clone((Cloneable) map); + return result; + } + + /** + * L'objet par default utilise est l'objet passe en parametre s'il n'est + * pas clonable ou un clone de l'objet s'il est clonable. + * @param map la map a decore + * @param defaultValue la valeur par default + */ + public MapWithDefault(Map<K, V> map, V defaultValue) { + this.map = map; + this.defaultValue = defaultValue; + } + + /** + * L'objet par defaut est construit via le constructeur de la classe + * passe en parametre prenant les arguments args. + * @param map la map a decore + * @param defaultValue la class de la valeur par defaut + * @param args les arguments du construteur pour la classe + */ + public MapWithDefault(Map<K, V> map, Class<V> defaultValue, Object... args) { + this.map = map; + this.defaultValue = defaultValue; + if (ArrayUtils.isNotEmpty(args)) { + this.args = Arrays.asList(args); + } + } + + /** + * Get new instance of defaultValue if defaultValue is clonable or + * return directly defaultValue otherwize. + * @return + */ + protected V getDefaultValue() { + try { + Object result = defaultValue; + if (defaultValue instanceof Class) { + if (args == null) { + result = ((Class) defaultValue).newInstance(); + } else { + result = ObjectUtil.newInstance((Class) defaultValue, args, true); + } + } else if (defaultValue instanceof Cloneable) { + result = ObjectUtil.clone((Cloneable) defaultValue); + } + return (V) result; + } catch (Exception eee) { + throw new RuntimeException(eee); + } + } + + // on surcharge le get pour creer automatiquement les objets + @Override + public V get(Object key) { + V result = map.get(key); + if (result == null) { + result = getDefaultValue(); + put((K) key, result); + } + return result; + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + public V put(K key, V value) { + return map.put(key, value); + } + + public V remove(Object key) { + return map.remove(key); + } + + public void putAll(Map<? extends K, ? extends V> m) { + map.putAll(m); + } + + public void clear() { + map.clear(); + } + + public Set<K> keySet() { + return map.keySet(); + } + + public Collection<V> values() { + return map.values(); + } + + public Set<Entry<K, V>> entrySet() { + return map.entrySet(); + } + +}