001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2011-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.util; 011 012import java.lang.reflect.Field; 013import java.lang.reflect.Modifier; 014import java.util.*; 015 016/** 017 * View of an object as a map. Each attribute name is an key, and the value of 018 * the attribute is the value. 019 * 020 * <p>Currently only returns public fields, not methods.</p> 021 */ 022public class BeanMap extends AbstractMap<String, Object> { 023 private final Object o; 024 private final Info info; 025 private static final Map<Class, Info> INFO_MAP = 026 new WeakHashMap<Class, Info>(); 027 028 /** 029 * Creates a map view onto an object. 030 * 031 * @param o Object 032 */ 033 public BeanMap(Object o) { 034 this.o = o; 035 this.info = getInfo(o.getClass()); 036 } 037 038 private static Info getInfo(Class<?> clazz) { 039 synchronized (INFO_MAP) { 040 Info info = INFO_MAP.get(clazz); 041 if (info == null) { 042 info = new Info(clazz); 043 INFO_MAP.put(clazz, info); 044 } 045 return info; 046 } 047 } 048 049 @Override 050 public Set<Entry<String, Object>> entrySet() { 051 return new AbstractSet<Entry<String, Object>>() { 052 @Override 053 public Iterator<Entry<String, Object>> iterator() { 054 final Iterator<BeanField> fieldIterator = 055 info.fields.iterator(); 056 return new Iterator<Entry<String, Object>>() { 057 public boolean hasNext() { 058 return fieldIterator.hasNext(); 059 } 060 061 public Entry<String, Object> next() { 062 final BeanField field = fieldIterator.next(); 063 return Pair.of(field.name(), field.value(o)); 064 } 065 066 public void remove() { 067 throw new UnsupportedOperationException(); 068 } 069 }; 070 } 071 072 @Override 073 public int size() { 074 return info.fields.size(); 075 } 076 }; 077 } 078 079 public static String xxx(Object o) { 080 return o.getClass().getSimpleName() + new BeanMap(o); 081 } 082 083 private static class Info { 084 private List<BeanField> fields = new ArrayList<BeanField>(); 085 086 public Info(Class<? extends Object> clazz) { 087 for (final Field field : clazz.getDeclaredFields()) { 088 final int mod = field.getModifiers(); 089 if (Modifier.isStatic(mod) 090 || !Modifier.isPublic(mod)) 091 { 092 continue; 093 } 094 fields.add( 095 new BeanField() { 096 public String name() { 097 return field.getName(); 098 } 099 100 public Object value(Object o) { 101 try { 102 return field.get(o); 103 } catch (IllegalAccessException e) { 104 return null; 105 } 106 } 107 } 108 ); 109 } 110 } 111 } 112 113 private interface BeanField { 114 String name(); 115 Object value(Object o); 116 } 117} 118 119// End BeanMap.java