001package org.biopax.paxtools.impl; 002 003import org.biopax.paxtools.controller.*; 004import org.biopax.paxtools.model.BioPAXElement; 005import org.biopax.paxtools.model.BioPAXFactory; 006import org.biopax.paxtools.model.BioPAXLevel; 007import org.biopax.paxtools.model.Model; 008import org.biopax.paxtools.util.IllegalBioPAXArgumentException; 009 010import java.lang.reflect.Array; 011import java.lang.reflect.Field; 012import java.util.*; 013 014/** 015 * This factory returns decorated objects for testing. 016 */ 017public class MockFactory extends BioPAXFactory 018{ 019// ------------------------------ FIELDS ------------------------------ 020 021 022 private static final List<String> strings = Arrays.asList(" ", "alpha", "beta", "gamma"); 023 024 private static final List<Float> floats = Arrays.asList(Float.MAX_VALUE, 1.0F, 0.0F, Float.MIN_VALUE); 025 026 private static final List<Double> doubles = Arrays.asList(Double.MAX_VALUE, 1.0, 0.0, Double.MIN_VALUE); 027 028 private static final List<Integer> ints = Arrays.asList(Integer.MAX_VALUE, 1, 0, Integer.MIN_VALUE + 1); 029 030 private static final List<Boolean> booleans = Arrays.asList(Boolean.TRUE, Boolean.FALSE); 031 032 private static final String base = "mock://id/"; 033 034 private int id = 0; 035 036 037 private EditorMap map; 038 039 private BioPAXLevel level; 040 041// --------------------------- CONSTRUCTORS --------------------------- 042 043 public MockFactory(BioPAXLevel level) 044 { 045 this.level = level; 046 this.map = SimpleEditorMap.get(level); 047 } 048 049 @Override 050 public <T extends BioPAXElement> T create(Class<T> aClass, String uri) 051 { 052 T t = this.getLevel().getDefaultFactory().create(aClass, uri); 053 populateMock(t); 054 return t; 055 } 056 057 @Override 058 public BioPAXElement create(String localName, String uri) 059 { 060 BioPAXElement bpe = this.getLevel().getDefaultFactory().create(localName, uri); 061 populateMock(bpe); 062 return bpe; 063 } 064 065 private void populateMock(BioPAXElement bpe) 066 { 067 Set<PropertyEditor> propertyEditors = map.getEditorsOf(bpe); 068 069 for (PropertyEditor propertyEditor : propertyEditors) 070 { 071 boolean multiple = propertyEditor.isMultipleCardinality(); 072 Object value = null; 073 if (propertyEditor instanceof StringPropertyEditor) 074 { 075 value = getStrings(bpe, multiple); 076 } else 077 { 078 Class range = propertyEditor.getRange(); 079 if (propertyEditor instanceof PrimitivePropertyEditor) 080 { 081 if (range == float.class) 082 { 083 value = multiple ? floats : floats.get(1); 084 } else if (range == double.class) 085 { 086 value = multiple ? doubles : doubles.get(1); 087 } else if (range == int.class) 088 { 089 value = multiple ? ints : ints.get(1); 090 } else if (range == Boolean.class) 091 { 092 value = multiple ? booleans : booleans.get(1); 093 } 094 } else if (propertyEditor instanceof EnumeratedPropertyEditor) 095 { 096 Field[] fields = range.getFields(); 097 if (multiple) 098 { 099 value = new HashSet(); 100 } 101 for (Field field : fields) 102 { 103 if (field.isEnumConstant()) 104 { 105 try 106 { 107 if (multiple) 108 { 109 ((Set) value).add(field.get(bpe)); 110 } else 111 { 112 value = field.get(bpe); 113 break; 114 } 115 } 116 catch (IllegalAccessException e) 117 { 118 throw new IllegalBioPAXArgumentException(); 119 } 120 } 121 } 122 } else 123 { 124// if (!Entity.class.isAssignableFrom(range)) 125// { 126// if (multiple) 127// { 128// value = createRestrictedMock((ObjectPropertyEditor) propertyEditor, bpe, 3); 129// } else 130// { 131// value = createRestrictedMock((ObjectPropertyEditor) propertyEditor, bpe, 132// 1).iterator().next(); 133// } 134// } 135 } 136 } 137 if (value != null) 138 { 139 if (multiple) 140 { 141 Collection values = ((Collection) value); 142 if (!values.isEmpty()) 143 { 144 Integer max = propertyEditor.getMaxCardinality(bpe.getModelInterface()); 145 values = upToMax(values, max); 146 147 for (Object o : values) 148 { 149 propertyEditor.setValueToBean(o, bpe); 150 } 151 } else 152 { 153 propertyEditor.setValueToBean(value, bpe); 154 } 155 } 156 } 157 } 158 } 159 160 private Object getStrings(BioPAXElement bpe, boolean multiple) 161 { 162 if (multiple) 163 { 164 ArrayList<String> list = new ArrayList<String>(4); 165 for (String str : strings) 166 { 167 list.add(bpe.getRDFId() + str); 168 } 169 return list; 170 } else return bpe.getRDFId() + strings.get(3); 171 } 172 173 private HashSet<BioPAXElement> createRestrictedMock(ObjectPropertyEditor propertyEditor, BioPAXElement bpe, int k) 174 { 175 HashSet<BioPAXElement> hashSet = new HashSet<BioPAXElement>(); 176 177 178 Set<Class<? extends BioPAXElement>> rRanges = propertyEditor.getRestrictedRangesFor(bpe.getModelInterface()); 179 for (Class<? extends BioPAXElement> rRange : rRanges) 180 { 181 hashSet.add(createMock(rRange, bpe.getModelInterface())); 182 } 183 return hashSet; 184 } 185 186 private BioPAXElement createMock(Class<? extends BioPAXElement> toCreate, Class domain) 187 { 188 assert domain != null; 189 Class<? extends BioPAXElement> actual; 190 actual = findConcreteMockClass(toCreate, domain); 191 if (actual != null) 192 { 193 return map.getLevel().getDefaultFactory().create(actual, base + id++); 194 } else return null; 195 196 } 197 198 private Class<? extends BioPAXElement> findConcreteMockClass(Class<? extends BioPAXElement> toCreate, Class domain) 199 { 200 Class<? extends BioPAXElement> actual = null; 201 if (map.getLevel().getDefaultFactory().canInstantiate(toCreate) && !toCreate.isAssignableFrom(domain)) 202 { 203 actual = toCreate; 204 } else 205 { 206 Set<? extends Class<? extends BioPAXElement>> knownSubClassesOf = map.getKnownSubClassesOf(toCreate); 207 for (Class<? extends BioPAXElement> subclass : knownSubClassesOf) 208 { 209 if (!subclass.isAssignableFrom(domain) && subclass != toCreate && 210 subclass.getPackage().getName().startsWith("org.biopax.paxtools.model")) 211 { 212 actual = findConcreteMockClass(subclass, domain); 213 break; 214 } 215 } 216 } 217 return actual; 218 } 219 220 private Collection upToMax(Collection values, Integer max) 221 { 222 int size = values.size(); 223 if (max != null && max < size) 224 { 225 values = new ArrayList(values); 226 for (int i = size - 1; i == max; i--) 227 { 228 ((List) values).remove(i); 229 } 230 assert values.size() == max; 231 } 232 return values; 233 } 234 235 236 public BioPAXLevel getLevel() 237 { 238 return this.level; 239 } 240 241 @Override 242 public String mapClassName(Class<? extends BioPAXElement> aClass) { 243 return this.getLevel().getDefaultFactory().mapClassName(aClass); 244 } 245 246 247 public <T extends BioPAXElement> T[] create(Model model, Class<T> biopaxClass, int number, String pre) 248 { 249 T[] result = (T[]) Array.newInstance(biopaxClass, number); 250 251 for (int i = 0; i < number; i++) 252 { 253 result[i] = model.addNew(biopaxClass, biopaxClass.getSimpleName() + pre + i); 254 } 255 return result; 256 } 257 258 public <T extends BioPAXElement> T[] create(Model model, Class<T> biopaxClass, int number) 259 { 260 return this.create(model,biopaxClass, number, ""); 261 } 262 263 public void bindInPairs(ObjectPropertyEditor editor, BioPAXElement... pairs) 264 { 265 for (int i = 0; i < pairs.length; i++) 266 { 267 BioPAXElement bean = pairs[i++]; 268 BioPAXElement value = pairs[i]; 269 editor.setValueToBean(value, bean); 270 } 271 } 272 273 public void bindArrays(ObjectPropertyEditor editor, BioPAXElement[] beans, BioPAXElement[] values) 274 { 275 for (int i = 0; i < beans.length; i++) 276 { 277 BioPAXElement bean = beans[i]; 278 BioPAXElement value = values[i]; 279 editor.setValueToBean(value, bean); 280 } 281 } 282 283 public void bindInPairs(String editor, BioPAXElement... pairs) 284 { 285 this.bindInPairs(this.editor(editor, pairs[0].getModelInterface()),pairs); 286 } 287 288 public void bindArrays(String editor, BioPAXElement[] beans, BioPAXElement[] values) 289 { 290 this.bindArrays(this.editor(editor, (Class<? extends BioPAXElement>) beans.getClass().getComponentType()), 291 beans, values); 292 } 293 294 public ObjectPropertyEditor editor(String property, Class<? extends BioPAXElement> clazz) 295 { 296 return (ObjectPropertyEditor) map.getEditorForProperty(property, clazz); 297 } 298 299}