no message

This commit is contained in:
2024-10-10 23:57:36 +03:00
parent cde3e1da42
commit a11b7711f7
209 changed files with 380 additions and 218 deletions

View File

@@ -0,0 +1,32 @@
package Common.Passes;
import Common.Database.Objects.DBObject;
public abstract class AddObjectPass<D extends DBObject> extends ObjectPass<D> {
public AddObjectPass(Class<D> d_in) {
super(d_in);
}
public Class<? extends DBObject> getOwner() {
return null;
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = d.newInstance();
return
((getOwner() == null) || (getDb().tables.get(getOwner()).CheckCurrent(Log))) &&
fillObjectFields();
}
protected boolean fillObjectFields() throws Exception {
return getTable().ShowAddObjectDialog(target);
}
@Override
public String getIconPath() {
return "/icons/RedAdd.png";
}
@Override
protected void body() throws Exception {
getDb().Insert(target);
}
@Override
protected void showDone() throws Exception {
getTable().ShowUI(target.getPK());
}
}

View File

@@ -0,0 +1,55 @@
package Common.Passes;
import Common.Database.Objects.DBObject;
public abstract class DeleteObjectPass<D extends DBObject> extends ObjectPass<D> {
public DeleteObjectPass(Class<D> d_in) {
super(d_in);
}
@Override
public String getIconPath() {
return "/icons/Delete.png";
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = (D) getTable().getCurrent();
return getTable().CheckCurrent(Log) && getTable().ShowDeleteObjectDialog(target);
}
//Очищаем все связанные таблицы, чтобы не допустить перерисовки во время удаления объекта.
@Override
protected void showPreparation() throws Exception {
getTable().ClearUI();
for (Class dep : getTable().getFKDependencies().keySet()) {
switch (getTable().getFKDependencies().get(dep).data) {
case NONE:
case DROP:
break;
case DELETE:
getDb().tables.get(dep).ClearUI();
break;
}
}
}
@Override
protected void body() throws Exception {
getDb().Delete(target);
for (Class dep : getTable().getFKDependencies().keySet()) {
switch (getTable().getFKDependencies().get(dep).data) {
case NONE:
break;
case DROP:
getDb().DropByFK(target, dep);
break;
case DELETE:
getDb().DeleteByFK(target, dep);
break;
}
}
}
//тут именно на финише, чтобы в любом случае вся таблица всегда была видна.
@Override
protected void performFinish() throws Exception {
getTable().ShowUI();
for (Class dep : getTable().getFKDependencies().keySet()) {
getDb().tables.get(dep).RefreshUI();
}
}
}

View File

@@ -0,0 +1,26 @@
package Common.Passes;
import Common.Database.Objects.DBObject;
public abstract class EditObjectPass<D extends DBObject> extends ObjectPass<D> {
public EditObjectPass(Class<D> d_in) {
super(d_in);
}
@Override
public String getIconPath() {
return "/icons/Edit.png";
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = (D) getTable().getCurrent();
return getTable().CheckCurrent(Log) && getTable().ShowEditObjectDialog(target);
}
@Override
protected void body() throws Exception {
getDb().Update(target);
}
@Override
protected void showFinish() throws Exception {
getTable().ShowUI(target.getPK());
for (Class dep : getTable().getFKDependencies().keySet())
getDb().tables.get(dep).RefreshUI();
}
}

View File

@@ -0,0 +1,19 @@
package Common.Passes;
import Common.Database.Objects.DBObject;
import Common.Database.Tables.DBTable;
import Common.Database.Database;
import Common.Passes.Pass;
public abstract class ObjectPass<D extends DBObject> extends Pass<D> {
protected Class<D> d; //класс объектов.
public ObjectPass(Class<D> d_in) {
d = d_in;
}
protected abstract Database getDb(); //источник данных
public DBTable getTable() {
return getDb().tables.get(d);
} //таблица в источнике данных
@Override
public String getButtonText() {
return "";
}
}

445
src/Common/Passes/Pass.java Normal file
View File

@@ -0,0 +1,445 @@
package Common.Passes;
import Common.Current_;
import Common.Utils.CommonUtils;
import Common.Utils.Stopwatch;
import Common.Utils.TextLog;
import Common.Visual.CommonUI;
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.GlobalData.GlobalDatabase;
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 static Vector<Pass> FAPasses = new Vector<>();
//</editor-fold>
//-
public static LinkedHashMap<PassCode, Pass> passes = new LinkedHashMap<>();
public PassStats stats = null;
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 static Throwable getCauseRec(Throwable ex) {
Throwable cause = ex.getCause();
return (cause == null) ? ex : getCauseRec(cause);
}
public static void setPassesControlsVisible(boolean flag, PassCode... codes_in) {
for (PassCode code_in : codes_in)
passes.get(code_in).setControlsVisible(flag);
}
//важно. вызывать только если есть интерфейс. passstats делать частью общей бд.пусть будут.
public static void CheckAllStats() throws Exception {
for (Pass pass : FAPasses) {
if (!((GlobalDatabase) CommonUtils.db).passStats.Data.containsKey(pass.code().toString()))
CommonUtils.db.Insert(pass.stats = new PassStats(pass.code().toString()));
else pass.stats = ((GlobalDatabase) CommonUtils.db).passStats.Data.get(pass.code().toString());
}
FAPasses.sort(new SortPassesByStats());
}
public static void CreateAll() {
for (PassCode code : PassCode.values()) {
try {
Class<?> clazz = Class.forName("Visual_DVM_2021.Passes.All." + code.toString());
Pass pass = ((Pass) clazz.newInstance());
passes.put(code, pass);
if (pass.hasStats())
FAPasses.add(pass);
} catch (Exception ex) {
CommonUtils.MainLog.PrintException(ex);
}
}
}
//<editor-fold desc="Интерфейс">
//https://www.delftstack.com/ru/howto/java/java-resize-image/
public String getIconPath() {
return null;
}
public Icon getTabIcon() {
return CommonUtils.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() {
}
protected boolean hasStats() {
return false;
}
public void UpdateStatsIfNeed() {
if (hasStats()) {
stats.Inc();
try {
CommonUtils.db.Update(stats);
FAPasses.sort(new SortPassesByStats());
if (Current.HasProject())
UI.fastAccessMenuBar.Refresh();
} catch (Exception ex) {
CommonUtils.MainLog.PrintException(ex);
}
}
}
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 (CommonUI.isActive())
showCanNotStart();
}
protected void PerformPreparation() throws Exception {
performPreparation();
if (CommonUI.isActive())
showPreparation();
}
private void PerformFinish() throws Exception {
performFinish();
//-
if (CommonUI.isActive())
showFinish();
}
private void PerformDone() throws Exception {
performDone();
//-
if (CommonUI.isActive())
showDone();
}
private void PerformFail() throws Exception {
performFail();
//-
if (CommonUI.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 = passes.get(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() &&
!CommonUI.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()
) {
CommonUI.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 {
CommonUI.Info("Проход " + CommonUtils.Brackets(getDescription()) + " не разрешено прерывать.");
}
public boolean needsConfirmations() {
return false;
}
//</editor-fold>
//-
protected void CheckException(Exception ex) {
if (ex instanceof PassException) {
Log.Writeln_(ex.getMessage());
} else
CommonUtils.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())
CommonUtils.MainLog.Print(getDescription() + " стартует..");
timer.Start();
//------------------------------->
try {
if (CommonUI.isActive()) FocusBeforeStart();
if (canStart(args)) {
PerformPreparation();
//todo тут должна быть вилка на анимацию?
if (CommonUI.isActive() && needsAnimation()) {
animation_sem = new Semaphore(1);
animation_sem.acquire();
//---
form = null;
Current_.set(Current.PassForm, null);
System.gc();
//--
Current_.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) {
CommonUtils.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;
CommonUtils.MainLog.PrintException(ex);
}
//------------------------------->
timer.Stop();
if (!getDescription().isEmpty()) {
CommonUtils.MainLog.Print(
getDescription() +
" окончен за " + timer.Print() +
" состояние " + CommonUtils.Brackets(state.getDescription())
);
if (!Log.isEmpty() && CommonUI.isActive())
CommonUI.Error(
"проход " + CommonUtils.Brackets(getDescription()) + "\n" + state.getDescription() + "\n\n" +
Log.toString());
}
//------------------------------->
return isDone();
}
//--
public void ShowSapforMessage(String message) {
if (CommonUI.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(CommonUtils.Brackets(message));
}
public void ShowMessage1(String message) {
if (form != null)
form.fields.Label1.setText((message.length() > 1) ? message : "");
else System.out.println(CommonUtils.Brackets(message));
}
public void ShowMessage2(String message) {
if (form != null)
form.fields.Label2.setText((message.isEmpty() ? "" : message));
else System.out.println(CommonUtils.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);
}
}

View File

@@ -0,0 +1,7 @@
package Common.Passes;
public class PassException extends Exception {
//штатное исключение
public PassException(String text) {
super(text);
}
}

View File

@@ -0,0 +1,33 @@
package Common.Passes;
public enum PassState {
Inactive,
Interrupted,
CantStart,
Failed,
Crushed,
Done,
ExternalCrushed //исключение за рамками Action. неординарная ситуация.
;
public String getDescription() {
switch (this) {
case ExternalCrushed:
return "внешнее исключение";
case Inactive:
return "неактивен";
//-----------------------------------------
case Interrupted:
return "остановлен пользователем";
case CantStart:
return "не может быть выполнен";
case Failed:
return "завершён с ошибками";
case Crushed:
return "завершён с исключением";
case Done:
return "успешно выполнен";
default:
break;
}
return "";
}
}

View File

@@ -0,0 +1,9 @@
package Common.Passes;
import Common.Passes.Pass;
import java.util.Comparator;
public class SortPassesByStats implements Comparator<Common.Passes.Pass> {
public int compare(Common.Passes.Pass p1, Pass p2) {
return p2.stats.Usages - p1.stats.Usages;
}
}