Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / expressionevaluator / impl / function / dataaccess / UpdateFunction.java @ 46517

History | View | Annotate | Download (7.95 KB)

1 44738 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.expressionevaluator.impl.function.dataaccess;
25
26 44750 jjdelcerro
import java.util.ArrayList;
27 45199 jjdelcerro
import java.util.HashMap;
28 44738 jjdelcerro
import java.util.List;
29 45199 jjdelcerro
import java.util.Map;
30 44738 jjdelcerro
import org.apache.commons.lang3.Range;
31 44750 jjdelcerro
import org.apache.commons.lang3.tuple.ImmutablePair;
32
import org.apache.commons.lang3.tuple.Pair;
33
import org.gvsig.expressionevaluator.Code;
34 44738 jjdelcerro
import org.gvsig.expressionevaluator.Codes;
35
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
36
import org.gvsig.expressionevaluator.Interpreter;
37 44750 jjdelcerro
import org.gvsig.expressionevaluator.Optimizer;
38
import org.gvsig.expressionevaluator.SymbolTable;
39 44738 jjdelcerro
import org.gvsig.expressionevaluator.impl.DALFunctions;
40
import org.gvsig.fmap.dal.DALLocator;
41
import org.gvsig.fmap.dal.DataManager;
42 44748 jjdelcerro
import static org.gvsig.fmap.dal.DataManager.FUNCTION_SELECT;
43 44738 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
44
import org.gvsig.fmap.dal.feature.Feature;
45
import org.gvsig.fmap.dal.feature.FeatureQuery;
46
import org.gvsig.fmap.dal.feature.FeatureStore;
47 44752 jjdelcerro
import org.gvsig.expressionevaluator.Code.Callable;
48 45199 jjdelcerro
import org.gvsig.expressionevaluator.CodeBuilder;
49
import org.gvsig.expressionevaluator.ExpressionUtils;
50 44856 jjdelcerro
import org.gvsig.expressionevaluator.spi.AbstractFunction;
51 45199 jjdelcerro
import static org.gvsig.fmap.dal.DataManager.FUNCTION_UPDATE;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.FeatureSet;
54 44738 jjdelcerro
55
/**
56
 *
57
 * @author jjdelcerro
58
 */
59 45127 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
60 45199 jjdelcerro
public class UpdateFunction
61
        extends AbstractFunction
62
        implements Optimizer.FunctionOptimizer {
63 44738 jjdelcerro
64 45199 jjdelcerro
    public UpdateFunction() {
65
        super(DALFunctions.GROUP_DATA_ACCESS,
66
                FUNCTION_UPDATE,
67
                Range.is(6),
68
                "bla bla bla",
69
                "UPDATE {{tablename}} SET column1 = exp1, column2 = exp2, ... WHERE expression;"
70
        );
71
    }
72 44738 jjdelcerro
73 45199 jjdelcerro
    @Override
74
    public boolean isHidden() {
75
        return false;
76
    }
77 44738 jjdelcerro
78 45199 jjdelcerro
    @Override
79
    public boolean allowConstantFolding() {
80
        return false;
81
    }
82 44738 jjdelcerro
83 45199 jjdelcerro
    @Override
84
    public boolean useArgumentsInsteadObjects() {
85
        return true;
86
    }
87 44738 jjdelcerro
88 45199 jjdelcerro
    @Override
89
    public Object call(Interpreter interpreter, Object[] args) throws Exception {
90
        throw new UnsupportedOperationException();
91 44750 jjdelcerro
    }
92 44738 jjdelcerro
93 45199 jjdelcerro
    private static final int TABLE = 0;
94
    private static final int WHERE = 1;
95
96
    @Override
97
    public Object call(Interpreter interpreter, Codes args) throws Exception {
98
        // UPDATE( store, where, column1, column2, column3, exp1, exp2, exp3)
99
        // indices 0      1      2        3        4        5     6     7
100
        // num_columns = (args.size()-2)/2 --> (8-2)/2 --> 3
101
        // first_column = 2
102
        // first_exp = num_columns +2 --> 5
103
104
        SymbolTable symbolTable = interpreter.getSymbolTable();
105
106
        int num_columns = (args.size() - 2) / 2;
107
        int first_column = 2;
108
        int first_exp = num_columns + 2;
109
110
        Code.Identifier storeName = (Code.Identifier) args.get(TABLE);
111
        Code where = args.get(WHERE);
112
        if (where.code() == Code.CONSTANT) {
113
            if (((Code.Constant) where).value() == null) {
114
                where = null;
115
            }
116 45117 jjdelcerro
        }
117 45199 jjdelcerro
        Map<String, Code> values = new HashMap<>();
118
        for (int i = 0; i < num_columns; i++) {
119
            Code.Identifier column = (Code.Identifier) args.get(first_column + i);
120
            Code exp = args.get(first_exp + i);
121
            values.put(column.name(), exp);
122 44750 jjdelcerro
        }
123 45199 jjdelcerro
124
        try {
125
            DataStore store = this.getStore(storeName.name());
126
            if (store == null) {
127
                throw new ExpressionRuntimeException("Cant locate the store '" + storeName + "' in function '" + FUNCTION_SELECT + "'.");
128
            }
129
            if (!(store instanceof FeatureStore)) {
130
                throw new ExpressionRuntimeException("The store'" + storeName + "' is not valid for function '" + FUNCTION_SELECT + "', a FeatureStore is required.");
131
            }
132
            FeatureStore featureStore = (FeatureStore) store;
133
            FeatureSet features;
134
            if (where == null) {
135
                features = featureStore.getFeatureSet();
136
            } else {
137
                where = this.replaceLocalReferences(symbolTable, where);
138 45308 fdiaz
                FeatureQuery query = featureStore.createFeatureQuery(where.toString(), (String)null, true);
139 45199 jjdelcerro
                query.retrievesAllAttributes();
140
                features = featureStore.getFeatureSet(query);
141
            }
142
            if (features == null) {
143
                return 0;
144
            }
145
            long count = 0;
146
            featureStore.edit();
147
            for (Feature feature : features) {
148
                EditableFeature ef = feature.getEditable();
149
                for (String column : values.keySet()) {
150
                    Code exp = values.get(column);
151
                    exp = this.replaceLocalReferences(symbolTable, exp);
152
                    Object value = interpreter.run(exp);
153
                    ef.set(column, value);
154
155
                    // TODO: Tener en cuenta aqui llamar a algo que no dispare el concurrent modificacion exception.
156
                    featureStore.update(ef);
157
                }
158
                count++;
159
            }
160
            featureStore.finishEditing();
161
            return count;
162
        } catch (ExpressionRuntimeException ex) {
163
            throw ex;
164
        } catch (Exception ex) {
165
            throw new ExpressionRuntimeException("Problems calling '" + FUNCTION_SELECT + "' function", ex);
166 44738 jjdelcerro
        }
167
    }
168
169 45199 jjdelcerro
    protected DataStore getStore(String storeName) {
170
        DataManager dataManager = DALLocator.getDataManager();
171
        DataStore store = dataManager.getStoresRepository().getStore(storeName);
172
        return store;
173
    }
174 44738 jjdelcerro
175 45199 jjdelcerro
    @Override
176
    public Code optimize(Optimizer optimizer, Callable caller) {
177
        return caller; // Don't optimize SELECT
178
    }
179
180
    private Code replaceLocalReferences(SymbolTable symbolTable, Code where) {
181
        try {
182
            List<Pair<Code, Code>> replaces = new ArrayList<>();
183
            CodeBuilder codeBuilder = ExpressionUtils.createCodeBuilder();
184
            Code where2 = where.clone();
185
            where2.accept((Object o) -> {
186
                if (o == null) {
187
                    return;
188
                }
189
                Code code = (Code) o;
190
                if( code.code()==Code.IDENTIFIER ) {
191
                    String id = ((Code.Identifier)code).name();
192
                    if( id.startsWith("@") ) {
193
                        replaces.add(new ImmutablePair(
194
                                code,
195
                                codeBuilder.constant(symbolTable.value(id.substring(1)))
196
                        ));
197 45117 jjdelcerro
                    }
198 44750 jjdelcerro
                }
199 45199 jjdelcerro
            });
200
201
            if (replaces.isEmpty()) {
202
                return where;
203
            }
204
            for (Pair<Code, Code> replace : replaces) {
205
                if (replace != null) {
206
                    where2.replace(replace.getLeft(), replace.getRight());
207 45117 jjdelcerro
                }
208 45199 jjdelcerro
            }
209
            return where2;
210
        } catch (Exception ex) {
211
            throw new ExpressionRuntimeException("Can't resolve local variables.", ex);
212 44750 jjdelcerro
        }
213
    }
214
215 44738 jjdelcerro
}