1 package org.openrdf.elmo.rolemapper;
2
3 import java.lang.reflect.AnnotatedElement;
4 import java.lang.reflect.Method;
5 import java.util.Collection;
6
7 import org.openrdf.elmo.RdfTypeFactory;
8 import org.openrdf.elmo.RoleMapper;
9 import org.openrdf.elmo.annotations.complementOf;
10 import org.openrdf.elmo.annotations.factory;
11 import org.openrdf.elmo.annotations.intersectionOf;
12 import org.openrdf.elmo.annotations.oneOf;
13 import org.openrdf.elmo.annotations.rdf;
14
15 public class RoleMapperImpl<URI> implements RoleMapper<URI> {
16 private RdfTypeFactory<URI> vf;
17
18 private ComplexMapper<URI> roleMapper;
19
20 public RoleMapperImpl(ComplexMapper<URI> roleMapper) {
21 this.roleMapper = roleMapper;
22 }
23
24 public void setRdfTypeFactory(RdfTypeFactory<URI> vf) {
25 this.vf = vf;
26 roleMapper.setRdfTypeFactory(vf);
27 }
28
29 public Class<?>[] findBaseRoles() {
30 return roleMapper.findBaseRoles();
31 }
32
33 public Collection<Class<?>> findIndividualRoles(URI instance,
34 Collection<Class<?>> classes) {
35 return roleMapper.findIndividualRoles(instance, classes);
36 }
37
38 public Class<?>[] findRoles(URI type) {
39 return roleMapper.findRoles(type);
40 }
41
42 public Collection<Class<?>> findRoles(Collection<URI> types,
43 Collection<Class<?>> roles) {
44 return roleMapper.findRoles(types, roles);
45 }
46
47 public Collection<URI> findSubTypes(Class<?> role, Collection<URI> rdfTypes) {
48 return roleMapper.findSubTypes(role, rdfTypes);
49 }
50
51 public URI findType(Class<?> concept) {
52 return roleMapper.findType(concept);
53 }
54
55 public Collection<URI> findTypes(Class<?> role, Collection<URI> rdfTypes) {
56 return roleMapper.findTypes(role, rdfTypes);
57 }
58
59 public boolean isIndividualRolesPresent(URI instance) {
60 return roleMapper.isIndividualRolesPresent(instance);
61 }
62
63 public boolean isTypeRecorded(URI type) {
64 return roleMapper.isTypeRecorded(type);
65 }
66
67 public void recordFactory(Class<?> javaClass) {
68 assert javaClass.isAnnotationPresent(factory.class) : javaClass;
69 boolean hasFactory = false;
70 for (Method method : javaClass.getMethods()) {
71 if (method.isAnnotationPresent(factory.class)) {
72 Class<?> rtype = method.getReturnType();
73 if (!rtype.isAnnotationPresent(factory.class)) {
74 recordRole(rtype, javaClass, null);
75 hasFactory = true;
76 }
77 }
78 }
79 if (!hasFactory)
80 throw new IllegalArgumentException("Class has now factory methods");
81 recordRole(javaClass, javaClass, null);
82 }
83
84 public void recordFactory(Class<?> javaClass, String type) {
85 assert javaClass.isAnnotationPresent(factory.class) : javaClass;
86 boolean hasFactory = false;
87 URI uri = vf.createRdfType(type);
88 for (Method method : javaClass.getMethods()) {
89 if (method.isAnnotationPresent(factory.class)) {
90 Class<?> rtype = method.getReturnType();
91 if (!rtype.isAnnotationPresent(factory.class)) {
92 recordRole(rtype, javaClass, uri);
93 hasFactory = true;
94 }
95 }
96 }
97 if (!hasFactory)
98 throw new IllegalArgumentException("Class has now factory methods");
99 recordRole(javaClass, javaClass, uri);
100 }
101
102 public void recordRole(Class<?> role) {
103 if (role.isAnnotationPresent(factory.class)) {
104 recordFactory(role);
105 } else {
106 recordRole(role, role, null);
107 }
108 }
109
110 public void recordRole(Class<?> role, String type) {
111 if (role.isAnnotationPresent(factory.class)) {
112 recordFactory(role, type);
113 } else {
114 recordRole(role, role, vf.createRdfType(type));
115 }
116 }
117
118 private void recordRole(Class<?> role, AnnotatedElement elm, URI rdfType) {
119 recordExplicitRoles(role, elm, rdfType);
120 recordAliases(role, elm);
121 }
122
123 private void recordExplicitRoles(Class<?> role, AnnotatedElement elm, URI rdfType) {
124 boolean defaultType = elm.isAnnotationPresent(rdf.class);
125 boolean complement = elm.isAnnotationPresent(complementOf.class);
126 boolean intersec = elm.isAnnotationPresent(intersectionOf.class);
127 boolean one = elm.isAnnotationPresent(oneOf.class);
128 boolean annotated = defaultType;
129 annotated = annotated || complement || intersec || one;
130 URI defType = findDefaultType(role, elm);
131 boolean useBaseType = !annotated;
132 if (defType != null) {
133 roleMapper.recordRole(role, defType);
134 useBaseType = false;
135 }
136 if (rdfType != null) {
137 roleMapper.recordRole(role, rdfType);
138 useBaseType = false;
139 }
140 if (useBaseType) {
141 roleMapper.recordBaseRole(role);
142 }
143 roleMapper.recordRole(role, elm);
144 }
145
146 private URI findDefaultType(Class<?> role, AnnotatedElement elm) {
147 if (elm.isAnnotationPresent(rdf.class)) {
148 String[] values = elm.getAnnotation(rdf.class).value();
149 if (values.length > 0) {
150 return vf.createRdfType(values[0]);
151 }
152 }
153 return null;
154 }
155
156 private void recordAliases(Class<?> role, AnnotatedElement elm) {
157 if (elm.isAnnotationPresent(rdf.class)) {
158 String[] uris = elm.getAnnotation(rdf.class).value();
159 for (int i = 1; i < uris.length; i++) {
160 URI eqType = vf.createRdfType(uris[i]);
161 recordExplicitRoles(role, elm, eqType);
162 }
163 }
164 }
165 }