/* * Copyright 2008-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.nominanuda.hibernate; import static com.nominanuda.zen.common.Str.STR; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.nominanuda.zen.obj.Arr; import com.nominanuda.zen.obj.JsonType; import com.nominanuda.zen.obj.Obj; public class ObjectExpander { private String idField = "id"; private List<String> fixedProps = Arrays.asList("title"); private List<String> discardedKeys = new LinkedList<String>(); private Map<String, PathMapFactory> expandedMaps = new HashMap<String, PathMapFactory>(); private Map<String, PathMapFactory> nakedMaps = new HashMap<String, PathMapFactory>(); public Obj expand(Map<String, Object> obj, String type, boolean expand) { PathMap pm = createPathMap(expand, type);//TODO return compileObject(obj, pm); } protected PathMap createPathMap(boolean expand, String typeOrNull) { if(typeOrNull == null) { return PathMapFactory.defaultPathMap(); } else { PathMapFactory f = expand ? expandedMaps.get(typeOrNull) : nakedMaps.get(typeOrNull); return f == null ? PathMapFactory.defaultPathMap() : f.create(); } } //TODO array of array not supported private Obj compileObject(Map<String, ? extends Object> m, PathMap pathMap) { for(String k : discardedKeys) { m.remove(k); } Obj res = Obj.make(); for(Entry<String, ? extends Object> entry : m.entrySet()) { String k = entry.getKey(); Object v = entry.getValue(); if(v == null) { continue; } else if(v instanceof Collection<?>) { if(pathMap.isTraversable(k)) { Arr arr = res.arr(k); for(Object o : (Collection<?>)v) { Object x = evalScalarOrObject(k, o, pathMap); arr.add(x); } } } else { Object x = evalScalarOrObject(k, v, pathMap); if(x != null) { res.put(k, x); } } } return res; } private Object evalScalarOrObject(String k, Object v, PathMap pathMap) { if(v == null) { return null; } else if(JsonType.isNullablePrimitive(v)) { return v; } else if(v instanceof Map<?,?>) { @SuppressWarnings("unchecked") Map<String, Object> m = (Map<String, Object>)v; if(pathMap.isTraversable(k)) { return compileObject(m, pathMap.traverse(k)); } else if(m.containsKey(idField)) { Obj o = Obj.make(); o.put(idField, (String)m.get(idField)); for(String p : fixedProps) { if(m.containsKey(p)) { o.put(p, m.get(p)); } } return o; } else { return compileObject(m, pathMap.traverseNoChek(k)); } } else {//bail out throw new IllegalArgumentException( "type "+v.getClass().getName() + " not supported @ "+pathMap.soFar()); } } private static class PathMapFactory { private String pathSpec; protected PathMapFactory(String spec) { pathSpec = spec; } public PathMap create() { return new PathMap(pathSpec); } public static PathMap defaultPathMap() { return new PathMap(""); } } public void setExpandedMaps(Map<String, String> maps) { this.expandedMaps = new HashMap<String, PathMapFactory>(); for(Entry<String, String> entry : maps.entrySet()) { this.expandedMaps.put(entry.getKey(), new PathMapFactory(entry.getValue())); } } public void setNakedMaps(Map<String, String> maps) { this.nakedMaps = new HashMap<String, PathMapFactory>(); for(Entry<String, String> entry : maps.entrySet()) { this.nakedMaps.put(entry.getKey(), new PathMapFactory(entry.getValue())); } } public static ObjectExpander defaultExpander() { ObjectExpander o = new ObjectExpander(); return o; } public void setDiscardedKeys(String discardedKeysCsv) { this.discardedKeys = STR.splitAndTrim(discardedKeysCsv,","); } public void setIdField(String idField) { this.idField = idField; } }