Source code: org/modama/framework/operations/Abstracton2InputOperation.java
1 package org.modama.framework.operations;
2
3 import org.modama.framework.entities.*;
4 import org.modama.framework.exceptions.UnexpectedErrorException;
5 import org.modama.framework.world.World;
6
7 import java.awt.image.RenderedImage;
8 import java.util.Iterator;
9 import java.util.List;
10
11 /**
12 * a baseclass for operation on exactly two inputs, it asumes that the order of the 2 inputs doesnt matter
13 * depending on the types of the input the output changes slightly:
14 *
15 * Ne -> NumberEntity
16 * Ie -> ImageEntity
17 * Nl -> NumberList
18 * Il -> ImageList
19 *
20 * - the input order doesnt matter, so their are 14 possiblities)
21 * Input Output
22 * Ne an Entity with the same data
23 * Ie an Entity with the same data
24 * Il a new Ie
25 * output = calc( ... calc( calc( calc( Il[0], Il[1] ), Il[2] ), Il[3] ) ... )
26 * Nl a new Ne
27 * output = calc( ... calc( calc( calc( Nl[0], Nl[1] ), Nl[2] ), Nl[3] ) ... )
28 * Ne Ne a new Ne
29 * output = calc( Ne, Ne )
30 * Ne Nl a new Nl with the size of the input Nl, every number of the List is combined with the Ne
31 * output[i] = calc( Ne, Nl[i] )
32 * Nl Nl a new Nl with the size of the bigger input list
33 * if( i inrange of both Nl ) output[i] = calc( Nl[i], Nl[i] )
34 * else output[i] = Nl[i] // the bigger Nl
35 * Ie Ie a new Ie
36 * output = calc( Ie, Ie )
37 * Ie Il a new Il with the size of the input Il
38 * output[i] = cals( Ie, Il[i] )
39 * Il Il a new Il with the size of the bigger inputlist
40 * if( i inrange of both Il ) output[i] = calc( Il[i], Il[i] )
41 * else output[i] = Il[i] // the bigger Il
42 * Ne Ie a new Ie
43 * output = calc( Ne, Ie )
44 * Ne Il a new Il, same size as inputlist
45 * output[i] = calc( Ne, Il[i] )
46 * Nl Ie not defined
47 * Nl Il a new Il, same size as the input Il
48 * if( Nl[i] defined )
49 * output[i] = calc( Nl[i], Il[i] )
50 * else
51 * output[i] = Il[i]
52 *
53 */
54 public abstract class Abstracton2InputOperation extends AbstractOperation {
55 /**
56 * Image Image calculator
57 */
58 IeIeCalculator iiCalculator;
59 /**
60 * Number Number calculator
61 */
62 NeNeCalculator nnCalculator;
63 /**
64 * Number Image calculator
65 */
66 NeIeCalculator niCalculator;
67
68 /*
69 protected void fillAvailabeCalculatorsArray() {
70 super.fillAvailabeCalculatorsArray();
71 // their should be a subclass of ImageCalculator
72 for (int i = 0; i < availabeCalculators.length; i++) {
73 Calculator availabeCalculator = availabeCalculators[i];
74 if( IeIeCalculator.class.isAssignableFrom( availabeCalculator.getClass() ) ) iiCalculator = (IeIeCalculator) availabeCalculator;
75 if( NeNeCalculator.class.isAssignableFrom( availabeCalculator.getClass() ) ) nnCalculator = (NeNeCalculator) availabeCalculator;
76 if( NeIeCalculator.class.isAssignableFrom( availabeCalculator.getClass() ) ) niCalculator = (NeIeCalculator) availabeCalculator;
77 }
78 }
79 */
80
81 /**
82 * accepts a maximum of 2 inputs, the only combination not allowed is NumberList ImageEntity
83 * @param entity
84 * @return
85 */
86 public boolean accept(AbstractEntity entity) {
87 // always accept the first input
88 if( input.size() == 0 ) return true;
89 // for the second we have to test
90 if( input.size() == 1 ) {
91 if( input.get(0) instanceof NumberList && entity instanceof ImageEntity ||
92 input.get(0) instanceof ImageEntity && entity instanceof NumberList ) return false;
93 return true;
94 }
95 return false;
96 }
97
98 /**
99 * helper to get the object of given type from the input
100 * @param type
101 * @return
102 */
103 protected Object getObjectFromInput( Class type ){
104 if( input.get(0).getClass().equals( type ) ) return input.get(0);
105 if( input.get(1).getClass().equals( type ) ) return input.get(1);
106 // this point should never be reached, because this helper is called in the calculators which are only active
107 // if they have valid input
108 throw new UnexpectedErrorException();
109 }
110
111 /**
112 * Calculator for a single image or number as input, does nothing
113 */
114 public class SingleInputCalculator implements Calculator {
115 public AbstractEntity calculate() {
116 // set data of output
117 output.setData( ((AbstractEntity)input.get(0)).getData() );
118 return output;
119 }
120
121 public boolean isValidInput() {
122 if( input.size() == 1 && (input.get(0) instanceof ImageEntity || input.get(0) instanceof NumberEntity) ) return true;
123 return false;
124 }
125
126 public Class getOutputClass() {
127 return input.get(0).getClass();
128 }
129 }
130
131 /**
132 * calculator for a single imagelist
133 */
134 public class SingleImageListCalculator implements Calculator {
135 public AbstractEntity calculate() {
136 ImageList entity = (ImageList) input.get(0);
137 // get iterator
138 Iterator it = entity.getImages().iterator();
139 // start with the first image
140 RenderedImage lastresult = ((ImageEntity)it.next()).getImage();
141 // combine all the images to one
142 while( it.hasNext() ){
143 lastresult = iiCalculator.calculate( lastresult, ((ImageEntity)it.next()).getImage() );
144 }
145 // set output
146 output.setData( lastresult );
147 return output;
148 }
149
150 public boolean isValidInput() {
151 if( input.size() == 1 && input.get(0) instanceof ImageList ) return true;
152 return false;
153 }
154
155 public Class getOutputClass() {
156 return ImageEntity.class;
157 }
158 }
159
160 /**
161 * calculator for a single numberlist
162 */
163 public class SingleNumberListCalculator implements Calculator {
164 public AbstractEntity calculate() {
165 double[] data = ((NumberList) input.get(0)).getNumbers();
166 // start with the first number
167 double lastresult = data[0];
168 // combine all the numbers to one
169 for( int i = 1; i < data.length; i++ ){
170 lastresult = nnCalculator.calculate( lastresult, data[i] );
171 }
172 // set output
173 output.setData( new Double(lastresult) );
174 return output;
175 }
176
177 public boolean isValidInput() {
178 if( input.size() == 1 && input.get(0) instanceof NumberList ) return true;
179 return false;
180 }
181
182 public Class getOutputClass() {
183 return NumberEntity.class;
184 }
185 }
186
187 /**
188 * calculator for 2 numbers
189 */
190 public abstract class NeNeCalculator implements Calculator {
191 public AbstractEntity calculate() {
192 // we dont have to make tests, all the inputs and variables should be exactly as needed
193 double data1 = ((NumberEntity)input.get(0)).getNumber().doubleValue();
194 double data2 = ((NumberEntity)input.get(1)).getNumber().doubleValue();
195 // set data of output
196 output.setData( new Double(calculate(data1,data2)) );
197 return output;
198 }
199
200 public abstract double calculate( double data1, double data2 );
201
202 public boolean isValidInput() {
203 if( input.size() == 2 && input.get(0) instanceof NumberEntity && input.get(1) instanceof NumberEntity ) return true;
204 return false;
205 }
206
207 public Class getOutputClass() {
208 return NumberEntity.class;
209 }
210 }
211
212 /**
213 * calculator for 2 images
214 */
215 public abstract class IeIeCalculator implements Calculator {
216 public AbstractEntity calculate() {
217 // we dont have to make tests, all the inputs and variables should be exactly as needed
218 RenderedImage data1 = ((ImageEntity)input.get(0)).getImage();
219 RenderedImage data2 = ((ImageEntity)input.get(1)).getImage();
220 // set data of output
221 output.setData( calculate(data1,data2) );
222 return output;
223 }
224
225 public abstract RenderedImage calculate( RenderedImage data1, RenderedImage data2 );
226
227 public boolean isValidInput() {
228 if( input.size() == 2 && input.get(0) instanceof ImageEntity && input.get(1) instanceof ImageEntity ) return true;
229 return false;
230 }
231
232 public Class getOutputClass() {
233 return ImageEntity.class;
234 }
235 }
236
237 /**
238 * calculator for 1 image and 1 number
239 */
240 public abstract class NeIeCalculator implements Calculator {
241 public AbstractEntity calculate() {
242 // we dont have to make tests, all the inputs and variables should be exactly as needed
243 double data1;
244 RenderedImage data2;
245 // fill the data, we have to test which one is the number and which one the image
246 data1 = ((NumberEntity)getObjectFromInput( NumberEntity.class )).getNumber().doubleValue();
247 data2 = ((ImageEntity)getObjectFromInput( ImageEntity.class )).getImage();
248 // set data of output
249 output.setData( calculate( data1, data2 ) );
250 return output;
251 }
252
253 public abstract RenderedImage calculate( double data1, RenderedImage data2 );
254
255 public boolean isValidInput() {
256 if( input.size() == 2 &&
257 ((input.get(0) instanceof ImageEntity && input.get(1) instanceof NumberEntity) ||
258 (input.get(0) instanceof NumberEntity && input.get(1) instanceof ImageEntity)) ) return true;
259 return false;
260 }
261
262 public Class getOutputClass() {
263 return ImageEntity.class;
264 }
265 }
266
267 /**
268 * calculator for a number and a numberlist
269 */
270 public class NeNlCalculator implements Calculator {
271 public AbstractEntity calculate() {
272 // we dont have to make tests, all the inputs and variables should be exactly as needed
273 double data1;
274 double[] data2;
275 // fill the data, we have to test which one is the number and which one the image
276 data1 = ((NumberEntity)getObjectFromInput( NumberEntity.class )).getNumber().doubleValue();
277 data2 = ((NumberList)getObjectFromInput( NumberList.class )).getNumbers();
278 // create data for output
279 double[] data3 = new double[data2.length];
280 for (int i = 0; i < data2.length; i++) {
281 data3[i] = nnCalculator.calculate( data1, data2[i] );
282 }
283 // set data to output
284 output.setData( data3 );
285 return output;
286 }
287
288 public boolean isValidInput() {
289 if( input.size() == 2 &&
290 ((input.get(0) instanceof NumberList && input.get(1) instanceof NumberEntity) ||
291 (input.get(0) instanceof NumberEntity && input.get(1) instanceof NumberList)) ) return true;
292 return false;
293 }
294
295 public Class getOutputClass() {
296 return NumberList.class;
297 }
298 }
299
300 /**
301 * calculator for 2 numberlists
302 */
303 public class NlNlCalculator implements Calculator {
304 public AbstractEntity calculate() {
305 // we dont have to make tests, all the inputs and variables should be exactly as needed
306 double[] data1;
307 double[] data2;
308 // get data
309 data1 = ((NumberList)input.get(0)).getNumbers();
310 data2 = ((NumberList)input.get(1)).getNumbers();
311 // set the bigger list to data1
312 if( data1.length < data2.length ) { data1 = data2; data2 = ((NumberList)input.get(0)).getNumbers(); }
313 // create data for output, size of greater inputlist
314 double[] data3 = new double[ data1.length ];
315 // size of smaller inputlist
316 int i = 0;
317 // calc for the values where we have 2 values
318 for (; i < data2.length; i++) data3[i] = nnCalculator.calculate( data1[i], data2[i] );
319 // take the values where have only one
320 for (; i < data3.length; i++) data3[i] = data1[i];
321 // set data to output
322 output.setData( data3 );
323 return output;
324 }
325
326 public boolean isValidInput() {
327 if( input.size() == 2 && input.get(0) instanceof NumberList && input.get(1) instanceof NumberList ) return true;
328 return false;
329 }
330
331 public Class getOutputClass() {
332 return NumberList.class;
333 }
334 }
335
336 /**
337 * calculator for an image and an imagelist
338 */
339 public class IeIlCalculator implements Calculator
340 {
341 public AbstractEntity calculate()
342 {
343 // we dont have to make tests, all the inputs and variables should be exactly as needed
344 RenderedImage data1;
345 List data2;
346 // get the data
347 data1 = ((ImageEntity)getObjectFromInput( ImageEntity.class )).getImage();
348 data2 = ((ImageList)getObjectFromInput( ImageList.class )).getImages();
349 // clear outputdata
350 ((ImageList)output).clear();
351 // iterator through the imagelist
352 Iterator it = data2.iterator();
353 World.getInstance().setAcceptObjects( false );
354 while( it.hasNext() )
355 {
356 // create a new imageentity
357 ImageEntity entity = new ImageEntity();
358 // do the calculation, set the data
359 entity.setImage( iiCalculator.calculate( data1, ((ImageEntity)it.next()).getImage() ) );
360 // add entity to the outputlist
361 ((ImageList)output).add( entity );
362 }
363 World.getInstance().setAcceptObjects( true );
364 return output;
365 }
366
367 public boolean isValidInput()
368 {
369 if( input.size() == 2 &&
370 ((input.get(0) instanceof ImageList && input.get(1) instanceof ImageEntity) ||
371 (input.get(0) instanceof ImageEntity && input.get(1) instanceof ImageList)) ) return true;
372 return false;
373 }
374
375 public Class getOutputClass()
376 {
377 return ImageList.class;
378 }
379 }
380
381 /**
382 * calculator for a number and an imagelist
383 */
384 public class NeIlCalculator implements Calculator {
385 public AbstractEntity calculate() {
386 // we dont have to make tests, all the inputs and variables should be exactly as needed
387 double data1;
388 List data2;
389 // get the data
390 data1 = ((NumberEntity)getObjectFromInput( NumberEntity.class )).getNumber().doubleValue();
391 data2 = ((ImageList)getObjectFromInput( ImageList.class )).getImages();
392 // clear outputdata
393 ((ImageList)output).clear();
394 // iterator through the imagelist
395 Iterator it = data2.iterator();
396 World.getInstance().setAcceptObjects( false );
397 while( it.hasNext() ){
398 // create a new imageentity
399 ImageEntity entity = new ImageEntity();
400 // do the calculation, set the data
401 entity.setImage( niCalculator.calculate( data1, ((ImageEntity)it.next()).getImage() ) );
402 // add entity to the outputlist
403 ((ImageList)output).add( entity );
404 }
405 World.getInstance().setAcceptObjects( true );
406 return output;
407 }
408
409 public boolean isValidInput() {
410 if( input.size() == 2 &&
411 ((input.get(0) instanceof ImageList && input.get(1) instanceof NumberEntity) ||
412 (input.get(0) instanceof NumberEntity && input.get(1) instanceof ImageList)) ) return true;
413 return false;
414 }
415
416 public Class getOutputClass() {
417 return ImageList.class;
418 }
419 }
420
421 /**
422 * calculator for a numberlist and an imagelist
423 */
424 public class NlIlCalculator implements Calculator {
425 public AbstractEntity calculate() {
426 // we dont have to make tests, all the inputs and variables should be exactly as needed
427 double[] data1;
428 List data2;
429 // get the data
430 data1 = ((NumberList)getObjectFromInput( NumberList.class )).getNumbers();
431 data2 = ((ImageList)getObjectFromInput( ImageList.class )).getImages();
432 // clear outputdata
433 ((ImageList)output).clear();
434 // iterator through the imagelist
435 Iterator it = data2.iterator();
436 int i = 0;
437 World.getInstance().setAcceptObjects( false );
438 while( it.hasNext() ){
439 // create a new imageentity
440 ImageEntity entity = new ImageEntity();
441 // do the calculation, set the data
442 entity.setImage( niCalculator.calculate( data1[i], ((ImageEntity)it.next()).getImage() ) );
443 // add entity to the outputlist
444 ((ImageList)output).add( entity );
445 // if we have a next number value in the numberlist, inc i
446 if( i < data1.length - 1 ) i++;
447 }
448 World.getInstance().setAcceptObjects( true );
449 return output;
450 }
451
452 public boolean isValidInput() {
453 if( input.size() == 2 &&
454 ((input.get(0) instanceof ImageList && input.get(1) instanceof NumberList) ||
455 (input.get(0) instanceof NumberList && input.get(1) instanceof ImageList)) ) return true;
456 return false;
457 }
458
459 public Class getOutputClass() {
460 return ImageList.class;
461 }
462 }
463
464 /**
465 * calculator for 2 imagelists
466 */
467 public class IlIlCalculator implements Calculator {
468 public AbstractEntity calculate() {
469 // we dont have to make tests, all the inputs and variables should be exactly as needed
470 List data1;
471 List data2;
472 // get the data
473 data1 = ((ImageList)input.get(0)).getImages();
474 data2 = ((ImageList)input.get(1)).getImages();
475 // set the bigger list to data1
476 if( data1.size() < data2.size() ) { data1 = data2; data2 = ((ImageList)input.get(0)).getImages(); }
477 // clear outputdata
478 ((ImageList)output).clear();
479 // iterator through the imagelists
480 Iterator it1 = data1.iterator();
481 Iterator it2 = data2.iterator();
482 // the smalers list iterator is the condition
483 World.getInstance().setAcceptObjects( false );
484 while( it2.hasNext() ){
485 // create a new imageentity
486 ImageEntity entity = new ImageEntity();
487 // do the calculation, set the data
488 entity.setImage( iiCalculator.calculate( ((ImageEntity)it1.next()).getImage(), ((ImageEntity)it2.next()).getImage() ) );
489 // add entity to the outputlist
490 ((ImageList)output).add( entity );
491 }
492 World.getInstance().setAcceptObjects( true );
493 // copy the rest
494 while( it1.hasNext() ){
495 ((ImageList)output).add( (AbstractEntity) it1.next() );
496 }
497 return output;
498 }
499
500 public boolean isValidInput() {
501 if( input.size() == 2 && input.get(0) instanceof ImageList && input.get(1) instanceof ImageList ) return true;
502 return false;
503 }
504
505 public Class getOutputClass() {
506 return ImageList.class;
507 }
508 }
509
510 public boolean canExecute()
511 {
512 return calculator != null;//input.size()==2;
513 }
514 }