Files
VisualSapfor/src/Common/Passes/Pass.java

410 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package Common.Passes;
import Common.Utils.Utils_;
import Common.Utils.Stopwatch;
import Common.Utils.TextLog;
import Common.Visual.UI_;
import Visual_DVM_2021.PassStats.PassStats;
import Visual_DVM_2021.Passes.PassCode;
import Visual_DVM_2021.Passes.UI.PassForm;
import _VisualDVM.Current;
import _VisualDVM.Global;
import _VisualDVM.Visual.Controls.PassButton;
import _VisualDVM.Visual.Controls.PassControl;
import _VisualDVM.Visual.Menus.StablePassMenuItem;
import _VisualDVM.Visual.UI;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.LinkedHashMap;
import java.util.Stack;
import java.util.Vector;
import java.util.concurrent.Semaphore;
public class Pass<T> {
public int callsCount = 0; //число вызовов прохода за текущий сеанс визуализатора.
public T target; //главный аргумент.
public PassState state = PassState.Inactive; //текущее состояние прохода.
public Semaphore animation_sem;
//--------------
public Vector<PassControl> controls = new Vector<>();
public TextLog Log; //внутренний журнал прохода.
protected boolean interrupt;
protected SwingWorker dispatcher = null;
private PassForm form = null;
protected JMenuItem menuItem = null;
private JButton button = null;
private JButton tabButton = null;
private Exception last_error; //последнее пойманное исключение выполнения.
//->>
public Throwable getCauseRec(Throwable ex) {
Throwable cause = ex.getCause();
return (cause == null) ? ex : getCauseRec(cause);
}
//<editor-fold desc="Интерфейс">
//https://www.delftstack.com/ru/howto/java/java-resize-image/
public String getIconPath() {
return null;
}
public Icon getTabIcon() {
return Utils_.getTabIcon(getIconPath());
}
public AbstractAction getControlAction() {
return new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
UpdateStatsIfNeed();
Do();
}
};
}
public String getButtonText() {
return getDescription();
}
public JMenuItem createMenuItem() {
if (menuItem == null)
menuItem = new StablePassMenuItem(this);
return menuItem;
}
public JButton createButton() {
if (button == null)
button = new PassButton(this);
return button;
}
public JButton createTabButton() {
if (tabButton == null)
tabButton = new PassButton(this, true);
return tabButton;
}
public void setControlsEnabled(boolean flag) {
for (PassControl control : controls)
control.setEnabled(flag);
}
public void setControlsVisible(boolean flag) {
for (PassControl control : controls)
control.setVisible(flag);
}
public void setControlsToolTipText(String text) {
for (PassControl control : controls)
control.setToolTipText(text);
}
protected void FocusResult() {
}
public boolean hasStats() {
return false;
}
public void UpdateStatsIfNeed() {
if (hasStats()) {
try {
Global.mainModule.getDb().passStats.IncPassStat(code());
} catch (Exception ex) {
Utils_.MainLog.PrintException(ex);
}
UI.fastAccessMenuBar.Refresh();
}
}
public PassCode code() {
return PassCode.valueOf(getClass().getSimpleName());
}
public boolean isDone() {
return state == PassState.Done;
}
public void setDone() {
state = PassState.Done;
}
public String getDescription() {
return code().getDescription();
}
public String getStartDescription() {
return getDescription();
}
protected void FocusBeforeStart() {
//отображение вкладок.
}
//-
//объединение старых методов InitArgs и CanStart. зачастую семантика у них пересекалась.
protected boolean canStart(Object... args) throws Exception {
return true;
}
//-
protected void body() throws Exception {
}
protected boolean validate() {
return true;
}
//-
protected void performCanNotStart() throws Exception {
}
protected void showCanNotStart() throws Exception {
}
protected void performPreparation() throws Exception {
}
protected void showPreparation() throws Exception {
}
protected void performFinish() throws Exception {
}
protected void showFinish() throws Exception {
}
protected void performDone() throws Exception {
}
protected void showDone() throws Exception {
}
protected void performFail() throws Exception {
}
protected void showFail() throws Exception {
}
//-
private void PerformCanNotStart() throws Exception {
performCanNotStart();
if (UI_.isActive())
showCanNotStart();
}
protected void PerformPreparation() throws Exception {
performPreparation();
if (UI_.isActive())
showPreparation();
}
private void PerformFinish() throws Exception {
performFinish();
//-
if (UI_.isActive())
showFinish();
}
private void PerformDone() throws Exception {
performDone();
//-
if (UI_.isActive())
showDone();
}
private void PerformFail() throws Exception {
performFail();
//-
if (UI_.isActive())
showFail();
}
//------
protected PassCode necessary() {
return null;
}
protected boolean resetsNecessary() {
return false;
}
public void Reset() {
if (state == PassState.Done)
state = PassState.Inactive;
}
//------
protected void createStack_r(Stack<Pass> ToDo, Vector<String> ToPrint) {
ToDo.push(this);
if (needsConfirmations() // если UI нет, сюда он не дойдет.
) {
ToPrint.add(this.getStartDescription());
}
if (necessary() != null) {
Pass next = Global.mainModule.getPass(necessary());
if (resetsNecessary() || !next.isDone())
next.createStack_r(ToDo, ToPrint);
}
}
public boolean Do(Object... args) {
Stack<Pass> ToDo = new Stack<>();
Vector<String> ToPrint = new Vector<>();
createStack_r(ToDo, ToPrint);
if (Global.properties.ConfirmPassesStart && !ToPrint.isEmpty() &&
!UI_.Question("Выполнить проход(ы):\n" + String.join("\n", ToPrint))
) return false;
while (ToDo.size() > 1) {
if (!ToDo.pop().start()) return false;
}
if (start(args)) {
if (Global.properties.FocusPassesResult)
FocusResult();
//-
if (Global.properties.ShowPassesDone && !ToPrint.isEmpty()
) {
UI_.Info("Проход(ы)\n\n" + String.join("\n", ToPrint) +
"\nуспешно выполнен(ы)!");
}
//-
return true;
}
return false;
}
//-
//<editor-fold desc="Анимация">
protected boolean needsAnimation() {
return false;
}
public void Interrupt() throws Exception {
UI_.Info("Проход " + Utils_.Brackets(getDescription()) + " не разрешено прерывать.");
}
public boolean needsConfirmations() {
return false;
}
//</editor-fold>
//-
protected void CheckException(Exception ex) {
if (ex instanceof PassException) {
Log.Writeln_(ex.getMessage());
} else
Utils_.MainLog.PrintException(ex);
}
public boolean start(Object... args) {
//------------------------------->
interrupt = false;
callsCount++;
Stopwatch timer = new Stopwatch();
state = PassState.Inactive;
last_error = null;
target = null;
Log = new TextLog();
if (!getDescription().isEmpty())
Utils_.MainLog.Print(getDescription() + " стартует..");
timer.Start();
//------------------------------->
try {
if (UI_.isActive()) FocusBeforeStart();
if (canStart(args)) {
PerformPreparation();
//todo тут должна быть вилка на анимацию?
if (UI_.isActive() && needsAnimation()) {
animation_sem = new Semaphore(1);
animation_sem.acquire();
//---
form = null;
Global.mainModule.set(Current.PassForm, null);
System.gc();
//--
Global.mainModule.set(Current.PassForm, form = new PassForm(this));
dispatcher = new SwingWorker() {
@Override
protected Object doInBackground() {
// UI.Print(DebugPrintLevel.Passes, "фоновое выполнение началось");
try {
body();
} catch (Exception ex) {
last_error = ex;
}
// UI.Print(DebugPrintLevel.Passes, "Ожидание активации окна анимации ");
//ждем пока окно откроется и освободит его.
try {
animation_sem.acquire();
} catch (InterruptedException e) {
Utils_.MainLog.PrintException(e);
}
//и уничтожаем его.
// UI.Print(DebugPrintLevel.Passes, "Окно анимации активировано.");
form.dispose();
form = null;
// UI.Print(DebugPrintLevel.Passes, "Окно анимации закрыто.");
animation_sem.release();
return null;
}
@Override
protected void done() {
//тут ничего не анализируем. события - отдельный поток. тут это не нужно
}
};
dispatcher.execute();
form.ShowDialog();
// UI.Print(DebugPrintLevel.Passes, "фоновое выполнение закончено, обработка резульатов");
if (last_error != null) {
state = PassState.Crushed;
CheckException(last_error);
}
// UI.Print(DebugPrintLevel.Passes, "OK");
dispatcher = null;
} else {
//исключения во время выполнения возможны в штатном режиме.
try {
body();
} catch (Exception ex) {
state = PassState.Crushed;//упал при выполнении.
CheckException(ex);
}
}
//---
// UI.Info(this.getClass().getSimpleName()+" +");
PerformFinish();
// UI.Info(this.getClass().getSimpleName()+" ++");
//---
if ((state != PassState.Crushed) && validate()) {
state = PassState.Done;
PerformDone();
} else {
state = PassState.Failed;
PerformFail();
}
} else {
state = PassState.CantStart;
PerformCanNotStart();
}
} catch (Exception ex) {
state = PassState.ExternalCrushed;
Utils_.MainLog.PrintException(ex);
}
//------------------------------->
timer.Stop();
if (!getDescription().isEmpty()) {
Utils_.MainLog.Print(
getDescription() +
" окончен за " + timer.Print() +
" состояние " + Utils_.Brackets(state.getDescription())
);
if (!Log.isEmpty() && UI_.isActive())
UI_.Error(
"проход " + Utils_.Brackets(getDescription()) + "\n" + state.getDescription() + "\n\n" +
Log.toString());
}
//------------------------------->
return isDone();
}
//--
public void ShowSapforMessage(String message) {
if (UI_.isActive() && form != null) {
String[] data = message.split(":");
switch (data[0]) {
case "message_1":
form.fields.Label1.setText((data.length > 1) ? data[1] : "");
break;
case "message_2":
form.fields.Label2.setText((data.length > 1) ? data[1] : "");
break;
case "progress":
form.fields.ProgressBar.setValue((data.length > 1) ? Integer.parseInt(data[1]) : 0);
break;
}
} else System.out.println(Utils_.Brackets(message));
}
public void ShowMessage1(String message) {
if (form != null)
form.fields.Label1.setText((message.length() > 1) ? message : "");
else System.out.println(Utils_.Brackets(message));
}
public void ShowMessage2(String message) {
if (form != null)
form.fields.Label2.setText((message.isEmpty() ? "" : message));
else System.out.println(Utils_.Brackets(message));
}
public void ShowProgress(int total, int current, boolean auto) {
if (form != null) {
form.lTitle.setText(getDescription() + " " + (current + 1) + "/" + total);
if (auto) {
double dp = ((double) current / total) * 100;
int p = (int) dp;
form.fields.ProgressBar.setValue(p);
}
}
}
public void ShowProgress2(int total, int current, String comment) {
if (form != null) {
form.fields.Label2.setText(comment + " " + current + "/" + total);
double dp = ((double) current / total) * 100;
int p = (int) dp;
form.fields.ProgressBar.setValue(p);
}
}
public void ShowProgressTextOnly(int total, int current, String comment) {
if (form != null)
form.lTitle.setText(form.lTitle.getText() + " : " + comment + " " + current + "/" + total);
}
}