blob: fd3b8063db12684a6b210f3b98668de8b4c858f4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.openejb.arquillian.common;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @version $Rev$ $Date$
*/
public class ObjectMap extends AbstractMap<String, Object> {
private final Object object;
private Map<String,Entry<String,Object>> attributes;
private Set<Entry<String,Object>> entries;
public ObjectMap(final Object object) {
this(object.getClass(), object);
}
public ObjectMap(final Class clazz) {
this(clazz, null);
}
public ObjectMap(final Class<?> clazz, final Object object) {
this.object = object;
attributes = new HashMap<String, Entry<String, Object>>();
for (final Field field : clazz.getFields()) {
final FieldEntry entry = new FieldEntry(field);
attributes.put(entry.getKey(), entry);
}
for (final Method getter : clazz.getMethods()) {
try {
if (!getter.getName().startsWith("get")) {
continue;
}
if (getter.getParameterTypes().length != 0) {
continue;
}
final String name = getter.getName().replaceFirst("get", "set");
final Method setter = clazz.getMethod(name, getter.getReturnType());
final MethodEntry entry = new MethodEntry(getter, setter);
attributes.put(entry.getKey(), entry);
} catch (final NoSuchMethodException e) {
// no-op
}
}
entries = Collections.unmodifiableSet(new HashSet<Entry<String, Object>>(attributes.values()));
}
@Override
public Object get(final Object key) {
final Entry<String, Object> entry = attributes.get(key);
if (entry == null) {
return null;
}
return entry.getValue();
}
@Override
public Object put(final String key, final Object value) {
final Entry<String, Object> entry = attributes.get(key);
if (entry == null) {
return null;
}
return entry.setValue(value);
}
@Override
public boolean containsKey(final Object key) {
return attributes.containsKey(key);
}
@Override
public Object remove(final Object key) {
throw new UnsupportedOperationException();
}
@Override
public Set<Entry<String, Object>> entrySet() {
return entries;
}
public class FieldEntry implements Entry<String, Object> {
private final Field field;
public FieldEntry(final Field field) {
this.field = field;
}
@Override
public String getKey() {
return field.getName();
}
@Override
public String getValue() {
try {
return (String) field.get(object);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
@Override
public Object setValue(final Object value) {
try {
final Object replaced = getValue();
field.set(object, value);
return replaced;
} catch (final IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
}
public class MethodEntry implements Entry<String, Object> {
private final String key;
private final Method getter;
private final Method setter;
public MethodEntry(final Method getter, final Method setter) {
final StringBuilder name = new StringBuilder(getter.getName());
// remove 'set' or 'get'
name.delete(0, 3);
// lowercase first char
name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
this.key = name.toString();
this.getter = getter;
this.setter = setter;
}
protected Object invoke(final Method method, final Object... args) {
try {
return method.invoke(object, args);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e);
} catch (final InvocationTargetException e) {
throw new ArquillianRuntimeException(e.getCause());
}
}
@Override
public String getKey() {
return key;
}
@Override
public Object getValue() {
return invoke(getter);
}
@Override
public Object setValue(final Object value) {
final Object original = getValue();
invoke(setter, value);
return original;
}
}
}