Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.core / src / main / java / es / unex / sextante / core / GeoAlgorithm.java @ 315

History | View | Annotate | Download (89.2 KB)

1
package es.unex.sextante.core;
2

    
3
import java.text.DateFormat;
4
import java.util.ArrayList;
5
import java.util.Date;
6
import java.util.HashMap;
7

    
8
import es.unex.sextante.additionalInfo.AdditionalInfoDataObject;
9
import es.unex.sextante.additionalInfo.AdditionalInfoFixedTable;
10
import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput;
11
import es.unex.sextante.additionalInfo.AdditionalInfoTableField;
12
import es.unex.sextante.dataObjects.I3DRasterLayer;
13
import es.unex.sextante.dataObjects.IDataObject;
14
import es.unex.sextante.dataObjects.ILayer;
15
import es.unex.sextante.dataObjects.IRasterLayer;
16
import es.unex.sextante.dataObjects.ITable;
17
import es.unex.sextante.dataObjects.IVectorLayer;
18
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
19
import es.unex.sextante.exceptions.NullParameterAdditionalInfoException;
20
import es.unex.sextante.exceptions.NullParameterValueException;
21
import es.unex.sextante.exceptions.UnsupportedOutputChannelException;
22
import es.unex.sextante.exceptions.WrongAnalysisExtentException;
23
import es.unex.sextante.exceptions.WrongParameterIDException;
24
import es.unex.sextante.exceptions.WrongParameterTypeException;
25
import es.unex.sextante.outputs.FileOutputChannel;
26
import es.unex.sextante.outputs.IOutputChannel;
27
import es.unex.sextante.outputs.Output;
28
import es.unex.sextante.outputs.Output3DRasterLayer;
29
import es.unex.sextante.outputs.OutputChart;
30
import es.unex.sextante.outputs.OutputImage;
31
import es.unex.sextante.outputs.OutputNumericalValue;
32
import es.unex.sextante.outputs.OutputRasterLayer;
33
import es.unex.sextante.outputs.OutputTable;
34
import es.unex.sextante.outputs.OutputText;
35
import es.unex.sextante.outputs.OutputVectorLayer;
36
import es.unex.sextante.parameters.Parameter;
37
import es.unex.sextante.parameters.ParameterDataObject;
38
import es.unex.sextante.parameters.ParameterFixedTable;
39
import es.unex.sextante.parameters.ParameterMultipleInput;
40
import es.unex.sextante.parameters.ParameterTableField;
41
import es.unex.sextante.parameters.RasterLayerAndBand;
42
import es.unex.sextante.shapesTools.ShapesTools;
43
import java.io.File;
44

    
45
import org.jfree.chart.ChartPanel;
46

    
47
import org.gvsig.fmap.geom.Geometry;
48

    
49

    
50
/**
51
 * A class defining a geo-algorithm
52
 *
53
 * @author Victor Olaya volaya@unex.es
54
 *
55
 */
56
public abstract class GeoAlgorithm {
57

    
58
   /**
59
    * The set of input parameters and their values
60
    */
61
   protected ParametersSet         m_Parameters;
62

    
63
   /**
64
    * The set of output objects. Results will be stored in this set once the execution is finished
65
    */
66
   protected OutputObjectsSet      m_OutputObjects;
67

    
68
   /**
69
    * A task to track progress of the algorithm
70
    */
71
   protected ITaskMonitor          m_Task;
72

    
73
   /**
74
    * The extent will be used to analyze layers and create create new output layers
75
    */
76
   protected AnalysisExtent        m_AnalysisExtent;
77

    
78
   /**
79
    * True if the algorithm generates output layers and its extent can be defined by the user
80
    */
81
   protected boolean               m_bUserCanDefineAnalysisExtent = true;
82

    
83
   /**
84
    * true if the number of steps needed to execute the algorithm can be known in advance
85
    */
86
   protected boolean               m_bIsDeterminatedProcess       = true;
87

    
88
   /**
89
    * The name of the algorithm
90
    */
91
   private String                  m_sName;
92

    
93
   /**
94
    * The name of the group this algorithm belongs to
95
    */
96
   private String                  m_sGroup;
97

    
98
   /**
99
    * A description string for misc. use
100
    */
101
   private String                  m_sDescription                                        = null;
102

    
103

    
104
   /**
105
    * Color values useful for e.g. coloring algorithm nodes in the modeler
106
    */
107
   private int                  i_R                                                                        = Sextante.i_R_Algorithm;
108
   private int                  i_G                                                                        = Sextante.i_G_Algorithm;
109
   private int                  i_B                                                                        = Sextante.i_B_Algorithm;
110
   private int                  i_Alpha                                                                = Sextante.i_Alpha_Algorithm;
111

    
112
   /**
113
    * Process metadata
114
    */
115
   private HashMap                 m_ProcessMetadata;
116

    
117
   /**
118
    * Used to indicate if the extent has been set by the user or automatically by the algorithm
119
    */
120
   protected boolean               m_bIsAutoExtent;
121

    
122
   /**
123
    * The CRS to use if the algorithm generates new layers
124
    */
125
   protected Object                m_CRS;
126

    
127
   private long                    m_lInitTime;
128
   private long                    m_lEndTime;
129

    
130
   /**
131
    * The output factory to use for generating new data objects from this algorithm
132
    */
133
   protected OutputFactory         m_OutputFactory;
134

    
135
   /**
136
    * Alternative names for outputs
137
    */
138
   private HashMap<String, String> m_OutputMap;
139
   
140
   /**
141
    * 
142
    */
143
   protected boolean m_RecalculateForCell = true; 
144

    
145
   public GeoAlgorithm() {
146

    
147
      m_Parameters = new ParametersSet();
148
      m_OutputObjects = new OutputObjectsSet();
149

    
150
      defineCharacteristics();
151

    
152
   }
153

    
154
   public boolean getRecalculateForCell() {
155
       return m_RecalculateForCell;
156
   } 
157
   public void setRecalculateForCell(boolean recalculate) {
158
       m_RecalculateForCell = recalculate;
159
   }
160
   /**
161
    * This method should be overridden and used to specify the parameters needed by the GeoAlgorithm, using the corresponding
162
    * methods of the ParametersSet object.
163
    *
164
    * Also, output objects must be added, so SEXTANTE knows in advance which outputs will be generated by the algorithm. See the
165
    * addOutputXXXX family of methods ({@link #addOutputRasterLayer}, {@link #addOutputVectorLayer}, etc.)
166
    *
167
    */
168
   public abstract void defineCharacteristics();
169

    
170

    
171
   /**
172
    * This method should be used to execute the algorithm once the parameters have been assigned.
173
    *
174
    * @param task
175
    *                a ITaskMonitor to track the progress of the execution. If is null, a
176
    * @see {@link SilentTaskMonitor} will be used.
177
    * @param outputFactory
178
    *                The output factory to use to generate new data objects
179
    * @return true if the algorithm was correctly executed. False if it was canceled
180
    * @throws GeoAlgorithmExecutionException
181
    */
182
   public boolean execute(final ITaskMonitor task,
183
                          final OutputFactory outputFactory) throws GeoAlgorithmExecutionException {
184
      return execute(task, outputFactory, null);
185
   }
186

    
187

    
188
   /**
189
    * This method should be used to execute the algorithm once the parameters have been assigned.
190
    *
191
    * @param task
192
    *                a ITaskMonitor to track the progress of the execution. If is null, a
193
    * @see {@link SilentTaskMonitor} will be used.
194
    * @param outputFactory
195
    *                The output factory to use to generate new data objects
196
    * @param outputMap
197
    *                Maps {@link IDataObject} algorithm output names to the desired output name. At IDataObject output creation,
198
    *                {@link OutputFactory} implementations will receive the values in this map as names.
199
    * @return true if the algorithm was correctly executed. False if it was canceled
200
    * @throws GeoAlgorithmExecutionException
201
    */
202
   public boolean execute(final ITaskMonitor task,
203
                          final OutputFactory outputFactory,
204
                          final HashMap<String, String> outputMap) throws GeoAlgorithmExecutionException {
205

    
206
      final StringBuffer sb = new StringBuffer();
207

    
208
      if (task == null) {
209
         m_Task = new SilentTaskMonitor();
210
      }
211
      else {
212
         m_Task = task;
213
         m_Task.setProgressText("");
214
      }
215
      m_OutputFactory = outputFactory;
216

    
217
      initInputDataObjects();
218

    
219
      if (!adjustOutputExtent()) {
220
         throw new WrongAnalysisExtentException();
221
      }
222

    
223
      final DateFormat formatter = DateFormat.getDateTimeInstance();
224

    
225
      final String[] cmd = this.getAlgorithmAsCommandLineSentences();
226

    
227
      if (cmd != null) {
228
         for (final String element : cmd) {
229
            sb.append("Executing command: " + element + "\n");
230
         }
231
      }
232

    
233
      m_OutputMap = outputMap;
234

    
235
      m_lInitTime = System.currentTimeMillis();
236
      sb.append("Starting algorithm execution...:" + formatter.format(new Date(m_lInitTime)) + "\n");
237

    
238
      final boolean bReturn = processAlgorithm();
239

    
240
      m_lEndTime = System.currentTimeMillis();
241
      sb.append("Finished algorithm execution:" + formatter.format(new Date(m_lEndTime)) + "\n");
242
      sb.append("Execution time (millisecs):" + Long.toString(m_lEndTime - m_lInitTime) + "\n");
243

    
244
      Sextante.addInfoToLog(sb.toString());
245

    
246
      closeInputDataObjects();
247
      createProcessMetadata();
248

    
249
      if (bReturn) {
250
         postProcessOutputDataObjects();
251
      }
252
      else {
253
         sb.append("Algorithm was canceled!!\n");
254
      }
255

    
256
      return bReturn;
257

    
258
   }
259

    
260

    
261
   /**
262
    * Creates metadata for the process once it has been executed
263
    */
264
   private void createProcessMetadata() {
265

    
266
      m_ProcessMetadata = new HashMap();
267

    
268
      m_ProcessMetadata.put("PROCESS_DATE", new Date(m_lInitTime));
269
      m_ProcessMetadata.put("PROCESS_DURATION", new Long(m_lEndTime - m_lInitTime));
270

    
271
      //TODO: add more metadata
272

    
273
   }
274

    
275

    
276
   /**
277
    * Returns a map with metadata entries. It will return an empty map if the process has not been executed yet.
278
    *
279
    * @return the metadata of the process.
280
    */
281
   public HashMap getProcessMetadata() {
282

    
283
      return m_ProcessMetadata;
284

    
285
   }
286

    
287

    
288
   /**
289
    * post-processes all output objects
290
    *
291
    */
292
   private void postProcessOutputDataObjects() throws GeoAlgorithmExecutionException {
293

    
294
      try {
295
         for (int i = 0; i < m_OutputObjects.getOutputObjectsCount(); i++) {
296
            final Output out = m_OutputObjects.getOutput(i);
297
            final Object obj = out.getOutputObject();
298
            if (obj instanceof IDataObject) {
299
               final IDataObject dataObject = (IDataObject) obj;
300
               dataObject.postProcess();
301
            }
302
         }
303
      }
304
      catch (final Exception e) {
305
         Sextante.addErrorToLog(e);
306
         throw new GeoAlgorithmExecutionException(e.getMessage());
307
      }
308

    
309
   }
310

    
311

    
312
   /**
313
    * Closes all input data objects when they are not needed anymore
314
    */
315
   private void closeInputDataObjects() {
316

    
317
      for (int i = 0; i < m_Parameters.getNumberOfParameters(); i++) {
318
         try {
319
            final Parameter param = m_Parameters.getParameter(i);
320
            final Object obj = param.getParameterValueAsObject();
321
            if (obj instanceof ILayer) {
322
               final ILayer layer = (ILayer) obj;
323
               layer.close();
324
            }
325
            else if (obj instanceof ITable) {
326
               final ITable table = (ITable) obj;
327
               table.close();
328
            }
329
            else if (obj instanceof ArrayList) {
330
               final ArrayList list = (ArrayList) obj;
331
               for (int j = 0; j < list.size(); j++) {
332
                  closeInputDataObject(list.get(j));
333
               }
334
            }
335
         }
336
         catch (final Exception e) {
337
            Sextante.addErrorToLog(e);
338
         }
339
      }
340

    
341
   }
342

    
343

    
344
   /**
345
    * Closes an input object
346
    *
347
    * @param obj
348
    *                the input object to close
349
    */
350
   private void closeInputDataObject(final Object obj) {
351

    
352
      if (obj instanceof ILayer) {
353
         final ILayer layer = (ILayer) obj;
354
         layer.close();
355
      }
356
      else if (obj instanceof ITable) {
357
         final ITable table = (ITable) obj;
358
         table.close();
359
      }
360
      else if (obj instanceof RasterLayerAndBand) {
361
         final RasterLayerAndBand rab = (RasterLayerAndBand) obj;
362
         final IRasterLayer layer = rab.getRasterLayer();
363
         layer.close();
364
      }
365

    
366
   }
367

    
368

    
369
   /**
370
    * Opens data objects before using them. It also sets the CRS for output layers as the CRS of the first valid input layers, or
371
    * the default one if no layer is used. (see {@link OuputFactory#getDefualtCRS}). Sextante does not perform any coordinate
372
    * transformation, and all input layers are assumed to have the same CRS, which will be the one assigned to all output layers.
373
    */
374
   private void initInputDataObjects() {
375

    
376
      for (int i = 0; i < m_Parameters.getNumberOfParameters(); i++) {
377
         final Parameter param = m_Parameters.getParameter(i);
378
         final Object obj = param.getParameterValueAsObject();
379
         initInputDataObject(obj);
380
      }
381

    
382
      if (m_CRS == null) {
383
         m_CRS = m_OutputFactory.getDefaultCRS();
384
      }
385
   }
386

    
387

    
388
   /**
389
    * Opens a single data objects before using it. It also sets the CRS for output layers if a layer is passed and the current
390
    * output CRS is not set.
391
    */
392
   private void initInputDataObject(final Object obj) {
393

    
394
      if (obj instanceof ILayer) {
395
         final ILayer layer = (ILayer) obj;
396
         layer.open();
397
         if (m_CRS == null) {
398
            m_CRS = layer.getCRS();
399
         }
400
         else {
401
            if ((layer.getCRS() == null) || !layer.getCRS().equals(m_CRS)) {
402
               Sextante.addWarningToLog("Distintos_CRS");
403
            }
404
         }
405
      }
406
      else if (obj instanceof ITable) {
407
         final ITable table = (ITable) obj;
408
         table.open();
409
      }
410
      else if (obj instanceof RasterLayerAndBand) {
411
         final RasterLayerAndBand rlab = (RasterLayerAndBand) obj;
412
         final IRasterLayer layer = rlab.getRasterLayer();
413
         layer.open();
414
         if (m_CRS == null) {
415
            m_CRS = layer.getCRS();
416
         }
417
      }
418
      else if (obj instanceof ArrayList) {
419
         final ArrayList list = (ArrayList) obj;
420
         for (int j = 0; j < list.size(); j++) {
421
            initInputDataObject(list.get(j));
422
         }
423
      }
424

    
425
   }
426

    
427

    
428
   /**
429
    * This method should implement the algorithm itself, using the values of the parameters and processing them.
430
    *
431
    * @return true if the algorithm was correctly executed. False if it was canceled.
432
    * @throws GeoAlgorithmExecutionException
433
    *                 if there were problems during algorithm execution
434
    */
435
   public abstract boolean processAlgorithm() throws GeoAlgorithmExecutionException;
436

    
437

    
438
   /**
439
    * This method sets the output extent according to input layers, in case it hasn't been set.
440
    *
441
    * To do so, it takes the minimum extent that covers all input layers, and the minimum cellsize in case there are input raster
442
    * layers.
443
    *
444
    * @return false if there are not enough layers to adjust the output extent for running this algorithm
445
    */
446
   public boolean adjustOutputExtent() {
447

    
448
      boolean bRasterLayers = false;
449
      boolean bLayers = false;
450
      boolean bOK = true;
451
      IRasterLayer rasterLayer;
452
      RasterLayerAndBand rlab;
453
      IVectorLayer vectorLayer;
454
      ArrayList layers;
455
      int i, j;
456

    
457
      if (!getUserCanDefineAnalysisExtent()) {
458
         m_bIsAutoExtent = false;
459
         return true;
460
      }
461

    
462
      if (m_bIsAutoExtent && (m_AnalysisExtent != null)) {
463
         return true;
464
      }
465

    
466
      if (m_AnalysisExtent == null) {
467
         m_bIsAutoExtent = true;
468
         for (i = 0; i < m_Parameters.getNumberOfParameters(); i++) {
469
            try {
470
               if (m_Parameters.getParameter(i).getParameterTypeName().equals("Raster Layer")) {
471
                  rasterLayer = m_Parameters.getParameterValueAsRasterLayer(m_Parameters.getParameter(i).getParameterName());
472
                  if (rasterLayer != null) {
473
                     if (!bRasterLayers) {
474
                        bLayers = true;
475
                        bRasterLayers = true;
476
                        m_AnalysisExtent = new AnalysisExtent(rasterLayer);
477
                     }
478
                     else {
479
                        if (!bRasterLayers) {
480
                           m_AnalysisExtent.setCellSize(rasterLayer.getLayerGridExtent().getCellSize());
481
                        }
482
                        m_AnalysisExtent.addExtent(rasterLayer.getLayerGridExtent());
483
                     }
484
                  }
485
               }
486
               else if (m_Parameters.getParameter(i).getParameterTypeName().equals("Vector Layer")) {
487
                  vectorLayer = m_Parameters.getParameterValueAsVectorLayer(m_Parameters.getParameter(i).getParameterName());
488
                  if (vectorLayer != null) {
489
                     if (!bLayers) {
490
                        bLayers = true;
491
                        m_AnalysisExtent = new AnalysisExtent(vectorLayer);
492
                     }
493
                     else {
494
                        m_AnalysisExtent.addExtent(vectorLayer.getFullExtent());
495
                     }
496
                  }
497
               }
498
               else if (m_Parameters.getParameter(i).getParameterTypeName().equals("Multiple Input")) {
499
                  final AdditionalInfoMultipleInput additionalInfo = (AdditionalInfoMultipleInput) m_Parameters.getParameter(i).getParameterAdditionalInfo();
500
                  if (additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_RASTER) {
501
                     layers = m_Parameters.getParameterValueAsArrayList(m_Parameters.getParameter(i).getParameterName());
502
                     for (j = 0; j < layers.size(); j++) {
503
                        rasterLayer = (IRasterLayer) layers.get(j);
504
                        if (!bLayers) {
505
                           bLayers = true;
506
                           bRasterLayers = true;
507
                           m_AnalysisExtent = new AnalysisExtent(rasterLayer);
508
                        }
509
                        else {
510
                           m_AnalysisExtent.addExtent(rasterLayer.getLayerGridExtent());
511
                        }
512
                     }
513
                  }
514
                  if (additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_BAND) {
515
                     layers = m_Parameters.getParameterValueAsArrayList(m_Parameters.getParameter(i).getParameterName());
516
                     for (j = 0; j < layers.size(); j++) {
517
                        rlab = (RasterLayerAndBand) layers.get(j);
518
                        rasterLayer = rlab.getRasterLayer();
519
                        if (!bRasterLayers) {
520
                           bLayers = true;
521
                           bRasterLayers = true;
522
                           m_AnalysisExtent = new AnalysisExtent(rasterLayer);
523
                        }
524
                        else {
525
                           m_AnalysisExtent.addExtent(rasterLayer.getLayerGridExtent());
526
                        }
527
                     }
528
                  }
529
                  if ((additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_ANY)
530
                      || (additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POINT)
531
                      || (additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_LINE)
532
                      || (additionalInfo.getDataType() == AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POLYGON)) {
533
                     layers = m_Parameters.getParameterValueAsArrayList(m_Parameters.getParameter(i).getParameterName());
534
                     for (j = 0; j < layers.size(); j++) {
535
                        vectorLayer = (IVectorLayer) layers.get(j);
536
                        if (!bLayers) {
537
                           bLayers = true;
538
                           m_AnalysisExtent = new AnalysisExtent(vectorLayer);
539
                        }
540
                        else {
541
                           m_AnalysisExtent.addExtent(vectorLayer.getFullExtent());
542
                        }
543
                     }
544
                  }
545
               }
546
            }
547
            catch (final ArrayIndexOutOfBoundsException e) {
548
               Sextante.addErrorToLog(e);
549
            }
550
            catch (final WrongParameterTypeException e) {
551
               Sextante.addErrorToLog(e);
552
            }
553
            catch (final WrongParameterIDException e) {
554
               Sextante.addErrorToLog(e);
555
            }
556
            catch (final NullParameterValueException e) {
557
               Sextante.addErrorToLog(e);
558
            }
559
            catch (final NullParameterAdditionalInfoException e) {
560
               Sextante.addErrorToLog(e);
561
            }
562
         }
563
         if (m_OutputObjects.getOutputLayersCount() != 0) {
564
            bOK = bOK && bLayers;
565
         }
566
         if (m_OutputObjects.getRasterLayersCount() != 0) {
567
            bOK = bOK && bRasterLayers;
568
         }
569
      }
570
      else {
571
         bOK = true;
572
         m_bIsAutoExtent = false;
573
      }
574

    
575
      return bOK;
576

    
577
   }
578

    
579

    
580
   /**
581
    * Returns the name of the algorithm
582
    *
583
    * @return The algorithm name. Might return different strings depending on the current SEXTANTE language
584
    */
585
   public String getName() {
586

    
587
      return m_sName;
588

    
589
   }
590

    
591

    
592
   /**
593
    * Sets the algorithm name. Use this in the defineCharacteristics() method Use
594
    *
595
    * @see {@link Sextante#getText(String)} to support internationalization
596
    * @param sName
597
    *                the name of the algorithm
598
    */
599
   public void setName(final String sName) {
600

    
601
      m_sName = sName;
602

    
603
   }
604

    
605

    
606
   /**
607
    * Returns the group this algorithm belongs to
608
    *
609
    * @return The group to which the algorithm belongs. Might return different strings depending on the current SEXTANTE language
610
    */
611
   public String getGroup() {
612

    
613
      return m_sGroup;
614

    
615
   }
616

    
617

    
618
   /**
619
    * Sets the name of the group this algorithm belongs to. Use this in the defineCharacteristics() method Use
620
    *
621
    * @see {@link Sextante#getText(String)} to support internationalization
622
    * @param sGroup
623
    *                the name of the group
624
    */
625
   public void setGroup(final String sGroup) {
626

    
627
      m_sGroup = sGroup;
628

    
629
   }
630

    
631

    
632
   /**
633
    * Returns the description string of the algorithm
634
    *
635
    * @return The description. This string is user-definable and e.g. used by the graphical modeler to label processing nodes.
636
    */
637
   public String getDescription() {
638

    
639
      return m_sDescription;
640

    
641
   }
642

    
643

    
644
   public int getColorR() {
645
           return(i_R);
646
   }
647

    
648
   public int getColorG() {
649
           return(i_G);
650
   }
651

    
652
   public int getColorB() {
653
           return(i_B);
654
   }
655

    
656
   public int getColorAlpha() {
657
           return(i_Alpha);
658
   }
659

    
660

    
661
   /**
662
    * Sets the algorithm's description string. null by default.
663
    * This string is e.g. used by the graphical modeler to label processing nodes.
664
    *
665
    * @param sDescription
666
    *                description string to be associated with this algorithm
667
    */
668
   public void setDescription(final String sDescription) {
669

    
670
      m_sDescription = sDescription;
671

    
672
   }
673

    
674
   public void setColorR(final int red) {
675
           i_R = red;
676
   }
677

    
678
   public void setColorG(final int green) {
679
           i_G = green;
680
   }
681

    
682
   public void setColorB(final int blue) {
683
           i_B = blue;
684
   }
685

    
686
   public void setColorAlpha(final int alpha) {
687
           i_Alpha = alpha;
688
   }
689

    
690
   /**
691
    *
692
    * @return the set of parameters needed to run the algorithm
693
    */
694
   public ParametersSet getParameters() {
695

    
696
      return m_Parameters;
697

    
698
   }
699

    
700

    
701
   /**
702
    * sets a new set of parameters for the algorithm
703
    *
704
    * @param parameters
705
    *                the new set of parameters
706
    */
707
   public void setParameters(final ParametersSet parameters) {
708

    
709
      m_Parameters = parameters;
710

    
711
   }
712

    
713

    
714
   /**
715
    * Returns the extent that will be used to analyse layers and create create new output layers
716
    *
717
    * @return The extent that will be used to analyse layers and create create new output layers
718
    */
719
   public AnalysisExtent getAnalysisExtent() {
720

    
721
      return m_AnalysisExtent;
722

    
723
   }
724

    
725

    
726
   /**
727
    * Sets a new extent will be used to analyse layers and create create new output layers
728
    *
729
    * @param extent
730
    *                the new extent that will be used to analyse layers and create create new output layers
731
    */
732
   public void setAnalysisExtent(final AnalysisExtent extent) {
733

    
734
      m_AnalysisExtent = extent;
735

    
736
   }
737

    
738

    
739
   /**
740
    * Sets the current step in the progress bar, based on the ratio between the current task step and the total number of steps
741
    * needed to complete the task
742
    *
743
    * @param iStep
744
    *                the current step
745
    * @param iTotalNumberOfSteps
746
    *                the total number of steps
747
    * @return true if the task hasn't been canceled
748
    */
749
   protected boolean setProgress(final int iStep,
750
                                 final int iTotalNumberOfSteps) {
751

    
752
      m_Task.setProgress(iStep, iTotalNumberOfSteps);
753
      return !m_Task.isCanceled();
754

    
755
   }
756

    
757

    
758
   /**
759
    * Sets the current progress text. Use this to inform the user about the work that the algorithm is currently doing.
760
    *
761
    * @param sText
762
    *                the new progress text
763
    */
764
   protected void setProgressText(final String sText) {
765

    
766
      m_Task.setProgressText(sText);
767

    
768
   }
769

    
770

    
771
   /**
772
    *
773
    * @return true if the algorithm requires parameters other than input layers or tables
774
    */
775
   public boolean requiresNonDataObjects() {
776

    
777
      return m_Parameters.requiresNonDataObjects();
778

    
779
   }
780

    
781

    
782
   /**
783
    * @return The number of parameters needed to run the algorithm
784
    */
785
   public int getNumberOfParameters() {
786

    
787
      return m_Parameters.getNumberOfParameters();
788

    
789
   }
790

    
791

    
792
   /**
793
    * @return The number of raster layers needed to run the algorithm
794
    */
795
   public int getNumberOfRasterLayers(final boolean includeMultipleInputs) {
796

    
797
      return m_Parameters.getNumberOfRasterLayers(includeMultipleInputs);
798

    
799
   }
800

    
801

    
802
   /**
803
    * @return The number of vector layer needed to run the algorithm
804
    */
805
   public int getNumberOfVectorLayers(final boolean includeMultipleInputs) {
806

    
807
      return m_Parameters.getNumberOfVectorLayers(includeMultipleInputs);
808

    
809
   }
810

    
811

    
812
   /**
813
    * @return The number of point vector layer needed to run the algorithm
814
    */
815
   public int getNumberOfPointVectorLayers() {
816

    
817
      return m_Parameters.getNumberOfPointVectorLayers();
818

    
819
   }
820

    
821

    
822
   /**
823
    * @return The number of line layer needed to run the algorithm
824
    */
825
   public int getNumberOfLineVectorLayers() {
826

    
827
      return m_Parameters.getNumberOfLineVectorLayers();
828

    
829
   }
830

    
831

    
832
   /**
833
    * @return The number of polygon vector layer needed to run the algorithm
834
    */
835
   public int getNumberOfPolygonLayers() {
836

    
837
      return m_Parameters.getNumberOfPolygonVectorLayers();
838

    
839
   }
840

    
841

    
842
   /**
843
    * @return The number of tables needed to run the algorithm
844
    */
845
   public int getNumberOfTables() {
846

    
847
      return m_Parameters.getNumberOfTables();
848

    
849
   }
850

    
851

    
852
   /**
853
    * @return The number of tables needed to run the algorithm
854
    */
855
   public int getNumberOfNoDataParameters() {
856

    
857
      return m_Parameters.getNumberOfNoDataParameters();
858

    
859
   }
860

    
861

    
862
   /**
863
    * @return The number of TableFields needed to run the algorithm
864
    */
865
   public int getNumberOfTableFieldsParameters() {
866

    
867
      return m_Parameters.getNumberOfTableFieldsParameters();
868

    
869
   }
870

    
871
   /**
872
    * @return The number of TableFields needed to run the algorithm
873
    */
874
   public int getNumberOfTableFilterParameters() {
875

    
876
      return m_Parameters.getNumberOfTableFilterParameters();
877

    
878
   }
879
   /**
880
    * @return The number of TableFields needed to run the algorithm
881
    */
882
   public int getNumberOfBandsParameters() {
883

    
884
      return m_Parameters.getNumberOfBandsParameters();
885

    
886
   }
887

    
888

    
889
   /**
890
    *
891
    * @return true if the user can define the analysis region to be used by the algorithm
892
    */
893
   public boolean getUserCanDefineAnalysisExtent() {
894

    
895
      return m_bUserCanDefineAnalysisExtent;
896

    
897
   }
898

    
899

    
900
   /**
901
    * Use this method to indicate that the user can define the analysis region extent. When creating the corresponding panel for
902
    * the algorithm, it will contain a "Output region" tab, so the user can define the extent he prefers
903
    *
904
    * @param bUserCanDefineAnalysisExtent
905
    *                true if the algorithm generates new raster layers
906
    */
907
   public void setUserCanDefineAnalysisExtent(final boolean bUserCanDefineAnalysisExtent) {
908

    
909
      m_bUserCanDefineAnalysisExtent = bUserCanDefineAnalysisExtent;
910

    
911
   }
912

    
913

    
914
   /**
915
    * Use this method to indicate that the algorithm is determinated (i.e. the number of steps to complete it is known)
916
    *
917
    * @param bDeterminated
918
    *                true if it is a determinated algorithm
919
    */
920
   public void setIsDeterminatedProcess(final boolean bDeterminated) {
921

    
922
      m_bIsDeterminatedProcess = bDeterminated;
923

    
924
   }
925

    
926

    
927
   /**
928
    *
929
    * @return true if the algorithm is determinated (i.e. the number of steps to complete it is known)
930
    */
931
   public boolean isDeterminatedProcess() {
932

    
933
      return m_bIsDeterminatedProcess;
934

    
935
   }
936

    
937

    
938
   //** Methods for creating and handling output objects (tables and layers) **/
939

    
940

    
941
   /**
942
    * @return the set of output objects generated by the algorithm
943
    */
944
   public OutputObjectsSet getOutputObjects() {
945

    
946
      return m_OutputObjects;
947

    
948
   }
949

    
950

    
951
   /**
952
    * sets a new set of output objects
953
    *
954
    * @param ooSet
955
    *                the new set of output objects
956
    */
957
   public void setOutputObjects(final OutputObjectsSet ooSet) {
958

    
959
      m_OutputObjects = ooSet;
960

    
961
   }
962

    
963

    
964
   /**
965
    * Use this method to add a new output object. Use it if, for instance, you have a layer created not within the geoalgorithm
966
    * using a getNewXXXX method, but in a different place, like, for example, calling another method.
967
    *
968
    * @param output
969
    *                The output object to add
970
    */
971
   protected void addOutputObject(final Output output) {
972

    
973
      m_OutputObjects.add(output);
974

    
975
   }
976

    
977

    
978
   /**
979
    *
980
    * Use this method to add a new output object. Use it if, for instance, you have a layer created not within the geoalgorithm
981
    * using a getNewXXXX method, but in a different place, like, for example, calling another method.
982
    *
983
    * @param sName
984
    *                the name of the output
985
    * @param sDescription
986
    *                the description (human-readable) of the output
987
    * @param channel
988
    *                the output channel to use in this output
989
    * @param obj
990
    *                the value of the output
991
    */
992
   protected void addOutputObject(final String sName,
993
                                  final String sDescription,
994
                                  final IOutputChannel channel,
995
                                  final Object obj) {
996
      Output out;
997
      if (obj instanceof IRasterLayer) {
998
         out = new OutputRasterLayer();
999
      }
1000
      else if (obj instanceof IVectorLayer) {
1001
         out = new OutputVectorLayer();
1002
      }
1003
      else if (obj instanceof ITable) {
1004
         out = new OutputTable();
1005
      }
1006
      else if (obj instanceof String) {
1007
         out = new OutputText();
1008
      }
1009
      else if (obj instanceof ChartPanel) {
1010
         out = new OutputChart();
1011
      }
1012
      else {
1013
         return;
1014
      }
1015

    
1016
      out.setOutputChannel(channel);
1017
      out.setDescription(sDescription);
1018
      out.setName(sName);
1019
      out.setOutputObject(obj);
1020
      m_OutputObjects.add(out);
1021

    
1022
   }
1023

    
1024

    
1025
   //------------ methods for creating layers and output objects-------------
1026

    
1027
   /**
1028
    * Returns the output channel associated with the given output. If it is null, it returns a temporary output channel, which is
1029
    * a {@link es.unex.sextante.dataObjects.FileOutputChannel} with a temporary filename. Returns null if no output with that name
1030
    * exists.
1031
    *
1032
    * @param sName
1033
    *                the name of the output from which to retrieve the output channel
1034
    * @return the output channel associated with the given output
1035
    */
1036
   protected IOutputChannel getOutputChannel(final String sName) {
1037

    
1038
      Output out;
1039
      IOutputChannel channel;
1040
      try {
1041
         out = m_OutputObjects.getOutput(sName);
1042
         channel = out.getOutputChannel();
1043
         if (channel == null) {
1044
            channel = new FileOutputChannel(m_OutputFactory.getTempFilename(out));
1045
            out.setOutputChannel(channel);
1046
            return channel;
1047
         }
1048
         else if (channel instanceof FileOutputChannel) {
1049
            final String sFilename = getOutputFilename(out);
1050
            if (sFilename == null) {
1051
               ((FileOutputChannel) channel).setFilename(m_OutputFactory.getTempFilename(out));
1052
               ((FileOutputChannel) channel).setTemporary(true);
1053
               return channel;
1054
            } else {
1055
               ((FileOutputChannel) channel).setFilename(sFilename);
1056
               ((FileOutputChannel) channel).setTemporary(false);
1057
               return channel;
1058
            }
1059
         }
1060
         else {
1061
            return channel;
1062
         }
1063

    
1064

    
1065
      }
1066
      catch (final Exception e) {
1067
         e.printStackTrace();
1068
         return null;
1069
      }
1070

    
1071
   }
1072

    
1073

    
1074
   /**
1075
    * Returns the filename associated with a given output, which must have a file-based output channel. If the output filename
1076
    * matches any of the valid extensions for the type of output (from the ones obtained from the current output factory), it
1077
    * returns that filename. Otherwise, it adds the default extension for the type of output. If the filename is null, it returns
1078
    * null.
1079
    *
1080
    * @param out
1081
    *                an output object
1082
    * @return a checked filename for the passed output object. returns null if the output object filename is null or the output
1083
    *         channel associated with the output is not file-based
1084
    */
1085
   protected String getOutputFilename(final Output out) {
1086

    
1087
      final IOutputChannel channel = out.getOutputChannel();
1088

    
1089
      if (!(channel instanceof FileOutputChannel)) {
1090
         return null;
1091
      }
1092
      final String sFilename = ((FileOutputChannel) channel).getFilename();
1093
      if (sFilename == null) {
1094
         return null;
1095
      }
1096
      String[] exts = null;
1097
      if (out instanceof OutputRasterLayer) {
1098
         exts = m_OutputFactory.getRasterLayerOutputExtensions();
1099
      }
1100
      else if (out instanceof OutputVectorLayer) {
1101
         exts = m_OutputFactory.getVectorLayerOutputExtensions();
1102
      }
1103
      else if (out instanceof OutputTable) {
1104
         exts = m_OutputFactory.getTableOutputExtensions();
1105
      }
1106
      else if (out instanceof Output3DRasterLayer) {
1107
         exts = m_OutputFactory.get3DRasterLayerOutputExtensions();
1108
      }
1109
      else {
1110
         return null;
1111
      }
1112

    
1113
      for (final String element : exts) {
1114
         if (sFilename.endsWith(element)) {
1115
            return sFilename;
1116
         }
1117
      }
1118
      return sFilename + "." + exts[0];
1119
   }
1120

    
1121
   /**
1122
    * This method creates a new vector layer and adds it to the set of output objects of the algorithm. Use this when your
1123
    * algorithm generates a new vector layer and you have to create it.
1124
    *
1125
    * @param sName
1126
    *                The name of the layer. Has to be the same that you used to define this output in the
1127
    * @see {@link #defineCharacteristics()} method.
1128
    * @param sDescription
1129
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1130
    *                GUI
1131
    * @param iShapeType
1132
    *                The shape type. See
1133
    * @see {@link IVectorLayer} for more info about valid values
1134
    * @param types
1135
    *                an array of classes indicating data types for each field
1136
    * @param sFields
1137
    *                an array of field names
1138
    * @return a new vector layer
1139
    * @throws GeoAlgorithmExecutionException
1140
    */
1141
   protected IVectorLayer getNewVectorLayer(final String sName,
1142
                                            final String sDescription,
1143
                                            final int iShapeType,
1144
                                            final Class[] types,
1145
                                            final String[] sFields, final int subtype) throws GeoAlgorithmExecutionException {
1146

    
1147
      try {
1148
         final OutputVectorLayer out = (OutputVectorLayer) m_OutputObjects.getOutput(sName);
1149
         IVectorLayer layer;
1150
         final IOutputChannel channel = getOutputChannel(sName);
1151
         layer = m_OutputFactory.getNewVectorLayer(getLayerName(sName, sDescription), iShapeType, types, sFields, channel, m_CRS, subtype);
1152
         if(layer!=null){
1153
             addOutputVectorLayer(sName, sDescription, iShapeType, channel, layer, out.getInputLayerToOverwrite(), subtype);
1154
         }
1155
         return layer;
1156
      }
1157
      catch (final Exception e) {
1158
         throw new GeoAlgorithmExecutionException(e.getMessage());
1159
      }
1160

    
1161
   }
1162

    
1163
   /**
1164
    * This method creates a new vector layer and adds it to the set of output objects of the algorithm. Use this when your
1165
    * algorithm generates a new vector layer and you have to create it.
1166
    *
1167
    * @param sName
1168
    *                The name of the layer. Has to be the same that you used to define this output in the
1169
    * @see {@link #defineCharacteristics()} method.
1170
    * @param sDescription
1171
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1172
    *                GUI
1173
    * @param iShapeType
1174
    *                The shape type. See
1175
    * @see {@link IVectorLayer} for more info about valid values
1176
    * @param types
1177
    *                an array of classes indicating data types for each field
1178
    * @param sFields
1179
    *                an array of field names
1180
    * @return a new vector layer
1181
    * @throws GeoAlgorithmExecutionException
1182
    */
1183
   protected IVectorLayer getNewVectorLayer(final String sName,
1184
                                            final String sDescription,
1185
                                            final int iShapeType,
1186
                                            final Class[] types,
1187
                                            final String[] sFields) throws GeoAlgorithmExecutionException {
1188

    
1189
       return getNewVectorLayer(sName,
1190
           sDescription,
1191
           iShapeType,
1192
           types,
1193
           sFields, Geometry.SUBTYPES.UNKNOWN);
1194

    
1195
   }
1196

    
1197
   /**
1198
    * This method creates a new vector layer and adds it to the set of output objects of the algorithm. Use this when your
1199
    * algorithm generates a new vector layer and you have to create it.
1200
    *
1201
    * @param sName
1202
    *                The name of the layer. Has to be the same that you used to define this output in the
1203
    * @see {@link #defineCharacteristics()} method.
1204
    * @param sDescription
1205
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1206
    *                GUI
1207
    * @param iShapeType
1208
    *                The shape type. See
1209
    * @see {@link IVectorLayer} for more info about valid values
1210
    * @param types
1211
    *                an array of classes indicating data types for each field
1212
    * @param sFields
1213
    *                an array of field names
1214
    * @param fieldSize
1215
    *                An array of field sizes
1216
    * @return a new vector layer
1217
    * @throws GeoAlgorithmExecutionException
1218
    */
1219
   protected IVectorLayer getNewVectorLayer(final String sName,
1220
                                            final String sDescription,
1221
                                            final int iShapeType,
1222
                                            final Class[] types,
1223
                                            final String[] sFields,
1224
                                            final int[] fieldSize) throws GeoAlgorithmExecutionException {
1225

    
1226
       return getNewVectorLayer(sName, sDescription, iShapeType, types, sFields, fieldSize, Geometry.SUBTYPES.UNKNOWN);
1227
   }
1228
   /**
1229
    * This method creates a new vector layer and adds it to the set of output objects of the algorithm. Use this when your
1230
    * algorithm generates a new vector layer and you have to create it.
1231
    *
1232
    * @param sName
1233
    *                The name of the layer. Has to be the same that you used to define this output in the
1234
    * @see {@link #defineCharacteristics()} method.
1235
    * @param sDescription
1236
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1237
    *                GUI
1238
    * @param iShapeType
1239
    *                The shape type. See
1240
    * @see {@link IVectorLayer} for more info about valid values
1241
    * @param types
1242
    *                an array of classes indicating data types for each field
1243
    * @param sFields
1244
    *                an array of field names
1245
    * @param fieldSize
1246
    *                An array of field sizes
1247
    * @return a new vector layer
1248
    * @throws GeoAlgorithmExecutionException
1249
    */
1250
   protected IVectorLayer getNewVectorLayer(final String sName,
1251
                                            final String sDescription,
1252
                                            final int iShapeType,
1253
                                            final Class[] types,
1254
                                            final String[] sFields,
1255
                                            final int[] fieldSize, final int subtype) throws GeoAlgorithmExecutionException {
1256

    
1257
      try {
1258
         final OutputVectorLayer out = (OutputVectorLayer) m_OutputObjects.getOutput(sName);
1259
         IVectorLayer layer;
1260
         final IOutputChannel channel = getOutputChannel(sName);
1261
         layer = m_OutputFactory.getNewVectorLayer(getLayerName(sName, sDescription), iShapeType, types, sFields, channel, m_CRS,
1262
                  fieldSize, subtype);
1263
         addOutputVectorLayer(sName, sDescription, iShapeType, channel, layer, out.getInputLayerToOverwrite());
1264
         return layer;
1265
      }
1266
      catch (final Exception e) {
1267
         throw new GeoAlgorithmExecutionException(e.getMessage());
1268
      }
1269

    
1270
   }
1271

    
1272

    
1273
   private String getLayerName(final String sName,
1274
                               final String sDescription) {
1275

    
1276
      if (m_OutputMap != null) {
1277
         final String mappedName = m_OutputMap.get(sName);
1278
         if (mappedName == null) {
1279
            return sName;
1280
         }
1281
         else {
1282
            return mappedName;
1283
         }
1284
      }
1285
      else {
1286
         return sDescription;
1287
      }
1288

    
1289
   }
1290

    
1291

    
1292
   /**
1293
    * This method creates a new vector layer but does not add it to the set of output objects of the algorithm. If you are going
1294
    * to read data from this layer, it is recommended to close the layer, call the postProcess() method and then open it again,
1295
    * since some implementations might not support reading and writing features at the same time.
1296
    *
1297
    * @param iShapeType
1298
    *                The shape type. See
1299
    * @see {@link IVectorLayer} for more info about valid values
1300
    * @param types
1301
    *                an array of classes indicating data types for each field
1302
    * @param sFields
1303
    *                an array of field names
1304
    * @return a new vector layer
1305
    * @throws UnsupportedOutputChannelException
1306
    */
1307
   protected IVectorLayer getTempVectorLayer(final int iShapeType,
1308
                                             final Class[] types,
1309
                                             final String[] sFields) throws UnsupportedOutputChannelException {
1310

    
1311
      final String sFilename = m_OutputFactory.getTempVectorLayerFilename();
1312
      final IOutputChannel channel = new FileOutputChannel(sFilename, true);
1313

    
1314
      return m_OutputFactory.getNewVectorLayer("", iShapeType, types, sFields, channel, m_CRS);
1315
   }
1316

    
1317

    
1318
   /**
1319
    * This method creates a new raster layer and adds it to the set of output objects of the algorithm. Use this when your
1320
    * algorithm generates a new raster layer and you have to create it. The grid extent is taken from the algorithm analysis
1321
    * extent (@see {@link #getAnalysisExtent()}
1322
    *
1323
    * @param sName
1324
    *                The name of the layer. Has to be the same that you used to define this output in the
1325
    * @see {@link #defineCharacteristics()} method.
1326
    * @param sDescription
1327
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1328
    *                GUI
1329
    * @param iDataType
1330
    *                The data type. See
1331
    * @see {@link IRasterLayer} for more info about valid values
1332
    * @param iBands
1333
    *                the number of bands of the new layer
1334
    * @return a new raster layer
1335
    * @throws UnsupportedOutputChannelException
1336
    */
1337
   protected IRasterLayer getNewRasterLayer(final String sName,
1338
                                            final String sDescription,
1339
                                            final int iDataType,
1340
                                            final int iBands) throws UnsupportedOutputChannelException {
1341

    
1342
      final IOutputChannel channel = getOutputChannel(sName);
1343

    
1344
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer(getLayerName(sName, sDescription), iDataType,
1345
               m_AnalysisExtent, iBands, channel, m_CRS);
1346

    
1347
      newLayer.setFullExtent();
1348

    
1349
      addOutputRasterLayer(sName, sDescription, iBands, channel, newLayer);
1350

    
1351
      return newLayer;
1352

    
1353
   }
1354

    
1355

    
1356
   /**
1357
    * This method creates a new monoband raster layer and adds it to the set of output objects of the algorithm. Use this when
1358
    * your algorithm generates a new raster layer and you have to create it. The grid extent is taken from the algorithm analysis
1359
    * extent (@see {@link #getAnalysisExtent()}
1360
    *
1361
    * @param sName
1362
    *                The name of the layer. Has to be the same that you used to define this output in the
1363
    * @see {@link #defineCharacteristics()} method.
1364
    * @param sDescription
1365
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1366
    *                GUI
1367
    * @param iDataType
1368
    *                The data type. See
1369
    * @see {@link IRasterLayer} for more info about valid values
1370
    * @return a new raster layer
1371
    * @throws UnsupportedOutputChannelException
1372
    */
1373
   protected IRasterLayer getNewRasterLayer(final String sName,
1374
                                            final String sDescription,
1375
                                            final int iDataType) throws UnsupportedOutputChannelException {
1376

    
1377
      final IOutputChannel channel = getOutputChannel(sName);
1378

    
1379
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer(getLayerName(sName, sDescription), iDataType,
1380
               m_AnalysisExtent, 1, channel, m_CRS);
1381

    
1382
      newLayer.setFullExtent();
1383

    
1384
      addOutputRasterLayer(sName, sDescription, 1, channel, newLayer);
1385

    
1386
      return newLayer;
1387

    
1388
   }
1389

    
1390

    
1391
   /**
1392
    * This method creates a new raster layer and adds it to the set of output objects of the algorithm. Use this when your
1393
    * algorithm generates a new raster layer and you have to create it.
1394
    *
1395
    * @param sName
1396
    *                The name of the layer. Has to be the same that you used to define this output in the
1397
    * @see {@link #defineCharacteristics()} method.
1398
    * @param sDescription
1399
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1400
    *                GUI
1401
    * @param iDataType
1402
    *                The data type. See
1403
    * @see {@link IRasterLayer} for more info about valid values
1404
    * @param extent
1405
    *                The grid extent of the layer to create
1406
    * @param iBands
1407
    *                the number of bands of the new layer
1408
    * @return a new raster layer
1409
    * @throws UnsupportedOutputChannelException
1410
    */
1411
   protected IRasterLayer getNewRasterLayer(final String sName,
1412
                                            final String sDescription,
1413
                                            final int iDataType,
1414
                                            final AnalysisExtent extent,
1415
                                            final int iBands) throws UnsupportedOutputChannelException {
1416

    
1417
      final IOutputChannel channel = getOutputChannel(sName);
1418

    
1419
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer(getLayerName(sName, sDescription), iDataType, extent,
1420
               iBands, channel, m_CRS);
1421

    
1422
      newLayer.setFullExtent();
1423

    
1424
      addOutputRasterLayer(sName, sDescription, iBands, channel, newLayer);
1425

    
1426
      return newLayer;
1427

    
1428
   }
1429

    
1430

    
1431
   /**
1432
    * This method creates a new monoband raster layer and adds it to the set of output objects of the algorithm. Use this when
1433
    * your algorithm generates a new raster layer and you have to create it.
1434
    *
1435
    * @param sName
1436
    *                The name of the layer. Has to be the same that you used to define this output in the
1437
    * @see {@link #defineCharacteristics()} method.
1438
    * @param sDescription
1439
    *                the long description of the output. This is the one usually used to describe the layer when added to a GIS
1440
    *                GUI
1441
    * @param iDataType
1442
    *                The data type. See
1443
    * @see {@link IRasterLayer} for more info about valid values
1444
    * @param extent
1445
    *                The grid extent of the layer to create
1446
    * @return a new raster layer
1447
    * @throws UnsupportedOutputChannelException
1448
    */
1449
   protected IRasterLayer getNewRasterLayer(final String sName,
1450
                                            final String sDescription,
1451
                                            final int iDataType,
1452
                                            final AnalysisExtent extent) throws UnsupportedOutputChannelException {
1453

    
1454
      final IOutputChannel channel = getOutputChannel(sName);
1455

    
1456
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer(getLayerName(sName, sDescription), iDataType, extent, 1,
1457
               channel, m_CRS);
1458

    
1459
      newLayer.setFullExtent();
1460

    
1461
      addOutputRasterLayer(sName, sDescription, 1, channel, newLayer);
1462

    
1463
      return newLayer;
1464

    
1465
   }
1466

    
1467

    
1468
   protected IRasterLayer getTempRasterLayer(final int iDataType,
1469
                                             final AnalysisExtent extent,
1470
                                             final int iBands) throws UnsupportedOutputChannelException {
1471

    
1472
      final String sFilename = m_OutputFactory.getTempRasterLayerFilename();
1473
      final IOutputChannel channel = new FileOutputChannel(sFilename, true);
1474

    
1475
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer("", iDataType, extent, iBands, channel, m_CRS);
1476

    
1477
      newLayer.setFullExtent();
1478

    
1479
      return newLayer;
1480

    
1481
   }
1482

    
1483

    
1484
   protected IRasterLayer getTempRasterLayer(final int iDataType,
1485
                                             final AnalysisExtent extent) throws UnsupportedOutputChannelException {
1486

    
1487
      final String sFilename = m_OutputFactory.getTempRasterLayerFilename();
1488
      final IOutputChannel channel = new FileOutputChannel(sFilename, true);
1489

    
1490
      final IRasterLayer newLayer = m_OutputFactory.getNewRasterLayer("", iDataType, extent, 1, channel, m_CRS);
1491

    
1492
      newLayer.setFullExtent();
1493

    
1494
      return newLayer;
1495

    
1496
   }
1497

    
1498

    
1499
   protected I3DRasterLayer getNew3DRasterLayer(final String sName,
1500
                                                final String sDescription,
1501
                                                final int iDataType,
1502
                                                final AnalysisExtent extent) throws UnsupportedOutputChannelException {
1503

    
1504
      final IOutputChannel channel = getOutputChannel(sName);
1505

    
1506
      final I3DRasterLayer newLayer = m_OutputFactory.getNew3DRasterLayer(getLayerName(sName, sDescription), iDataType, extent,
1507
               channel, m_CRS);
1508

    
1509
      addOutput3DRasterLayer(sName, sDescription, channel, newLayer);
1510

    
1511
      return newLayer;
1512

    
1513
   }
1514

    
1515

    
1516
   protected I3DRasterLayer getNew3DRasterLayer(final String sName,
1517
                                                final String sDescription,
1518
                                                final int iDataType) throws UnsupportedOutputChannelException {
1519

    
1520
      final IOutputChannel channel = getOutputChannel(sName);
1521

    
1522
      final I3DRasterLayer newLayer = m_OutputFactory.getNew3DRasterLayer(getLayerName(sName, sDescription), iDataType,
1523
               m_AnalysisExtent, channel, m_CRS);
1524

    
1525
      addOutput3DRasterLayer(sName, sDescription, channel, newLayer);
1526

    
1527
      return newLayer;
1528

    
1529
   }
1530

    
1531

    
1532
   protected ITable getNewTable(final String sName,
1533
                                final String sDescription,
1534
                                final Class[] types,
1535
                                final String[] sFields) throws UnsupportedOutputChannelException {
1536

    
1537
      final IOutputChannel channel = getOutputChannel(sName);
1538

    
1539
      final ITable table = m_OutputFactory.getNewTable(getLayerName(sName, sDescription), types, sFields, channel);
1540

    
1541
      addOutputTable(sName, sDescription, channel, table);
1542

    
1543
      return table;
1544

    
1545
   }
1546

    
1547

    
1548
   /////////////////////////////////////////////////////////////////////////////////////
1549

    
1550
   /**
1551
    * Adds a new raster layer to the output set
1552
    *
1553
    * @param sName
1554
    *                The name to identify the layer in the set
1555
    * @param sDescription
1556
    *                The description of the layer
1557
    * @param iBands
1558
    *                The number of bands the output layer will have
1559
    * @param channel
1560
    *                the output channel associated to the output
1561
    * @param layer
1562
    *                the layer itself
1563
    */
1564
   protected void addOutputRasterLayer(final String sName,
1565
                                       final String sDescription,
1566
                                       final int iBands,
1567
                                       final IOutputChannel channel,
1568
                                       final IRasterLayer layer) {
1569

    
1570
      final OutputRasterLayer out = new OutputRasterLayer();
1571
      out.setName(sName);
1572
      out.setDescription(sDescription);
1573
      out.setOutputObject(layer);
1574
      out.setOutputChannel(channel);
1575
      out.setNumberOfBands(iBands);
1576

    
1577
      m_OutputObjects.add(out);
1578

    
1579
   }
1580

    
1581

    
1582
   /**
1583
    * Adds a new raster layer to the output set. The value of the output is null, and so is the filename. Use this method in the
1584
    * DefineCharacteristics() method of the algorithm, to define the outputs expected.
1585
    *
1586
    * @param sName
1587
    *                The name to identify the layer in the set
1588
    * @param sDescription
1589
    *                The description of the layer
1590
    * @param iBands
1591
    *                The number of bands the output layer will have
1592
    */
1593
   protected void addOutputRasterLayer(final String sName,
1594
                                       final String sDescription,
1595
                                       final int iBands) {
1596

    
1597
      addOutputRasterLayer(sName, sDescription, iBands, null, null);
1598

    
1599
   }
1600

    
1601

    
1602
   /**
1603
    * Adds a new monoband raster layer to the output set. The value of the output is null, and so is the filename. Use this method
1604
    * in the DefineCharacteristics() method of the algorithm, to define the outputs expected.
1605
    *
1606
    * @param sName
1607
    *                The name to identify the layer in the set
1608
    * @param sDescription
1609
    *                The description of the layer
1610
    */
1611
   protected void addOutputRasterLayer(final String sName,
1612
                                       final String sDescription) {
1613

    
1614
      addOutputRasterLayer(sName, sDescription, 1, null, null);
1615

    
1616
   }
1617

    
1618

    
1619
   /**
1620
    * Adds a new 3D raster layer to the output set. The value of the output is null, and so is the filename. Use this method in
1621
    * the DefineCharacteristics() method of the algorithm, to define the outputs expected.
1622
    *
1623
    * @param sName
1624
    *                The name to identify the layer in the set
1625
    * @param sDescription
1626
    *                The description of the layer
1627
    */
1628

    
1629
   protected void addOutput3DRasterLayer(final String sName,
1630
                                         final String sDescription) {
1631

    
1632
      addOutput3DRasterLayer(sName, sDescription, null, null);
1633

    
1634
   }
1635

    
1636

    
1637
   /**
1638
    * Adds a new 3D raster layer to the output set
1639
    *
1640
    * @param sName
1641
    *                the name to identify the layer in the set
1642
    * @param sDescription
1643
    *                the description of the layer
1644
    * @param channel
1645
    *                the output channel associated to the output
1646
    * @param layer
1647
    *                the layer itself
1648
    */
1649
   protected void addOutput3DRasterLayer(final String sName,
1650
                                         final String sDescription,
1651
                                         final IOutputChannel channel,
1652
                                         final I3DRasterLayer layer) {
1653

    
1654
      final Output3DRasterLayer out = new Output3DRasterLayer();
1655
      out.setName(sName);
1656
      out.setDescription(sDescription);
1657
      out.setOutputObject(layer);
1658
      out.setOutputChannel(channel);
1659

    
1660
      m_OutputObjects.add(out);
1661

    
1662
   }
1663

    
1664
   /**
1665
    * Adds a new vector layer to the output set
1666
    *
1667
    * @param sName
1668
    *                The name to identify the layer in the set
1669
    * @param sDescription
1670
    *                The description of the layer
1671
    * @param iType
1672
    *                the shape type of the layer
1673
    * @param channel
1674
    *                the output channel associated to the output
1675
    * @param layer
1676
    *                the layer itself
1677
    * @param sInputLayerToOverwrite
1678
    *                the name of the input param (another vector layer) that this output can overwrite
1679
    *
1680
    */
1681
   protected void addOutputVectorLayer(final String sName,
1682
                                       final String sDescription,
1683
                                       final int iType,
1684
                                       final IOutputChannel channel,
1685
                                       final IVectorLayer layer,
1686
                                       final String sInputLayerToOverwrite,
1687
                                       final int subtype) {
1688

    
1689
      final OutputVectorLayer out = new OutputVectorLayer();
1690
      out.setName(sName);
1691
      out.setDescription(sDescription);
1692
      out.setOutputObject(layer);
1693
      out.setOutputChannel(channel);
1694
      out.setShapeType(iType);
1695
      out.setInputLayerToOverwrite(sInputLayerToOverwrite);
1696
      out.setSubType(subtype);
1697

    
1698
      m_OutputObjects.add(out);
1699

    
1700
   }
1701

    
1702
   /**
1703
    * Adds a new vector layer to the output set
1704
    *
1705
    * @param sName
1706
    *                The name to identify the layer in the set
1707
    * @param sDescription
1708
    *                The description of the layer
1709
    * @param iType
1710
    *                the shape type of the layer
1711
    * @param channel
1712
    *                the output channel associated to the output
1713
    * @param layer
1714
    *                the layer itself
1715
    * @param sInputLayerToOverwrite
1716
    *                the name of the input param (another vector layer) that this output can overwrite
1717
    *
1718
    */
1719
   protected void addOutputVectorLayer(final String sName,
1720
                                       final String sDescription,
1721
                                       final int iType,
1722
                                       final IOutputChannel channel,
1723
                                       final IVectorLayer layer,
1724
                                       final String sInputLayerToOverwrite) {
1725

    
1726
       addOutputVectorLayer(sName, sDescription, iType, null, null, sInputLayerToOverwrite, Geometry.SUBTYPES.UNKNOWN);
1727
   }
1728

    
1729

    
1730
   /**
1731
    * Adds a new vector layer to the output set. The value of the output is null, and so is the filename. Use this method in the
1732
    * DefineCharacteristics() method of the algorithm, to define the outputs expected.
1733
    *
1734
    * @param sName
1735
    *                The name to identify the layer in the set
1736
    * @param sDescription
1737
    *                The description of the layer
1738
    * @param iType
1739
    *                the shape type of the layer
1740
    * @param sInputLayerToOverwrite
1741
    *                the name of the input param (another vector layer) that this output can overwrite
1742
    */
1743
   protected void addOutputVectorLayer(final String sName,
1744
                                       final String sDescription,
1745
                                       final int iType,
1746
                                       final String sInputLayerToOverwrite) {
1747

    
1748
      addOutputVectorLayer(sName, sDescription, iType, null, null, sInputLayerToOverwrite);
1749

    
1750
   }
1751

    
1752

    
1753
   /**
1754
    * Adds a new vector layer to the output set. The value of the output is null, and so is the filename. Use this method in the
1755
    * DefineCharacteristics() method of the algorithm, to define the outputs expected.
1756
    *
1757
    * @param sName
1758
    *                The name to identify the layer in the set
1759
    * @param sDescription
1760
    *                The description of the layer
1761
    * @param iType
1762
    *                the shape type of the layer
1763
    */
1764
   protected void addOutputVectorLayer(final String sName,
1765
                                       final String sDescription,
1766
                                       final int iType) {
1767

    
1768
      addOutputVectorLayer(sName, sDescription, iType, null, null, null);
1769

    
1770
   }
1771

    
1772

    
1773
   /**
1774
    * Adds a new vector layer to the output set. The value of the output is null, and so is the filename. Use this method in the
1775
    * DefineCharacteristics() method of the algorithm, to define the outputs expected. The shape type is set to undefined
1776
    *
1777
    * @param sName
1778
    *                The name to identify the layer in the set
1779
    * @param sDescription
1780
    *                The description of the layer
1781
    */
1782
   protected void addOutputVectorLayer(final String sName,
1783
                                       final String sDescription) {
1784

    
1785
      addOutputVectorLayer(sName, sDescription, OutputVectorLayer.SHAPE_TYPE_UNDEFINED, null, null, null);
1786

    
1787
   }
1788

    
1789

    
1790
   /**
1791
    * Adds a new table to the output set
1792
    *
1793
    * @param sName
1794
    *                The name to identify the layer in the set
1795
    * @param sDescription
1796
    *                The description of the layer
1797
    * @param channel
1798
    *                the output channel associated to the output
1799
    * @param table
1800
    *                the table itself
1801
    */
1802
   protected void addOutputTable(final String sName,
1803
                                 final String sDescription,
1804
                                 final IOutputChannel channel,
1805
                                 final ITable table) {
1806

    
1807
      final Output out = new OutputTable();
1808
      out.setName(sName);
1809
      out.setDescription(sDescription);
1810
      out.setOutputObject(table);
1811
      out.setOutputChannel(channel);
1812

    
1813
      m_OutputObjects.add(out);
1814

    
1815
   }
1816

    
1817

    
1818
   /**
1819
    * Adds a new table to the output set. The value of the output is null, and so is the filename. Use this method in the
1820
    * DefineCharacteristics() method of the algorithm, to define the outputs expected.
1821
    *
1822
    * @param sName
1823
    *                The name to identify the layer in the set
1824
    * @param sDescription
1825
    *                The description of the layer
1826
    */
1827
   protected void addOutputTable(final String sName,
1828
                                 final String sDescription) {
1829

    
1830
      addOutputTable(sName, sDescription, null, null);
1831

    
1832
   }
1833

    
1834

    
1835
   /**
1836
    * Adds a new chart panel to the output set
1837
    *
1838
    * @param sName
1839
    *                The name to identify the layer in the set
1840
    * @param sDescription
1841
    *                The description of the layer
1842
    * @param chart
1843
    *                a chart panel
1844
    */
1845
   protected void addOutputChart(final String sName,
1846
                                 final String sDescription,
1847
                                 final ChartPanel chart) {
1848

    
1849
      final Output out = new OutputChart();
1850
      out.setName(sName);
1851
      out.setDescription(sDescription);
1852
      out.setOutputObject(chart);
1853

    
1854
      m_OutputObjects.add(out);
1855

    
1856
   }
1857

    
1858

    
1859
   /**
1860
    * Adds a new chart to the output set. The value of the output is null. Use this method in the DefineCharacteristics() method
1861
    * of the algorithm, to define the outputs expected.
1862
    *
1863
    * @param sName
1864
    *                The name to identify the output in the set
1865
    * @param sDescription
1866
    *                The description of the output
1867
    */
1868
   protected void addOutputChart(final String sName,
1869
                                 final String sDescription) {
1870

    
1871
      addOutputChart(sName, sDescription, null);
1872

    
1873
   }
1874

    
1875

    
1876
   /**
1877
    * Adds a new image to the output set. The value of the output is null. Use this method in the DefineCharacteristics() method
1878
    * of the algorithm, to define the outputs expected.
1879
    *
1880
    * @param sName
1881
    *                The name to identify the output in the set
1882
    * @param sDescription
1883
    *                The description of the output
1884
    */
1885
   protected void addOutputImage(final String sName,
1886
                                 final String sDescription) {
1887

    
1888
      final Output out = new OutputImage();
1889
      out.setName(sName);
1890
      out.setDescription(sDescription);
1891
      out.setOutputObject(null);
1892

    
1893
      m_OutputObjects.add(out);
1894

    
1895
   }
1896

    
1897

    
1898
   /**
1899
    * Adds a new text string to the output set
1900
    *
1901
    * @param sName
1902
    *                The name to identify the string in the set
1903
    * @param sDescription
1904
    *                The description of the string
1905
    * @param sText
1906
    *                the text to add (HTML formatted text)
1907
    */
1908
   protected void addOutputText(final String sName,
1909
                                final String sDescription,
1910
                                final String sText) {
1911

    
1912
      final Output out = new OutputText();
1913
      out.setName(sName);
1914
      out.setDescription(sDescription);
1915
      out.setOutputObject(sText);
1916

    
1917
      m_OutputObjects.add(out);
1918

    
1919
   }
1920

    
1921

    
1922
   /**
1923
    * Adds a new text numerical value to the output set. The value of the output is null. Use this method in the
1924
    * DefineCharacteristics() method of the algorithm, to define the outputs expected.
1925
    *
1926
    * @param sName
1927
    *                The name to identify the output in the set
1928
    * @param sDescription
1929
    *                The description of the output
1930
    */
1931
   protected void addOutputNumericalValue(final String sName,
1932
                                          final String sDescription) {
1933

    
1934
      final Output out = new OutputNumericalValue();
1935
      out.setName(sName);
1936
      out.setDescription(sDescription);
1937
      out.setOutputObject(null);
1938

    
1939
      m_OutputObjects.add(out);
1940

    
1941
   }
1942

    
1943

    
1944
   /**
1945
    * Adds a new numerical value to the output set
1946
    *
1947
    * @param sName
1948
    *                The name to identify the value in the set
1949
    * @param number
1950
    *                the value of the output
1951
    */
1952
   protected void addOutputNumericalValue(final String sName,
1953
                                          final Number number) {
1954

    
1955
      final Output out = new OutputNumericalValue();
1956
      out.setName(sName);
1957
      out.setDescription(sName);
1958
      out.setOutputObject(number);
1959

    
1960
      m_OutputObjects.add(out);
1961

    
1962
   }
1963

    
1964

    
1965
   /**
1966
    * Adds a new text string to the output set. The value of the output is null. Use this method in the DefineCharacteristics()
1967
    * method of the algorithm, to define the outputs expected.
1968
    *
1969
    * @param sName
1970
    *                The name to identify the output in the set
1971
    * @param sDescription
1972
    *                The description of the output
1973
    */
1974
   protected void addOutputText(final String sName,
1975
                                final String sDescription) {
1976

    
1977
      addOutputText(sName, sDescription, null);
1978

    
1979
   }
1980

    
1981

    
1982
   @Override
1983
   public String toString() {
1984

    
1985
      return m_sName;
1986

    
1987
   }
1988

    
1989

    
1990
   /**
1991
    *
1992
    * @return the command line name of the algorithm
1993
    */
1994
   public String getCommandLineName() {
1995

    
1996
      final String sClass = this.getClass().getName();
1997
      final int iLast = sClass.lastIndexOf(".");
1998
      final String sCommandName = sClass.substring(iLast + 1, sClass.length() - "Algorithm".length());
1999

    
2000
      return sCommandName.toLowerCase();
2001

    
2002
   }
2003

    
2004

    
2005
   /**
2006
    *
2007
    * @return a new instance of the algorithm
2008
    * @throws InstantiationException
2009
    * @throws IllegalAccessException
2010
    */
2011
   public GeoAlgorithm getNewInstance() throws InstantiationException, IllegalAccessException {
2012

    
2013
      final GeoAlgorithm alg = this.getClass().newInstance();
2014

    
2015
      alg.setName(m_sName);
2016
      alg.setGroup(m_sGroup);
2017

    
2018
      alg.setParameters(m_Parameters.getNewInstance());
2019
      alg.setOutputObjects(m_OutputObjects.getNewInstance());
2020

    
2021
      if (m_bIsAutoExtent) {
2022
         alg.setAnalysisExtent(null);
2023
         alg.m_bIsAutoExtent = true;
2024
      }
2025

    
2026
      return alg;
2027

    
2028
   }
2029

    
2030

    
2031
   /**
2032
    *
2033
    * @return true if the algorithm is suitable for a modeling process. This should be based on how well-defined the outputs are.
2034
    *         If, for instance, the number of output layers cannot be known in advance, then this method should return false
2035
    */
2036
   public boolean isSuitableForModelling() {
2037

    
2038
      return true;
2039

    
2040
   }
2041

    
2042

    
2043
   /**
2044
    * Any preprocessing needed before executing the algorithm as part of a model should be carried on in this method. Also, this
2045
    * method should be used to do any extra checking, to ensure that parameter values are correct. If not, an exception should be
2046
    * thrown. If data are not yet available (another algorithm in the model has to be run before this one), this method should
2047
    * return false. Otherwise, should return true if the algorithm can be run after being preprocessed.
2048
    *
2049
    * @param model
2050
    *                the model from which the algorithm is being executed
2051
    * @throws GeoAlgorithmExecutionException
2052
    *                 if the parameters are not correct and the algorithm cannot be executed
2053
    * @returns true if the algorithm can be executed after being preprocessed
2054
    */
2055
   public boolean preprocessForModeller(final Object model) throws GeoAlgorithmExecutionException {
2056

    
2057
      //By default it does nothing, since most algorithms
2058
      //do not need preprocessing or checking at all.
2059

    
2060
      return true;
2061

    
2062
   }
2063

    
2064

    
2065
   /**
2066
    * Returns true if the algorithms generates new layers
2067
    *
2068
    * @return true if the algorithms generates new layers
2069
    */
2070
   public boolean generatesLayers() {
2071

    
2072
      return m_OutputObjects.hasLayers();
2073

    
2074
   }
2075

    
2076

    
2077
   /**
2078
    * Returns true if the algorithms generates new layers or tables
2079
    *
2080
    * @return true if the algorithms generates new layers or tables
2081
    */
2082
   public boolean generatesLayersOrTables() {
2083

    
2084
      return m_OutputObjects.hasDataObjects();
2085

    
2086
   }
2087

    
2088

    
2089
   /**
2090
    * Returns the number of new objects (layers and tables) generated by the algorithm
2091
    *
2092
    * @return the number of new objects (layers and tables) generated by the algorithm
2093
    */
2094
   public int getNumberOfOutputObjects() {
2095

    
2096
      return m_OutputObjects.getOutputDataObjectsCount();
2097

    
2098
   }
2099

    
2100

    
2101
   /**
2102
    * Returns a string containing the command line usage of the algorithm
2103
    *
2104
    * @return a string containing the command line usage of the algorithm
2105
    */
2106
   public String getCommandLineHelp() {
2107

    
2108
      final String sFirstLine = "Usage: runalg( \"" + getCommandLineName() + "\",\n";
2109

    
2110
      return getCommandLineParametersHelp(sFirstLine);
2111

    
2112
   }
2113

    
2114

    
2115
   protected String getCommandLineParametersHelp(final String sFirstLine) {
2116

    
2117
      int i;
2118
      final ParametersSet params = getParameters();
2119
      final StringBuffer sb = new StringBuffer(sFirstLine);
2120
      sb.append(getfixedLengthBlankLine(sFirstLine.length()));
2121

    
2122
      for (i = 0; i < params.getNumberOfParameters(); i++) {
2123
         final Parameter param = params.getParameter(i);
2124
         sb.append(param.getParameterName() + "[");
2125
         if (param instanceof ParameterDataObject) {
2126
            AdditionalInfoDataObject ai;
2127
            try {
2128
               ai = (AdditionalInfoDataObject) param.getParameterAdditionalInfo();
2129
               if (!ai.getIsMandatory()) {
2130
                  sb.append("Optional ");
2131
               }
2132
            }
2133
            catch (final NullParameterAdditionalInfoException e) {}
2134

    
2135
         }
2136
         sb.append(param.getParameterTypeName());
2137
         if (param instanceof ParameterTableField) {
2138
            AdditionalInfoTableField ai;
2139
            try {
2140
               ai = (AdditionalInfoTableField) param.getParameterAdditionalInfo();
2141
               sb.append(" from " + ai.getParentParameterName());
2142
            }
2143
            catch (final NullParameterAdditionalInfoException e) {}
2144
         }
2145
         if (param instanceof ParameterFixedTable) {
2146
            AdditionalInfoFixedTable ai;
2147
            try {
2148
               ai = (AdditionalInfoFixedTable) param.getParameterAdditionalInfo();
2149
               final String sCols[] = ai.getCols();
2150
               sb.append(" (Cols:");
2151
               for (final String element : sCols) {
2152
                  sb.append(" | " + element);
2153
               }
2154
               sb.append(" | ). (Rows: ");
2155
               if (ai.isNumberOfRowsFixed()) {
2156
                  sb.append(ai.getRowsCount() + ")");
2157
               }
2158
               else {
2159
                  sb.append("any)");
2160
               }
2161
            }
2162
            catch (final NullParameterAdditionalInfoException e) {}
2163
         }
2164
         else if (param instanceof ParameterMultipleInput) {
2165
            AdditionalInfoMultipleInput ai;
2166
            try {
2167
               ai = (AdditionalInfoMultipleInput) param.getParameterAdditionalInfo();
2168
               switch (ai.getDataType()) {
2169
                  case AdditionalInfoMultipleInput.DATA_TYPE_BAND:
2170
                     sb.append(" - Band");
2171
                     break;
2172
                  case AdditionalInfoMultipleInput.DATA_TYPE_RASTER:
2173
                     sb.append(" - Raster Layer");
2174
                     break;
2175
                  case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_ANY:
2176
                     sb.append(" - Vector Layer");
2177
                     break;
2178
                  case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POINT:
2179
                     sb.append(" - Points Layer");
2180
                     break;
2181
                  case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_LINE:
2182
                     sb.append(" - Lines Layer");
2183
                     break;
2184
                  case AdditionalInfoMultipleInput.DATA_TYPE_VECTOR_POLYGON:
2185
                     sb.append(" - Polygons Layer");
2186
                     break;
2187
                  case AdditionalInfoMultipleInput.DATA_TYPE_TABLE:
2188
                     sb.append(" - Table");
2189
                     break;
2190
               }
2191
            }
2192
            catch (final NullParameterAdditionalInfoException e) {}
2193
         }
2194
         sb.append("]");
2195
         sb.append(",\n" + getfixedLengthBlankLine(sFirstLine.length()));
2196
      }
2197

    
2198
      for (i = 0; i < m_OutputObjects.getOutputObjectsCount(); i++) {
2199
         final Output out = m_OutputObjects.getOutput(i);
2200
         if ((out instanceof OutputRasterLayer) || (out instanceof OutputVectorLayer) || (out instanceof OutputTable)) {
2201
            //i++;
2202
            sb.append(out.getName() + "[output ");
2203
            if (out instanceof OutputRasterLayer) {
2204
               sb.append("raster layer");
2205
            }
2206
            else if (out instanceof OutputVectorLayer) {
2207
               sb.append("vector layer");
2208
            }
2209
            else if (out instanceof OutputTable) {
2210
               sb.append("table");
2211
            }
2212
            sb.append("]");
2213
            sb.append(",\n" + getfixedLengthBlankLine(sFirstLine.length()));
2214
         }
2215
      }
2216

    
2217
      sb.append(");");
2218

    
2219
      return sb.toString();
2220

    
2221
   }
2222

    
2223

    
2224
   private String getfixedLengthBlankLine(final int iLength) {
2225

    
2226
      final String sResult = "                                                                     ";
2227

    
2228
      return sResult.substring(0, iLength);
2229

    
2230
   }
2231

    
2232
   public File getHelpFile() {
2233
       return null;
2234
   }
2235

    
2236
   /**
2237
    * Returns the command line expression that would create this instance of the algorithm
2238
    *
2239
    * @return A command line expression representing this algorithm
2240
    */
2241
   public String[] getAlgorithmAsCommandLineSentences() {
2242

    
2243
      int i;
2244
      String[] sReturn;
2245
      final String sFirstLine = "runalg(\"" + getCommandLineName() + "\", ";
2246
      final StringBuffer sb = new StringBuffer(sFirstLine);
2247

    
2248
      for (i = 0; i < m_Parameters.getNumberOfParameters(); i++) {
2249
         final Parameter param = m_Parameters.getParameter(i);
2250
         sb.append(param.getCommandLineParameter() + ", ");
2251
      }
2252

    
2253
      for (int j = 0; j < m_OutputObjects.getOutputObjectsCount(); j++) {
2254
         final Output out = m_OutputObjects.getOutput(j);
2255
         if ((out instanceof OutputRasterLayer) || (out instanceof Output3DRasterLayer) || (out instanceof OutputVectorLayer)
2256
             || (out instanceof OutputTable)) {
2257
            sb.append(out.getCommandLineParameter() + ", ");
2258
         }
2259
      }
2260

    
2261
      final String sAlg = sb.substring(0, sb.length() - 2) + ")";
2262

    
2263
      if (getUserCanDefineAnalysisExtent()) {
2264
         sReturn = new String[2];
2265
         if (m_bIsAutoExtent) {
2266
            sReturn[0] = "autoextent(\"true\")";
2267
         }
2268
         else {
2269
            final AnalysisExtent ge = getAnalysisExtent();
2270
            sReturn[0] = "extent( " + ge.toString() + ")";
2271
         }
2272
         sReturn[1] = sAlg;
2273
      }
2274
      else {
2275
         sReturn = new String[1];
2276
         sReturn[0] = sAlg;
2277
      }
2278

    
2279
      return sReturn;
2280

    
2281
   }
2282

    
2283

    
2284
   ////////////////////////Requirements/////////////////////////////
2285

    
2286
   /**
2287
    * Returns true if the algorithm requires vector layers to run
2288
    *
2289
    * @see ParametersSet#requiresVectorLayers()
2290
    * @return true if the algorithm requires vector layers to run
2291
    */
2292
   public boolean requiresVectorLayers() {
2293

    
2294
      return m_Parameters.requiresVectorLayers();
2295

    
2296
   }
2297

    
2298

    
2299
   /**
2300
    * Returns true if the algorithm requires vector layers as individual input (i.e. not as a multiple input)
2301
    *
2302
    * @return true if the algorithm requires vector layers as individual input
2303
    */
2304
   public boolean requiresIndividualVectorLayers() {
2305

    
2306
      return m_Parameters.getNumberOfVectorLayers() > 0;
2307

    
2308
   }
2309

    
2310

    
2311
   /**
2312
    * Returns true if the algorithm requires polygon vector layers to run
2313
    *
2314
    * @see ParametersSet#requiresPolygonVectorLayers()
2315
    * @return true if the algorithm requires polygon vector layers to run
2316
    */
2317
   public boolean requiresPolygonVectorLayers() {
2318

    
2319
      return m_Parameters.requiresPolygonVectorLayers();
2320

    
2321
   }
2322

    
2323

    
2324
   /**
2325
    * Returns true if the algorithm requires line vector layers to run
2326
    *
2327
    * @see ParametersSet#requiresLineVectorLayers()
2328
    * @return true if the algorithm requires line vector layers to run
2329
    */
2330
   public boolean requiresLineVectorLayers() {
2331

    
2332
      return m_Parameters.requiresLineVectorLayers();
2333

    
2334
   }
2335

    
2336

    
2337
   /**
2338
    * Returns true if the algorithm requires point vector layers to run
2339
    *
2340
    * @see ParametersSet#requiresVectorLayers()
2341
    * @return true if the algorithm requires point vector layers to run
2342
    */
2343
   public boolean requiresPointVectorLayers() {
2344

    
2345
      return m_Parameters.requiresPointVectorLayers();
2346

    
2347
   }
2348

    
2349

    
2350
   /**
2351
    * Returns true if the algorithm requires raster layers to run
2352
    *
2353
    * @see ParametersSet#requiresVectorLayers()
2354
    * @return true if the algorithm requires raster layers to run
2355
    */
2356
   public boolean requiresRasterLayers() {
2357

    
2358
      return m_Parameters.requiresRasterLayers();
2359

    
2360
   }
2361

    
2362

    
2363
   /**
2364
    * Returns true if the algorithm requires 3D raster layers to run
2365
    *
2366
    * @see ParametersSet#requiresVectorLayers()
2367
    * @return true if the algorithm requires raster layers to run
2368
    */
2369
   public boolean requires3DRasterLayers() {
2370

    
2371
      return m_Parameters.requires3DRasterLayers();
2372

    
2373
   }
2374

    
2375

    
2376
   /**
2377
    * Returns true if the algorithm requires raster layers as individual input (i.e. not as a multiple input)
2378
    *
2379
    * @return true if the algorithm requires raster layers as individual input
2380
    */
2381
   public boolean requiresIndividualRasterLayers() {
2382

    
2383
      return m_Parameters.getNumberOfRasterLayers() > 0;
2384

    
2385
   }
2386

    
2387

    
2388
   /**
2389
    * Returns true if the algorithm requires raster layers as multiple input
2390
    *
2391
    * @return true if the algorithm requires raster layers as multiple input
2392
    */
2393
   public boolean requiresMultipleRasterLayers() {
2394

    
2395
      return m_Parameters.requiresMultipleRasterLayers();
2396

    
2397
   }
2398

    
2399

    
2400
   /**
2401
    * Returns true if the algorithm requires vector layers as multiple input
2402
    *
2403
    * @return true if the algorithm requires vector layers as multiple input
2404
    */
2405
   public boolean requiresMultipleVectorLayers() {
2406

    
2407
      return m_Parameters.requiresMultipleVectorLayers();
2408

    
2409
   }
2410

    
2411

    
2412
   /**
2413
    * Returns true if the algorithm requires tables layers as multiple input
2414
    *
2415
    * @return true if the algorithm requires tables layers as multiple input
2416
    */
2417
   public boolean requiresMultipleTables() {
2418

    
2419
      return m_Parameters.requiresMultipleTables();
2420

    
2421
   }
2422

    
2423

    
2424
   /**
2425
    * Returns true if the algorithm requires raster bands as multiple input (i.e. the parameter set contains a multiple input
2426
    * parameter of type band)
2427
    *
2428
    * @return true if the algorithm requires raster bands as multiple input
2429
    */
2430
   public boolean requiresMultipleRasterBands() {
2431

    
2432
      return m_Parameters.requiresMultipleRasterBands();
2433

    
2434
   }
2435

    
2436

    
2437
   /**
2438
    * Returns true if the algorithm requires raster layers to run
2439
    *
2440
    * @see ParametersSet#requiresVectorLayers()
2441
    * @return true if the algorithm requires raster layers to run
2442
    */
2443
   public boolean requiresTables() {
2444

    
2445
      return m_Parameters.requiresTables();
2446

    
2447
   }
2448

    
2449

    
2450
   /**
2451
    * Returns true if the algorithm requires table field layers to run
2452
    *
2453
    * @see ParametersSet#requiresTableFields()
2454
    * @return true if the algorithm requires table fields to run
2455
    */
2456
   public boolean requiresTableFields() {
2457

    
2458
      return m_Parameters.requiresTableFields();
2459

    
2460
   }
2461

    
2462

    
2463
   /**
2464
    * Returns true if the algorithm requires point coordinates to run
2465
    *
2466
    * @see ParametersSet#requiresPoints()
2467
    * @return true if the algorithm requires point coordinates to run
2468
    */
2469
   public boolean requiresPoints() {
2470

    
2471
      return m_Parameters.requiresPoints();
2472

    
2473
   }
2474

    
2475

    
2476
   /**
2477
    * Returns false if there are not enough raster data in the given array to run the algorithm
2478
    *
2479
    * @param objs
2480
    *                an array of available data objects
2481
    * @return false if the algorithm requires more raster layers than the ones in the data objects array. True if they suffice
2482
    */
2483
   public boolean meetsRasterRequirements(final Object[] objs) {
2484

    
2485
      if (objs == null) {
2486
         return false;
2487
      }
2488

    
2489
      if (requiresRasterLayers()) {
2490
         for (final Object element : objs) {
2491
            if (element instanceof IRasterLayer) {
2492
               return true;
2493
            }
2494
         }
2495
         return false;
2496
      }
2497
      else {
2498
         return true;
2499
      }
2500

    
2501
   }
2502

    
2503

    
2504
   /**
2505
    * Returns false if there are not enough 3D raster data in the given array to run the algorithm
2506
    *
2507
    * @param objs
2508
    *                an array of available data objects
2509
    * @return false if the algorithm requires more raster layers than the ones in the data objects array. True if they suffice
2510
    */
2511
   public boolean meets3DRasterRequirements(final Object[] objs) {
2512

    
2513
      if (objs == null) {
2514
         return false;
2515
      }
2516

    
2517
      if (requires3DRasterLayers()) {
2518
         for (final Object element : objs) {
2519
            if (element instanceof I3DRasterLayer) {
2520
               return true;
2521
            }
2522
         }
2523
         return false;
2524
      }
2525
      else {
2526
         return true;
2527
      }
2528

    
2529
   }
2530

    
2531

    
2532
   /**
2533
    * Returns false if there are not enough vector data in the given array to run the algorithm
2534
    *
2535
    * @param objs
2536
    *                an array of available data objects
2537
    * @return false if the algorithm requires more (or different, i.e other shape type) vector layers than the ones in the data
2538
    *         objects array. True if they suffice
2539
    */
2540
   public boolean meetsVectorRequirements(final Object[] objs) {
2541

    
2542
      boolean bPolygonLayers = false;
2543
      boolean bLineLayers = false;
2544
      boolean bPointLayers = false;
2545
      boolean bVectorLayers = false;
2546

    
2547
      if (objs == null) {
2548
         return false;
2549
      }
2550

    
2551
      if (requiresVectorLayers()) {
2552
         for (final Object element : objs) {
2553
            if (element instanceof IVectorLayer) {
2554
               switch (((IVectorLayer) element).getShapeType()) {
2555
                  case IVectorLayer.SHAPE_TYPE_POINT:
2556
                     bPointLayers = true;
2557
                     bVectorLayers = true;
2558
                     break;
2559
                  case IVectorLayer.SHAPE_TYPE_LINE:
2560
                     bLineLayers = true;
2561
                     bVectorLayers = true;
2562
                     break;
2563
                  case IVectorLayer.SHAPE_TYPE_POLYGON:
2564
                     bPolygonLayers = true;
2565
                     bVectorLayers = true;
2566
                     break;
2567
               }
2568
            }
2569
         }
2570

    
2571
         if ((requiresPointVectorLayers() && !bPointLayers) || (requiresLineVectorLayers() && !bLineLayers)
2572
             || (requiresPolygonVectorLayers() && !bPolygonLayers)) {
2573
            return false;
2574
         }
2575
         else {
2576
            return bVectorLayers;
2577
         }
2578
      }
2579
      else {
2580
         return true;
2581

    
2582
      }
2583

    
2584

    
2585
   }
2586

    
2587

    
2588
   /**
2589
    * Returns false if there are not enough table objects in the given array to run the algorithm
2590
    *
2591
    * @param objs
2592
    *                an array of available data objects
2593
    * @return false if the algorithm requires more tables than the ones in the data objects array. True if they suffice
2594
    */
2595
   public boolean meetsTableRequirements(final Object[] objs) {
2596

    
2597
      if (objs == null) {
2598
         return false;
2599
      }
2600

    
2601
      if (requiresTables()) {
2602
         for (final Object element : objs) {
2603
            if (element instanceof ITable) {
2604
               return true;
2605
            }
2606
         }
2607
         return false;
2608
      }
2609
      else {
2610
         return true;
2611
      }
2612

    
2613
   }
2614

    
2615

    
2616
   /**
2617
    * Returns true if the algorithm could be executed with the given data objects.
2618
    *
2619
    * @param objs
2620
    *                an array of available data objects
2621
    * @return true if the algorithm could be executed with the given data objects.
2622
    */
2623
   public boolean meetsDataRequirements(final Object[] objs) {
2624

    
2625
      if (objs == null) {
2626
         return false;
2627
      }
2628

    
2629
      return meets3DRasterRequirements(objs) && meetsRasterRequirements(objs) && meetsVectorRequirements(objs)
2630
             && meetsTableRequirements(objs);
2631

    
2632
   }
2633

    
2634

    
2635
   /**
2636
    * Returns true if the algorithm parameters have correct values.
2637
    *
2638
    * @return true if the algorithm parameters have correct values
2639
    */
2640
   public boolean hasCorrectParameterValues() {
2641

    
2642
      return m_Parameters.areParameterValuesCorrect();
2643
   }
2644

    
2645

    
2646
   /**
2647
    * Returns true if the extent has been set automatically by the algorithm, false if it was introduced by the user
2648
    *
2649
    * @return true if the extent has been set automatically by the algorithm, false if it was introduced by the user
2650
    */
2651
   public boolean isAutoExtent() {
2652
      return m_bIsAutoExtent;
2653
   }
2654

    
2655

    
2656
   /**
2657
    * Return true if the algorithm can define the output extent from its required input layers. False otherwise.
2658
    *
2659
    * @return true if the algorithm can define the output extent from its required input layers. False otherwise.
2660
    */
2661
   public boolean canDefineOutputExtentFromInput() {
2662

    
2663
      if (m_OutputObjects.get3DRasterLayersCount() != 0) {
2664
         return requires3DRasterLayers();
2665
      }
2666

    
2667
      if (m_OutputObjects.getRasterLayersCount() != 0) {
2668
         return requiresRasterLayers() || requires3DRasterLayers();
2669
      }
2670

    
2671
      if (m_OutputObjects.getVectorLayersCount() != 0) {
2672
         return requiresRasterLayers() || requires3DRasterLayers() || requiresVectorLayers();
2673
      }
2674

    
2675
      return true;
2676

    
2677
   }
2678

    
2679

    
2680
   /**
2681
    * Until we find a way of automating this, 3d algorithms should overwrite this method to return true. Otherwise, it will return
2682
    * false by default. This method is used to know whether to show a 3D Analysis Extent definition panel in the algorithm dialog
2683
    * or a regular 2D one
2684
    *
2685
    * @return true if the algorithm takes 3D inputs or produces 3D output
2686
    */
2687
   public boolean is3D() {
2688

    
2689
      return false;
2690

    
2691
   }
2692

    
2693

    
2694
   /**
2695
    * returns the crs used by the algorithm to produces its outputs
2696
    *
2697
    * @return the crs used by the algorithm to produces its outputs;
2698
    */
2699
   public Object getOutputCRS() {
2700

    
2701
      return m_CRS;
2702

    
2703
   }
2704

    
2705

    
2706
   /**
2707
    * Returns true if the algorithm should be shown in a SEXTANTE component, false otherwise. Use this to programatically hide
2708
    * algorithms if you do not want them to be shown and used for some reason.
2709
    *
2710
    * @return true if the algorithm should be shown in a SEXTANTE component, false otherwise.
2711
    */
2712
   public boolean isActive() {
2713

    
2714
      return true;
2715

    
2716
   }
2717

    
2718

    
2719
   /**
2720
    * Changes the attribute name if this name is in the array.
2721
    *
2722
    * @param name
2723
    * @param size
2724
    * @param attrNames
2725
    * @return
2726
    */
2727
   protected String checkAttrName(String name, int size, String[] attrNames) {
2728
           return ShapesTools.checkAttrName(name, size, attrNames);
2729
        }
2730

    
2731
        protected void initializeDefaultValues(final Class<?>[] types,
2732
                        final Object[] resultValues) {
2733
                for (int j = 0; j < types.length; j++) {
2734
                        if (String.class.isAssignableFrom(types[j])){
2735
                                resultValues[j] = "";
2736
                        } else if (Number.class.isAssignableFrom(types[j])){
2737
                                resultValues[j] = 0;
2738
                        } else if (Boolean.class.isAssignableFrom(types[j])){
2739
                                resultValues[j] = false;
2740
                        }
2741
                }
2742
        }
2743

    
2744

    
2745

    
2746
}