/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.designer.action.query;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import ro.nextreports.designer.FormLoader;
import ro.nextreports.designer.Globals;
import ro.nextreports.designer.chart.ChartUtil;
import ro.nextreports.designer.persistence.ReportPersistence;
import ro.nextreports.designer.persistence.ReportPersistenceFactory;
import ro.nextreports.designer.querybuilder.DBBrowserNode;
import ro.nextreports.designer.querybuilder.DBBrowserTree;
import ro.nextreports.designer.querybuilder.DBObject;
import ro.nextreports.designer.ui.BaseDialog;
import ro.nextreports.designer.util.I18NSupport;
import ro.nextreports.designer.util.ImageUtil;
import ro.nextreports.designer.util.Show;
import ro.nextreports.designer.util.UIActivator;
import ro.nextreports.engine.Report;
import ro.nextreports.engine.util.ReportUtil;
import ro.nextreports.engine.util.StringUtil;
public class ValidateSqlsAction extends AbstractAction {
public static String VALID_SQL_PROPERTY = "VALID_SQL";
private DBObject sqlObject;
private ReportPersistence repPersist = ReportPersistenceFactory.createReportPersistence(Globals.getReportPersistenceType());
private boolean multiple;
private static final Log LOG = LogFactory.getLog(ValidateSqlsAction.class);
public ValidateSqlsAction(DBObject sqlObject) {
String text;
multiple = (sqlObject.getType() == DBObject.REPORTS_GROUP) ||
(sqlObject.getType() == DBObject.QUERIES_GROUP) ||
(sqlObject.getType() == DBObject.CHARTS_GROUP) ||
(sqlObject.getType() == DBObject.FOLDER_QUERY) ||
(sqlObject.getType() == DBObject.FOLDER_REPORT) ||
(sqlObject.getType() == DBObject.FOLDER_CHART);
if (multiple) {
text = I18NSupport.getString("sql.validation");
} else {
text = I18NSupport.getString("sql.validation.single");
}
putValue(Action.NAME, text);
putValue(Action.SMALL_ICON, ImageUtil.getImageIcon("sql_validation"));
putValue(Action.SHORT_DESCRIPTION, text);
putValue(Action.LONG_DESCRIPTION, text);
this.sqlObject = sqlObject;
}
public void actionPerformed(ActionEvent e) {
Thread executorThread = new Thread(new Runnable() {
public void run() {
UIActivator activator = new UIActivator(Globals.getMainFrame(), I18NSupport.getString("sql.validation"));
activator.start();
if (!multiple) {
try {
testSingleValidation(sqlObject, true);
} finally {
if (activator != null) {
activator.stop();
}
}
// validate all sqls
} else {
try {
final DBBrowserTree tree = Globals.getMainFrame().getQueryBuilderPanel().getTree();
final DBBrowserNode node;
if ((sqlObject.getType() == DBObject.REPORTS_GROUP) ||
(sqlObject.getType() == DBObject.QUERIES_GROUP) ||
(sqlObject.getType() == DBObject.CHARTS_GROUP) ) {
node = tree.searchNode(sqlObject.getName());
} else {
node = tree.searchNode(sqlObject.getName(), sqlObject.getAbsolutePath(), sqlObject.getType());
}
StringBuilder result = new StringBuilder();
testMultipleValidation(node, tree, result);
String message = result.toString();
if (!message.isEmpty()) {
Show.warningScroll(I18NSupport.getString("sql.invalid"), message, 10, 30, createActions(node, tree));
} else {
Show.info(I18NSupport.getString("sql.valid"));
}
} finally {
if (activator != null) {
activator.stop();
}
}
}
}
}, "NEXT : " + getClass().getSimpleName());
executorThread.start();
}
private void testMultipleValidation(DBBrowserNode node, DBBrowserTree tree, StringBuilder result) {
if (node.getChildCount() == 0) {
tree.startExpandingTree(node, false, null);
}
for (int i = 0, size = node.getChildCount(); i < size; i++) {
DBBrowserNode child = (DBBrowserNode) node.getChildAt(i);
DBObject object = child.getDBObject();
if ((object.getType() == DBObject.FOLDER_QUERY) ||
(object.getType() == DBObject.FOLDER_REPORT) ||
(object.getType() == DBObject.FOLDER_CHART)) {
testMultipleValidation(child, tree, result);
} else {
String res = testSingleValidation(object, false);
result.append(res);
}
}
}
private String testSingleValidation(DBObject obj, boolean showMessage) {
Report report = null;
if (obj.getType() == DBObject.QUERIES) {
report = repPersist.loadReport(obj.getAbsolutePath());
} else if (obj.getType() == DBObject.REPORTS) {
report = FormLoader.getInstance().load(obj.getAbsolutePath());
} else if (obj.getType() == DBObject.CHARTS) {
report = ChartUtil.loadChart(obj.getAbsolutePath()).getReport();
}
boolean error = false;
if (report != null) {
String message = Globals.getDBViewer().isValidSql(report);
StringBuilder sb = new StringBuilder();
if (message == null) {
// valid
List<Report> subreports = ReportUtil.getSubreports(report);
for (Report subreport : subreports) {
message = Globals.getDBViewer().isValidSql(subreport);
if (message != null) {
error = true;
sb.append("Subreport '").append(report.getName()).append("/").append(subreport.getName()).append("':\n").append(message).append("\n\n");
break;
}
}
} else {
sb.append("Report '").append(report.getName()).append("':\n").append(message).append("\n\n");
error = true;
}
if (error) {
obj.putProperty(VALID_SQL_PROPERTY, false);
if (showMessage) {
Show.warningScroll(I18NSupport.getString("sql.invalid"), sb.toString(), 10, 30, createActions(obj));
}
} else {
obj.putProperty(VALID_SQL_PROPERTY, true);
if (showMessage) {
Show.info(I18NSupport.getString("sql.valid"));
}
}
return sb.toString();
}
return "";
}
private List<Action> createActions (final DBBrowserNode node, final DBBrowserTree tree) {
Action replace = new AbstractAction(I18NSupport.getString("validate.replace")) {
@Override
public void actionPerformed(ActionEvent e) {
final FindPanel findPanel = new FindPanel();
BaseDialog dialog = new FindDialog(findPanel);
dialog.pack();
Show.centrateComponent(Globals.getMainFrame(), dialog);
dialog.setVisible(true);
if (dialog.okPressed()) {
Thread executorThread = new Thread(new Runnable() {
public void run() {
UIActivator activator = new UIActivator(Globals.getMainFrame(), I18NSupport.getString("validate.replace"));
activator.start();
try {
setEnabled(false);
String oldText = findPanel.getOldText();
String newText = findPanel.getNewText();
boolean isCaseSensitive = findPanel.isCaseSensitive();
LOG.info("Validate replace action '" + node.getDBObject().getName() + "' " + oldText + " -> " + newText);
replaceDir(node, tree, oldText, newText, isCaseSensitive);
} finally {
setEnabled(true);
if (activator != null) {
activator.stop();
}
Show.info(I18NSupport.getString("validate.replace.finish"));
}
}
}, "NEXT : " + getClass().getSimpleName());
executorThread.start();
}
}
};
List<Action> actions = new ArrayList<Action>();
actions.add(replace);
return actions;
}
private List<Action> createActions (final DBObject object) {
Action replace = new AbstractAction(I18NSupport.getString("validate.replace")) {
@Override
public void actionPerformed(ActionEvent e) {
FindPanel findPanel = new FindPanel();
BaseDialog dialog = new FindDialog(findPanel);
dialog.pack();
Show.centrateComponent(Globals.getMainFrame(), dialog);
dialog.setVisible(true);
if (dialog.okPressed()) {
String oldText = findPanel.getOldText();
String newText = findPanel.getNewText();
boolean isCaseSensitive = findPanel.isCaseSensitive();
LOG.info("Validate replace action '" + object.getName() + "' " + oldText + " -> " + newText);
replaceFile(object, oldText, newText, isCaseSensitive);
}
}
};
List<Action> actions = new ArrayList<Action>();
actions.add(replace);
return actions;
}
private void replaceFile(DBObject obj, String oldText, String newText, boolean isCaseSensitive) {
if ((obj.getType() == DBObject.QUERIES) ||
(obj.getType() == DBObject.REPORTS) ||
(obj.getType() == DBObject.CHARTS)) {
String filePath = obj.getAbsolutePath();
Boolean validQ = (Boolean) obj.getProperty(ValidateSqlsAction.VALID_SQL_PROPERTY);
if ((validQ != null) && !validQ.booleanValue()) {
LOG.info(" --> replace file '" + filePath + "' " + oldText + " -> " + newText);
StringUtil.replaceInFile(new File(filePath), oldText, newText, isCaseSensitive);
}
}
}
private void replaceDir(DBBrowserNode node, DBBrowserTree tree, String oldText, String newText, boolean isCaseSensitive) {
if (node.getChildCount() == 0) {
tree.startExpandingTree(node, false, null);
}
for (int i = 0, size = node.getChildCount(); i < size; i++) {
DBBrowserNode child = (DBBrowserNode) node.getChildAt(i);
DBObject object = child.getDBObject();
if ((object.getType() == DBObject.FOLDER_QUERY) ||
(object.getType() == DBObject.FOLDER_REPORT) ||
(object.getType() == DBObject.FOLDER_CHART)) {
LOG.info("--> replace dir '" + object.getAbsolutePath() + "' " + oldText + " -> " + newText);
replaceDir(child, tree, oldText, newText, isCaseSensitive);
} else {
replaceFile(object, oldText, newText, isCaseSensitive);
}
}
}
}