Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / gridCalculus / gridCalculator / FormulaParser.java @ 59

History | View | Annotate | Download (7.41 KB)

1
package es.unex.sextante.gridCalculus.gridCalculator;
2

    
3
import java.util.ArrayList;
4
import java.util.List;
5

    
6
import org.nfunk.jep.JEP;
7

    
8
import es.unex.sextante.core.ObjectAndDescription;
9
import es.unex.sextante.core.Sextante;
10
import es.unex.sextante.dataObjects.IRasterLayer;
11
import es.unex.sextante.parameters.RasterLayerAndBand;
12

    
13
public class FormulaParser {
14

    
15
   private static final int MAX_BANDS = 256;
16

    
17

    
18
   public static String prepareFormula(final String sFormula,
19
                                       final List<String> names) {
20

    
21
      int i;
22
      int iIndex;
23
      String sName;
24
      String sSubstring;
25
      final StringBuffer sb = new StringBuffer(sFormula);
26
      iIndex = 0;
27
      while ((iIndex = sb.indexOf("|", iIndex)) != -1) {
28
         if ((sb.indexOf("|", iIndex - 1) == -1) && (sb.indexOf("|", iIndex + 1) == -1)) {
29
            sb.delete(iIndex, iIndex + 1);
30
            sb.insert(iIndex, " Band ");
31
            iIndex = 0;
32
         }
33
         else {
34
            iIndex++;
35
         }
36
      }
37
      iIndex = 0;
38
      for (i = 0; i < names.size(); i++) {
39
         sName = ((String) names.get(i)).toLowerCase();
40
         while ((iIndex = sb.indexOf(sName, iIndex)) != -1) {
41
            sSubstring = sb.substring(iIndex, Math.min(iIndex + sName.length() + " band ".length(), sb.length()));
42
            if (!sSubstring.toLowerCase().equals(sName + " band ")) {
43
               sb.delete(iIndex, iIndex + sName.length());
44
               sb.insert(iIndex, sName + " Band 1");
45
               iIndex = 0;
46
            }
47
            else {
48
               iIndex++;
49
            }
50
         }
51
      }
52

    
53
      return sb.toString();
54

    
55
   }
56

    
57
   /**
58
    * Converts the name of a layer in a normalized name. 
59
    * @param name
60
    * @return
61
    */
62
   public static String getNormalizedName(String name) {
63
           //If the name starts with a number adds a prefix
64
           String pattern = "^[\\d].*";
65
           if(name != null && name.matches(pattern)) {
66
               name = "prefix_" + name; 
67
       }
68
           return name;
69
   }
70
   
71
   /**
72
    * Replace all variables in a formula by a normalized name
73
    * @param formula
74
    * @param layerName
75
    * @param normalizedName
76
    * @return
77
    */
78
   public static String replaceVariables(String formula, String layerName, String normalizedName) {
79
           if(!normalizedName.equals(layerName)) {
80
                   return formula.replaceAll(layerName, normalizedName);
81
       }
82
           return formula;
83
   }
84

    
85
   public static List<RasterLayerAndBand> getBandsFromFormula(String sFormula,
86
                                               final List<IRasterLayer> layers) {
87

    
88
      int i, j;
89

    
90
      IRasterLayer layer;
91
      String sLayerName;
92
      final List<RasterLayerAndBand> array = new ArrayList<RasterLayerAndBand>();
93
      final List<String> names = new ArrayList<String>();
94
      final JEP jep = new JEP();
95
      jep.addStandardConstants();
96
      jep.addStandardFunctions();
97
      
98
      for (i = 0; i < layers.size(); i++) {
99
         layer = (IRasterLayer) layers.get(i);
100
         String layerName = layer.getName();
101
         String normalizedLayerName = getNormalizedName(layerName);
102
         sFormula = replaceVariables(sFormula, layerName, normalizedLayerName);
103
         names.add(normalizedLayerName);
104
      }
105
      
106
      sFormula = FormulaParser.prepareFormula(sFormula.toLowerCase(), names);
107
      sFormula = sFormula.toLowerCase().replaceAll(" ", "");
108
      sFormula = sFormula.replaceAll("\\[", "_");
109
      sFormula = sFormula.replaceAll("\\]", "_");
110
      sFormula = FormulaParser.replaceDots(sFormula);
111
      for (i = 0; i < layers.size(); i++) {
112
         layer = (IRasterLayer) layers.get(i);
113
         for (j = 0; j < layer.getBandsCount(); j++) {
114
            sLayerName = layer.getName() + " Band " + Integer.toString(j + 1);
115
            sLayerName = sLayerName.toLowerCase();
116
            sLayerName = sLayerName.replaceAll(" ", "");
117
            sLayerName = sLayerName.replaceAll("\\[", "_");
118
            sLayerName = sLayerName.replaceAll("\\]", "_");
119
            sLayerName = FormulaParser.replaceDots(sLayerName);
120
            sLayerName = getNormalizedName(sLayerName);
121
            if (sFormula.lastIndexOf(sLayerName) != -1) {
122
               array.add(new RasterLayerAndBand(layer, j));
123
               jep.addVariable(sLayerName, 0.0);
124
            }
125
         }
126

    
127
      }
128

    
129
      jep.parseExpression(sFormula);
130

    
131
      if (jep.hasError()) {
132
         Sextante.addErrorToLog(jep.getErrorInfo());
133
         return null;
134
      }
135

    
136
      if (array.size() == 0) {
137
         return null;
138
      }
139

    
140
      return array;
141
   }
142

    
143

    
144
   public static List<String> getBandsFromFormulaForModeler(String sFormula,
145
                                                         final ObjectAndDescription[] layers,
146
                                                         final ObjectAndDescription[] numerical) {
147
      int i, j;
148

    
149
      ObjectAndDescription oad;
150
      String sLayerName, sName;
151
      final List<String> array = new ArrayList<String>();
152
      final List<String> names = new ArrayList<String>();
153
      final JEP jep = new JEP();
154
      jep.addStandardConstants();
155
      jep.addStandardFunctions();
156

    
157
      for (i = 0; i < layers.length; i++) {
158
         oad = layers[i];
159
         String layerName = (String) oad.getObject();
160
         String normalizedLayerName = getNormalizedName(layerName);
161
         sFormula = replaceVariables(sFormula, layerName, normalizedLayerName);
162
         names.add(layerName);
163
      }
164

    
165
      for (i = 0; i < numerical.length; i++) {
166
         jep.addVariable(((String) numerical[i].getObject()).toLowerCase(), 0.0);
167
      }
168

    
169
      sFormula = FormulaParser.prepareFormula(sFormula.toLowerCase(), names);
170
      sFormula = sFormula.toLowerCase().replaceAll(" ", "");
171
      sFormula = sFormula.replaceAll("\\[", "_");
172
      sFormula = sFormula.replaceAll("\\]", "_");
173
      sFormula = sFormula.replaceAll("\\:", "_");
174
      sFormula = sFormula.replaceAll("\"", "_");
175
      sFormula = FormulaParser.replaceDots(sFormula);
176
      for (i = 0; i < names.size(); i++) {
177
         sName = names.get(i);
178
         for (j = 0; j < MAX_BANDS; j++) {
179
            sLayerName = sName + " Band " + Integer.toString(j + 1);
180
            sLayerName = sLayerName.toLowerCase();
181
            sLayerName = sLayerName.replaceAll(" ", "");
182
            sLayerName = sLayerName.replaceAll("\\[", "_");
183
            sLayerName = sLayerName.replaceAll("\\]", "_");
184
            sLayerName = sLayerName.replaceAll("\\:", "_");
185
            sLayerName = sLayerName.replaceAll("\"", "_");
186
            sLayerName = FormulaParser.replaceDots(sLayerName);
187
            sLayerName = getNormalizedName(sLayerName);
188
            if (sFormula.lastIndexOf(sLayerName) != -1) {
189
               array.add((String) layers[i].getObject());
190
               jep.addVariable(sLayerName, 0.0);
191
            }
192
         }
193

    
194
      }
195

    
196
      jep.parseExpression(sFormula);
197

    
198
      if (jep.hasError()) {
199
         return null;
200
      }
201

    
202
      if (array.size() == 0) {
203
         return null;
204
      }
205

    
206
      return array;
207

    
208
   }
209

    
210

    
211
   public static String replaceDots(final String s) {
212

    
213
      char c, c2;
214
      StringBuffer sb = new StringBuffer(s);
215
      for (int i = 0; i < sb.length() - 1; i++) {
216
         c = sb.charAt(i);
217
         c2 = sb.charAt(i + 1);
218
         if ((c == '.') && !Character.isDigit(c2)) {
219
            sb = sb.deleteCharAt(i);
220
         }
221
      }
222

    
223
      return sb.toString();
224

    
225
   }
226

    
227
}