summaryrefslogtreecommitdiffstats
path: root/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java
blob: f2c78af41024a942e01629c4e5dad8fa6c738a6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
 *
 *  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 com.agfa.hap.sdo.mapper;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import com.agfa.hap.sdo.DataMapper;
import com.agfa.hap.sdo.Property;
import com.agfa.hap.sdo.SnapshotDefinition;
import com.agfa.hap.sdo.Type;

/**
 * DataMapper that uses Java Bean conventions to access data on java classes.
 * This mapper assumes that for each {@link Property} there are appropriately named
 * accessors defined on the corresponding class.
 * Each {@link Type} is mapped to the java class with the same name. It is also possible
 * to register a class as corresponding to a type. 
 * <p/>
 * This DataMapper ensures that opposite properties are properly filled in. As such, objects will
 * not be added multiple times to a many-valued property if that property has an opposite property.
 * @author AMOCZ
 */
public class JavaBeanMapper implements DataMapper<Object> {

	public JavaBeanMapper(TypeMapper typeMapper) {
		this.typeMapper = typeMapper;
	}
	
	public Iterator<?> getObjects(Object object, Property property) {
		PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property);
		if (propertyAccessor == null){
			throw new RuntimeException("no property accessor for sdo property " + property);
		}
		return ((Collection<?>) propertyAccessor.getValue(object, property, this)).iterator();
	}

	public Object getProperty(Object object, Property property) {
		PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property);
		if (propertyAccessor == null){
			throw new RuntimeException("no property accessor for sdo property " + property);
		}
		return propertyAccessor.getValue(object, property, this);
	}

	public void setProperty(Object object, Property property, Object value) {
		PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property);
		if (propertyAccessor == null){
			throw new RuntimeException("no property accessor for sdo property " + property);
		}
		propertyAccessor.setValue(object, property, value, this);
		if (property.getOpposite() != null && value != null) {
			setOpposite(object, property, value);
		}
	}

	protected void setOpposite(Object object, Property property, Object value) {
		typeMapper.property(value.getClass(), property.getOpposite()).setValue(value, property.getOpposite(), object, this);
	}
	
	public void setUnavailable(Object object, Property property) {
	}	

	public Type getType(Object object) {
		return typeMapper.getCorrespondingType(object.getClass());		
	}

	public Type getCorrespondingType(Class clazz) {
		return typeMapper.getCorrespondingType(clazz);
	}

	public TypeMapper getTypeMapper() {
		return typeMapper;
	}
	
	public Object create(Type type) {
		Constructor<?> constructor = typeMapper.getConstructor(type);
		if (constructor == null){
			return null;
		}
		try {			
			return constructor.newInstance((Object[]) null);
		} catch (InstantiationException e) {
			throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e);
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e);
		} catch (InvocationTargetException e) {
			throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e);
		}
	}

	public Object newProxy(Type type, Object identity) {
		return null;
	}

	public boolean isProxy(Object instance) {
		return false;
	}

	
	public Collection<Object> getProperties(Collection<Object> objects, Property bulkProperty, SnapshotDefinition def) {
		Iterator<Object> it = objects.iterator();
		if (!it.hasNext()) {
			return Collections.emptyList();
		}
		return (Collection<Object>) typeMapper.property(it.next().getClass(), bulkProperty).getValues(objects, bulkProperty, def, this);
	}

	public boolean isBulkProperty(Class clazz, Property property) {
		PropertyAccessor propertyAccessor = typeMapper.property(clazz, property);
		if (propertyAccessor == null){
			throw new RuntimeException("no property accessor for sdo property " + property);
		}
		return propertyAccessor.isBulkAccessor();
	}


	private final TypeMapper typeMapper;

}