You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/04/19 23:57:52 UTC
(cayenne) 04/06: Modeler events cleanup
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit a55dd40ed9ec1cfb373a70228941f0362a2de750
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun Apr 19 11:54:36 2026 -0400
Modeler events cleanup
1. smarter history tracking
---
.../apache/cayenne/modeler/NavigationHistory.java | 167 +++++++++
.../apache/cayenne/modeler/ProjectController.java | 299 +++-------------
.../apache/cayenne/modeler/util/CircularArray.java | 398 ---------------------
.../cayenne/modeler/util/CircularArrayTest.java | 143 --------
4 files changed, 222 insertions(+), 785 deletions(-)
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NavigationHistory.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NavigationHistory.java
new file mode 100644
index 000000000..e9268b2b6
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NavigationHistory.java
@@ -0,0 +1,167 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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 org.apache.cayenne.modeler;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.event.EmbeddableEvent;
+import org.apache.cayenne.map.event.EntityEvent;
+import org.apache.cayenne.modeler.event.display.DataMapDisplayEvent;
+import org.apache.cayenne.modeler.event.display.DataNodeDisplayEvent;
+import org.apache.cayenne.modeler.event.display.DisplayEvent;
+import org.apache.cayenne.modeler.event.display.DomainDisplayEvent;
+import org.apache.cayenne.modeler.event.display.EmbeddableDisplayEvent;
+import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
+import org.apache.cayenne.modeler.event.display.ProcedureDisplayEvent;
+import org.apache.cayenne.modeler.event.display.QueryDisplayEvent;
+import org.apache.cayenne.modeler.event.model.DataMapEvent;
+import org.apache.cayenne.modeler.event.model.DataNodeEvent;
+import org.apache.cayenne.modeler.event.model.DomainEvent;
+import org.apache.cayenne.modeler.event.model.ProcedureEvent;
+import org.apache.cayenne.modeler.event.model.QueryEvent;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Consumer;
+
+class NavigationHistory {
+ private final static int MAX_HISTORY_SIZE = 20;
+
+ private final List<DisplayEvent> history;
+ private final List<DisplayEvent> replayHistory;
+ private DisplayEvent currentEvent;
+
+ public NavigationHistory() {
+ this.history = new ArrayList<>(MAX_HISTORY_SIZE);
+ this.replayHistory = new ArrayList<>(MAX_HISTORY_SIZE);
+ }
+
+ public DisplayEvent getLastEvent() {
+ return history.isEmpty() ? null : history.get(history.size() - 1);
+ }
+
+ public void recordEvent(DisplayEvent e) {
+ recordEvent(history, e);
+ }
+
+ public void replayLastEvent(ProjectController controller) {
+
+ if (history.isEmpty()) {
+ return;
+ }
+
+ DisplayEvent e = history.remove(history.size() - 1);
+ recordEvent(replayHistory, e);
+ replay(controller, e);
+ }
+
+
+ public void replayNextEvent(ProjectController controller) {
+ if (replayHistory.isEmpty()) {
+ return;
+ }
+
+ DisplayEvent e = replayHistory.remove(replayHistory.size() - 1);
+ recordEvent(history, e);
+ replay(controller, e);
+ }
+
+ private void recordEvent(List<DisplayEvent> target, DisplayEvent e) {
+
+ // "currentEvent" will be the same as "e" if this was caused by replay
+ if (this.currentEvent != null && this.currentEvent != e) {
+ if (target.size() >= MAX_HISTORY_SIZE) {
+ target.remove(0);
+ }
+
+ target.add(this.currentEvent);
+ }
+
+ this.currentEvent = e;
+ }
+
+ private void replay(ProjectController controller, DisplayEvent e) {
+ if (e instanceof EntityDisplayEvent) {
+ EntityDisplayEvent ede = (EntityDisplayEvent) e;
+ if (ede.getEntity() instanceof ObjEntity) {
+ controller.fireObjEntitySelected(ede);
+ } else if (ede.getEntity() instanceof DbEntity) {
+ controller.fireDbEntitySelected(ede);
+ }
+ } else if (e instanceof EmbeddableDisplayEvent) {
+ controller.fireEmbeddableSelected((EmbeddableDisplayEvent) e);
+ } else if (e instanceof ProcedureDisplayEvent) {
+ controller.fireProcedureSelected((ProcedureDisplayEvent) e);
+ } else if (e instanceof QueryDisplayEvent) {
+ controller.fireQuerySelected((QueryDisplayEvent) e);
+ } else if (e instanceof DataMapDisplayEvent) {
+ controller.fireDataMapSelected((DataMapDisplayEvent) e);
+ } else if (e instanceof DataNodeDisplayEvent) {
+ controller.fireDataNodeSelected((DataNodeDisplayEvent) e);
+ } else if (e instanceof DomainDisplayEvent) {
+ controller.fireDomainSelected((DomainDisplayEvent) e);
+ }
+ }
+
+ public void forgetObject(EventObject e) {
+
+ Consumer<List<DisplayEvent>> remover = list -> {
+ Iterator<DisplayEvent> it = list.iterator();
+ while (it.hasNext()) {
+ DisplayEvent de = it.next();
+ if (e instanceof EntityEvent && de instanceof EntityDisplayEvent) {
+ if (((EntityEvent) e).getEntity() == ((EntityDisplayEvent) de).getEntity()) {
+ it.remove();
+ }
+ } else if (e instanceof EmbeddableEvent && de instanceof EmbeddableDisplayEvent) {
+ if (((EmbeddableEvent) e).getEmbeddable() == ((EmbeddableDisplayEvent) de).getEmbeddable()) {
+ it.remove();
+ }
+ } else if (e instanceof ProcedureEvent && de instanceof ProcedureDisplayEvent) {
+ if (((ProcedureEvent) e).getProcedure() == ((ProcedureDisplayEvent) de).getProcedure()) {
+ it.remove();
+ }
+ } else if (e instanceof QueryEvent && de instanceof QueryDisplayEvent) {
+ if (((QueryEvent) e).getQuery() == ((QueryDisplayEvent) de).getQuery()) {
+ it.remove();
+ }
+ } else if (e instanceof DataMapEvent && de instanceof DataMapDisplayEvent) {
+ if (((DataMapEvent) e).getDataMap() == ((DataMapDisplayEvent) de).getDataMap()) {
+ it.remove();
+ }
+ } else if (e instanceof DataNodeEvent && de instanceof DataNodeDisplayEvent) {
+ if (((DataNodeEvent) e).getDataNode() == ((DataNodeDisplayEvent) de).getDataNode()) {
+ it.remove();
+ }
+ } else if (e instanceof DomainEvent && de instanceof DomainDisplayEvent) {
+ if (((DomainEvent) e).getDomain() == ((DomainDisplayEvent) de).getDomain()) {
+ it.remove();
+ }
+ }
+ }
+ };
+
+ remover.accept(history);
+ remover.accept(replayHistory);
+ }
+
+}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
index be4c3c33b..ea57d7d06 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java
@@ -23,6 +23,8 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.configuration.ConfigurationNode;
import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.map.Attribute;
+import org.apache.cayenne.map.Relationship;
import org.apache.cayenne.modeler.event.display.*;
import org.apache.cayenne.modeler.event.model.*;
import org.apache.cayenne.map.DataMap;
@@ -61,7 +63,6 @@ import org.apache.cayenne.modeler.pref.DataMapDefaults;
import org.apache.cayenne.modeler.pref.DataNodeDefaults;
import org.apache.cayenne.modeler.pref.ProjectStatePreferences;
import org.apache.cayenne.modeler.util.CayenneController;
-import org.apache.cayenne.modeler.util.CircularArray;
import org.apache.cayenne.modeler.util.Comparators;
import org.apache.cayenne.project.ConfigurationNodeParentGetter;
import org.apache.cayenne.project.Project;
@@ -75,7 +76,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EventListener;
-import java.util.EventObject;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -89,14 +89,14 @@ public class ProjectController extends CayenneController {
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectController.class);
- private final static int MAX_HISTORY_SIZE = 20;
+ private NavigationHistory history;
private EventListenerList listeners;
private boolean dirty;
private Project project;
private Preferences projectControllerPreferences;
private ControllerState state;
- private final CircularArray<ControllerState> controllerStateHistory;
+
private EntityResolver entityResolver;
private ProjectFileChangeTracker fileChangeTracker;
@@ -104,8 +104,8 @@ public class ProjectController extends CayenneController {
public ProjectController(CayenneModelerController parent) {
super(parent);
this.listeners = new EventListenerList();
- this.controllerStateHistory = new CircularArray<>(MAX_HISTORY_SIZE);
this.state = new ControllerState();
+ this.history = new NavigationHistory();
}
@Override
@@ -292,77 +292,17 @@ public class ProjectController extends CayenneController {
}
public void reset() {
- clearState();
+ state = new ControllerState();
setDirty(false);
listeners = new EventListenerList();
- controllerStateHistory.clear();
+ history = new NavigationHistory();
}
public boolean isDirty() {
return dirty;
}
- /**
- * Resets all current models to null.
- */
- private void clearState() {
- state = new ControllerState();
- }
-
- private void saveState(DisplayEvent e) {
- if (!controllerStateHistory.contains(state)) {
- state.event = e;
- controllerStateHistory.add(state);
- }
- }
- private void removeFromHistory(EventObject e) {
-
- int count = controllerStateHistory.size();
- List<ControllerState> removeList = new ArrayList<>();
-
- for (int i = 0; i < count; i++) {
- ControllerState cs = controllerStateHistory.get(i);
- if (cs == null || cs.event == null) {
- continue;
- }
- EventObject csEvent = cs.event;
-
- if (e instanceof EntityEvent && csEvent instanceof EntityDisplayEvent) {
- if (((EntityEvent) e).getEntity() == ((EntityDisplayEvent) csEvent).getEntity()) {
- removeList.add(cs);
- }
- } else if (e instanceof EmbeddableEvent && csEvent instanceof EmbeddableDisplayEvent) {
- if (((EmbeddableEvent) e).getEmbeddable() == ((EmbeddableDisplayEvent) csEvent).getEmbeddable()) {
- removeList.add(cs);
- }
- } else if (e instanceof ProcedureEvent && csEvent instanceof ProcedureDisplayEvent) {
- if (((ProcedureEvent) e).getProcedure() == ((ProcedureDisplayEvent) csEvent).getProcedure()) {
- removeList.add(cs);
- }
- } else if (e instanceof QueryEvent && csEvent instanceof QueryDisplayEvent) {
- if (((QueryEvent) e).getQuery() == ((QueryDisplayEvent) csEvent).getQuery()) {
- removeList.add(cs);
- }
- } else if (e instanceof DataMapEvent && csEvent instanceof DataMapDisplayEvent) {
- if (((DataMapEvent) e).getDataMap() == ((DataMapDisplayEvent) csEvent).getDataMap()) {
- removeList.add(cs);
- }
- } else if (e instanceof DataNodeEvent && csEvent instanceof DataNodeDisplayEvent) {
- if (((DataNodeEvent) e).getDataNode() == ((DataNodeDisplayEvent) csEvent).getDataNode()) {
- removeList.add(cs);
- }
- } else if (e instanceof DomainEvent && csEvent instanceof DomainDisplayEvent) {
- if (((DomainEvent) e).getDomain() == ((DomainDisplayEvent) csEvent).getDomain()) {
- removeList.add(cs);
- }
- }
- }
-
- for (ControllerState o : removeList) {
- controllerStateHistory.remove(o);
- }
- }
public DataChannelDescriptor getSelectedDataDomain() {
return state.dataDomain;
@@ -430,7 +370,7 @@ public class ProjectController extends CayenneController {
}
public DisplayEvent getLastDisplayEvent() {
- return state.event;
+ return history.getLastEvent();
}
public void addDomainDisplayListener(DomainDisplayListener listener) {
@@ -595,9 +535,9 @@ public class ProjectController extends CayenneController {
if (e.getDomain() != state.dataDomain || (
state.dataNode != null || state.dataMap != null || state.dbEntity != null || state.objEntity != null || state.procedure != null || state.query != null || state.embeddable != null
)) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
- saveState(e);
+ history.recordEvent(e);
}
for (DomainDisplayListener listener : listeners.getListeners(DomainDisplayListener.class)) {
@@ -622,7 +562,7 @@ public class ProjectController extends CayenneController {
setDirty(true);
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (DomainListener listener : listeners.getListeners(DomainListener.class)) {
@@ -642,10 +582,10 @@ public class ProjectController extends CayenneController {
if (e.getDataNode() != state.dataNode || (
state.dataMap != null || state.dbEntity != null || state.objEntity != null || state.procedure != null || state.query != null || state.embeddable != null
)) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataNode = e.getDataNode();
- saveState(e);
+ history.recordEvent(e);
}
for (DataNodeDisplayListener listener : listeners.getListeners(DataNodeDisplayListener.class)) {
@@ -658,7 +598,7 @@ public class ProjectController extends CayenneController {
setDirty(true);
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (DataNodeListener listener : listeners.getListeners(DataNodeListener.class)) {
@@ -683,12 +623,12 @@ public class ProjectController extends CayenneController {
if (e.getDataMap() != state.dataMap || (
state.dbEntity != null || state.objEntity != null || state.procedure != null || state.query != null || state.embeddable != null
)) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataNode = e.getDataNode();
state.dataMap = e.getDataMap();
- saveState(e);
+ history.recordEvent(e);
}
for (DataMapDisplayListener listener : listeners.getListeners(DataMapDisplayListener.class)) {
@@ -712,7 +652,7 @@ public class ProjectController extends CayenneController {
setDirty(true);
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (DataMapListener eventListener : listeners.getListeners(DataMapListener.class)) {
@@ -741,7 +681,7 @@ public class ProjectController extends CayenneController {
}
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (ObjEntityListener listener : listeners.getListeners(ObjEntityListener.class)) {
@@ -770,7 +710,7 @@ public class ProjectController extends CayenneController {
}
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (DbEntityListener listener : listeners.getListeners(DbEntityListener.class)) {
@@ -795,7 +735,7 @@ public class ProjectController extends CayenneController {
setDirty(true);
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (QueryListener eventListener : listeners.getListeners(QueryListener.class)) {
@@ -820,7 +760,7 @@ public class ProjectController extends CayenneController {
setDirty(true);
if (e.getId() == MapEvent.REMOVE) {
- removeFromHistory(e);
+ history.forgetObject(e);
}
for (ProcedureListener eventListener : listeners.getListeners(ProcedureListener.class)) {
@@ -867,129 +807,32 @@ public class ProjectController extends CayenneController {
}
}
- public void rewindForward() {
- int size = controllerStateHistory.size();
- if (size < 2) {
- return;
- }
-
- int i = controllerStateHistory.indexOf(state);
- ControllerState cs;
-
- int counter = 0;
- while (true) {
- if (i < 0) {
- // A new state was created without it being saved. Move to the beginning of the list
- cs = controllerStateHistory.get(0);
- } else if (i + 1 < size) {
- // move forward
- cs = controllerStateHistory.get(i + 1);
- } else {
- // wrap around
- cs = controllerStateHistory.get(0);
- }
-
- if (cs.isNotSame(state)) {
- break;
- }
-
- // if it doesn't find it within 5 tries it is probably stuck in a loop
- if (++counter > 5) {
- break;
- }
-
- i++;
- }
-
- replayNavigationState(cs);
- }
public void rewindBackwards() {
- int size = controllerStateHistory.size();
- if (size < 2) {
- return;
- }
-
- int i = controllerStateHistory.indexOf(state);
- ControllerState cs;
-
- int counter = 0;
- while (true) {
- if (i < 0) {
- // a new state got created without it being saved.
- try {
- cs = controllerStateHistory.get(size - 2);
- } catch (ArrayIndexOutOfBoundsException ex) {
- cs = controllerStateHistory.get(size - 1);
- }
- } else if (i - 1 >= 0) {
- // move to the previous one
- cs = controllerStateHistory.get(i - 1);
- } else {
- // wrap around
- cs = controllerStateHistory.get(size - 1);
- }
-
- if (cs.isNotSame(state)) {
- break;
- }
-
- // if it doesn't find it within 5 tries it is probably stuck in a loop
- if (++counter > 5) {
- break;
- }
-
- i--;
-
- }
-
- replayNavigationState(cs);
+ history.replayLastEvent(this);
}
- private void replayNavigationState(ControllerState cs) {
- state = cs;
- DisplayEvent de = cs.event;
- if (de == null) {
- return;
- }
-
- if (de instanceof EntityDisplayEvent) {
- EntityDisplayEvent ede = (EntityDisplayEvent) de;
- if (ede.getEntity() instanceof ObjEntity) {
- fireObjEntitySelected(ede);
- } else if (ede.getEntity() instanceof DbEntity) {
- fireDbEntitySelected(ede);
- }
- } else if (de instanceof EmbeddableDisplayEvent) {
- fireEmbeddableSelected((EmbeddableDisplayEvent) de);
- } else if (de instanceof ProcedureDisplayEvent) {
- fireProcedureSelected((ProcedureDisplayEvent) de);
- } else if (de instanceof QueryDisplayEvent) {
- fireQuerySelected((QueryDisplayEvent) de);
- } else if (de instanceof DataMapDisplayEvent) {
- fireDataMapSelected((DataMapDisplayEvent) de);
- } else if (de instanceof DataNodeDisplayEvent) {
- fireDataNodeSelected((DataNodeDisplayEvent) de);
- } else if (de instanceof DomainDisplayEvent) {
- fireDomainSelected((DomainDisplayEvent) de);
- }
+ public void rewindForward() {
+ history.replayNextEvent(this);
}
public void fireObjEntitySelected(EntityDisplayEvent e) {
- LOGGER.debug("fireObjEntitySelected: {}", e.getEntity().getName());
+ boolean changed = e.getEntity() != state.objEntity;
+
+ LOGGER.debug("fireObjEntitySelected: {}, changed: {}", e.getEntity().getName(), changed);
- if (e.getEntity() != state.objEntity) {
- clearState();
+ if (changed) {
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataNode = e.getDataNode();
state.dataMap = e.getDataMap();
state.objEntity = (ObjEntity) e.getEntity();
- saveState(e);
- }
+ history.recordEvent(e);
- for (ObjEntityDisplayListener l : listeners.getListeners(ObjEntityDisplayListener.class)) {
- l.currentObjEntityChanged(e);
+ for (ObjEntityDisplayListener l : listeners.getListeners(ObjEntityDisplayListener.class)) {
+ l.currentObjEntityChanged(e);
+ }
}
}
@@ -997,12 +840,12 @@ public class ProjectController extends CayenneController {
LOGGER.debug("fireEmbeddableSelected: {}", e.getEmbeddable().getClassName());
if (e.getEmbeddable() != state.embeddable) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataNode = e.getDataNode();
state.dataMap = e.getDataMap();
state.embeddable = e.getEmbeddable();
- saveState(e);
+ history.recordEvent(e);
}
for (EmbeddableDisplayListener l : listeners.getListeners(EmbeddableDisplayListener.class)) {
@@ -1014,12 +857,12 @@ public class ProjectController extends CayenneController {
LOGGER.debug("fireQuerySelected: {}", e.getQuery().getName());
if (e.getQuery() != state.query) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.query = e.getQuery();
- saveState(e);
+ history.recordEvent(e);
}
for (QueryDisplayListener l : listeners.getListeners(QueryDisplayListener.class)) {
@@ -1031,11 +874,11 @@ public class ProjectController extends CayenneController {
LOGGER.debug("fireProcedureSelected: {}", e.getProcedure().getName());
if (e.getProcedure() != state.procedure) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.procedure = e.getProcedure();
- saveState(e);
+ history.recordEvent(e);
}
for (ProcedureDisplayListener l : listeners.getListeners(ProcedureDisplayListener.class)) {
@@ -1048,7 +891,7 @@ public class ProjectController extends CayenneController {
if (!Arrays.equals(e.getProcedureParameters(), state.procedureParameters)) {
if (state.procedure != e.getProcedure()) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.procedure = e.getProcedure();
@@ -1065,12 +908,12 @@ public class ProjectController extends CayenneController {
LOGGER.debug("fireDbEntitySelected: {}", e.getEntity().getName());
if (e.getEntity() != state.dbEntity) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataNode = e.getDataNode();
state.dataMap = e.getDataMap();
state.dbEntity = (DbEntity) e.getEntity();
- saveState(e);
+ history.recordEvent(e);
}
for (DbEntityDisplayListener l : listeners.getListeners(DbEntityDisplayListener.class)) {
@@ -1103,11 +946,11 @@ public class ProjectController extends CayenneController {
}
public void fireDbAttributeSelected(AttributeDisplayEvent e) {
- LOGGER.debug("fireDbAttributeSelected: {}", Arrays.stream(e.getAttributes()).map(a -> a.getName()).toArray());
+ LOGGER.debug("fireDbAttributeSelected: {}", Arrays.stream(e.getAttributes()).map(Attribute::getName).toArray());
if (!Arrays.equals(e.getAttributes(), state.dbAttributes)) {
if (e.getEntity() != state.dbEntity) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.dbEntity = (DbEntity) e.getEntity();
@@ -1146,11 +989,11 @@ public class ProjectController extends CayenneController {
}
public void fireObjAttributeSelected(AttributeDisplayEvent e) {
- LOGGER.debug("fireObjAttributeSelected: {}", Arrays.stream(e.getAttributes()).map(a -> a.getName()).toArray());
+ LOGGER.debug("fireObjAttributeSelected: {}", Arrays.stream(e.getAttributes()).map(Attribute::getName).toArray());
if (!Arrays.equals(e.getAttributes(), state.objAttributes)) {
if (e.getEntity() != state.objEntity) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.objEntity = (ObjEntity) e.getEntity();
@@ -1165,11 +1008,11 @@ public class ProjectController extends CayenneController {
}
public void fireEmbeddableAttributeSelected(EmbeddableAttributeDisplayEvent ev) {
- LOGGER.debug("fireEmbeddableAttributeSelected: {}", Arrays.stream(ev.getEmbeddableAttributes()).map(a -> a.getName()).toArray());
+ LOGGER.debug("fireEmbeddableAttributeSelected: {}", Arrays.stream(ev.getEmbeddableAttributes()).map(EmbeddableAttribute::getName).toArray());
if (!Arrays.equals(ev.getEmbeddableAttributes(), state.embeddableAttributes)) {
if (ev.getEmbeddable() != state.embeddable) {
- clearState();
+ state = new ControllerState();
state.dataDomain = ev.getDomain();
state.dataMap = ev.getDataMap();
state.embeddable = ev.getEmbeddable();
@@ -1212,10 +1055,10 @@ public class ProjectController extends CayenneController {
}
public void fireDbRelationshipSelected(RelationshipDisplayEvent e) {
- LOGGER.debug("fireDbRelationshipSelected: {}", Arrays.stream(e.getRelationships()).map(r -> r.getName()).toArray());
+ LOGGER.debug("fireDbRelationshipSelected: {}", Arrays.stream(e.getRelationships()).map(Relationship::getName).toArray());
if (!Arrays.equals(e.getRelationships(), state.dbRelationships)) {
if (e.getEntity() != state.dbEntity) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.dbEntity = (DbEntity) e.getEntity();
@@ -1255,7 +1098,7 @@ public class ProjectController extends CayenneController {
public void fireMultipleObjectsSelected(MultipleObjectsDisplayEvent e) {
LOGGER.debug("fireMultipleObjectsSelected");
- clearState();
+ state = new ControllerState();
state.paths = e.getNodes();
state.parentPath = e.getParentNode();
@@ -1265,10 +1108,10 @@ public class ProjectController extends CayenneController {
}
public void fireObjRelationshipSelected(RelationshipDisplayEvent e) {
- LOGGER.debug("fireObjRelationshipSelected: {}", Arrays.stream(e.getRelationships()).map(r -> r.getName()).toArray());
+ LOGGER.debug("fireObjRelationshipSelected: {}", Arrays.stream(e.getRelationships()).map(Relationship::getName).toArray());
if (!Arrays.equals(e.getRelationships(), state.objRelationships)) {
if (e.getEntity() != state.objEntity) {
- clearState();
+ state = new ControllerState();
state.dataDomain = e.getDomain();
state.dataMap = e.getDataMap();
state.objEntity = (ObjEntity) e.getEntity();
@@ -1488,9 +1331,10 @@ public class ProjectController extends CayenneController {
}
}
+
+
static class ControllerState {
- private DisplayEvent event;
private DataChannelDescriptor dataDomain;
private DataNodeDescriptor dataNode;
private DataMap dataMap;
@@ -1525,38 +1369,5 @@ public class ProjectController extends CayenneController {
callbackMethods = new ObjCallbackMethod[0];
}
-
- /*
- * Used to determine if the val ControllerState is equivalent, which means if the event is refired again, will
- * it end up in the same place on the screen. This gets a bit messy at the end, because of inheritance heirarchy
- * issues.
- */
- public boolean isNotSame(ControllerState val) {
-
- if (val == null)
- return true;
-
- if (event instanceof EntityDisplayEvent && val.event instanceof EntityDisplayEvent) {
- if (((EntityDisplayEvent) val.event).getEntity() instanceof ObjEntity) {
- return objEntity != val.objEntity;
- } else {
- return dbEntity != val.dbEntity;
- }
- } else if (event instanceof ProcedureDisplayEvent && val.event instanceof ProcedureDisplayEvent) {
- return procedure != val.procedure;
- } else if (event instanceof QueryDisplayEvent && val.event instanceof QueryDisplayEvent) {
- return query != val.query;
- } else if (event instanceof EmbeddableDisplayEvent && val.event instanceof EmbeddableDisplayEvent) {
- return embeddable != val.embeddable;
- } else if (event.getClass() == DataMapDisplayEvent.class && event.getClass() == val.event.getClass()) {
- return dataMap != val.dataMap;
- } else if (event.getClass() == DataNodeDisplayEvent.class && event.getClass() == val.event.getClass()) {
- return dataNode != val.dataNode;
- } else if (event.getClass() == DomainDisplayEvent.class && event.getClass() == val.event.getClass()) {
- return dataDomain != val.dataDomain;
- }
-
- return true;
- }
}
}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CircularArray.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CircularArray.java
deleted file mode 100644
index da93b7a30..000000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CircularArray.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*****************************************************************
- * 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
- *
- * https://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 org.apache.cayenne.modeler.util;
-
-/**
- * A circular array is an array of fixed size as objects are added it will push
- * objects off of the end to allow space for new objects to be added. This is
- * useful for things like a fixed history size for a navigation tool.
- *
- * @since 1.2
- */
-public class CircularArray<T> {
-
- private Object[] array = null;
- private int head = 0;
- private int tail = 0;
- private int count = 0;
- private int capacity = 0;
-
- /**
- * Creates an array of capacity size.
- *
- * @param capacity
- * - size of the new array
- */
- public CircularArray(int capacity) {
- if (capacity <= 0) {
- throw new IllegalArgumentException("Capacity must be greater than zero");
- }
- array = new Object[capacity];
- this.capacity = capacity;
- }
-
- /**
- * Clears out the contents of the array.
- */
- public void clear() {
- array = new Object[capacity];
- head = 0;
- tail = 0;
- count = 0;
- }
-
- /**
- * Returns true if the array has no elements;
- */
- public boolean isEmpty() {
- return count == 0;
- }
-
- /**
- * Adds a new object to the array. If the array is full it will push the
- * oldest item out of the array.
- *
- * @param obj
- * - the object to be added
- */
- public void add(Object obj) {
- // we have wrapped and we have to move the head pointer
- if (count == capacity && tail == head) {
- head = (head + 1) % capacity;
- }
-
- array[tail] = obj;
-
- tail = (tail + 1) % capacity;
-
- count++;
- if (count > capacity)
- count = capacity;
- }
-
- /**
- * Returns the number of objects stored in the array.
- */
- public int capacity() {
- return capacity;
- }
-
- /*
- * Converts the logical index into a physical index.
- */
- int convert(int index) {
- return (index + head) % capacity;
- }
-
- /*
- * Makes sure that the index is within range.
- */
- private void rangeCheck(int index) {
- if (index >= capacity || index < 0) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + capacity);
- }
- }
-
- /**
- * Returns true if the array contains the specified object.
- *
- * @param obj
- * the object to be checked
- */
- public boolean contains(T obj) {
- return indexOf(obj) >= 0;
- }
-
- /**
- * Gets the object at the specified index.
- *
- * @param index
- * the index of the object to be retrieved
- */
- @SuppressWarnings("unchecked")
- public T get(int index) {
- rangeCheck(index);
- if (count == 0) {
- return null;
- }
- return (T)array[convert(index)];
- }
-
- /**
- * Returns the index of the specified object
- *
- * @param obj
- * the object that is being searched for
- */
- public int indexOf(T obj) {
- for (int i = 0; i < capacity; i++) {
- int index = convert(i);
- if (array[index] == obj) {
- return i;
- }
- }
- // not found
- return -1;
- }
-
- /**
- * Removes the specified object from the array
- *
- * @param obj object to be removed
- */
- public void remove(T obj) {
- if (count == 0) {
- return;
- }
-
- int i = indexOf(obj);
-
- while (i >= 0) {
- // convert from logical to physical location
- int pos = convert(i);
-
- if (pos == head) {
- // move the head up one
- head = (head + 1) % capacity;
- array[pos] = null;
- count--;
- } else if (pos == tail) {
- // move the tail back one
- tail = (tail - 1 + capacity) % capacity;
- array[pos] = null;
- count--;
- } else {
- // create a brand new array and start it back out at zero
- Object[] a = new Object[capacity];
- int destPos = 0;
- int len = 0;
-
- if (head == tail) {
- // most likeley scenario when it is full
- if (head < pos) {
- // copy from head to position
- len = pos - head;
- System.arraycopy(array, head, a, destPos, len);
- destPos += len;
-
- // copy from pos +1 to end
- len = (capacity - 1) - pos;
- if (len > 0) {
- System.arraycopy(array, pos + 1, a, destPos, len);
- destPos += len;
- }
-
- // copy from zero to head
- len = head;
- if (len > 0) {
- System.arraycopy(array, 0, a, destPos, len);
- }
- } else if (head > pos) {
- // copy from head to end of array
- len = capacity - head;
- if (len > 0) {
- System.arraycopy(array, head, a, destPos, len);
- destPos += len;
- }
-
- // copy from zero to pos -1
- len = pos;
- if (len > 0) {
- System.arraycopy(array, 0, a, destPos, len);
- destPos += len;
- }
-
- // copy from pos + 1 to tail
- len = tail - pos - 1;
- if (len > 0) {
- System.arraycopy(array, pos + 1, a, destPos, len);
- }
- }
- } else if (head < tail) {
- // copy from head to position -1
- len = pos - head;
- if (len > 0) {
- System.arraycopy(array, head, a, destPos, len);
- destPos += len;
- }
-
- // copy from position + 1 to tail
- len = tail - pos;
- if (len > 0) {
- System.arraycopy(array, pos + 1, a, destPos, len);
- destPos += len;
- }
- } else if (head > tail) {
- if (head < pos) {
- // copy from head to position
- len = pos - head;
- System.arraycopy(array, head, a, destPos, len);
- destPos += len;
-
- // copy from pos +1 to end
- len = capacity - 1 - pos;
- if (len > 0) {
- System.arraycopy(array, pos + 1, a, destPos, len);
- destPos += len;
- }
-
- // copy from beginning to tail
- len = tail;
- if (len > 0) {
- System.arraycopy(array, 0, a, destPos, len);
- }
- } else if (head > pos) {
- // copy from head to end of array
- len = capacity - head;
- if (len > 0) {
- System.arraycopy(array, head, a, destPos, len);
- destPos += len;
- }
-
- // copy from zero to pos -1
- len = pos - 1;
- if (len > 0) {
- System.arraycopy(array, 0, a, destPos, len);
- destPos += len;
- }
-
- // copy from pos+1 to tail
- len = tail - pos;
- if (len > 0) {
- System.arraycopy(array, pos + 1, a, destPos, len);
- }
- }
- }
- count--;
- array = a;
- head = 0;
- tail = count;
- }
- i = indexOf(obj);
- }
- }
-
- /**
- * Resizes the array to the specified new size. If the new capacity is
- * smaller than the current object count in the array, it will keep the
- * newCapacity most recent objects.
- *
- * @param newCapacity
- * the new capacity of the array
- */
- public void resize(int newCapacity) {
- int i = 0;
- int offset = 0;
- if (newCapacity < count) {
- // making it smaller so we want to readjust the first object
- // to be copied into the new array
- i = count - newCapacity;
- offset = count - newCapacity;
- }
- Object newArray[] = new Object[newCapacity];
- for (; i < count; i++) {
- newArray[i - offset] = array[convert(i)];
- }
- head = 0;
- tail = 0;
- capacity = newCapacity;
-
- // adjust the count if it is more than the new capacity
- if (capacity < count)
- count = capacity;
- array = newArray;
- }
-
- /**
- * Returns the number of objects stored in the array.
- */
- public int size() {
- return count;
- }
-
- /**
- * Converts the array to an Object array.
- */
- public T[] toArray() {
- Object[] o = new Object[capacity];
- for (int i = 0; i < capacity; i++) {
- o[i] = array[convert(i)];
- }
- return (T[])o;
- }
-
- public String internalRep() {
- Object o;
- StringBuilder sb = new StringBuilder();
- sb.append("\n");
- for (int i = 0; i < array.length; i++) {
- sb.append('(').append(i).append(") ");
-
- o = array[i];
- if (o == null) {
- sb.append("null");
- } else {
- sb.append(o.toString());
- }
- if (i == head || i == tail) {
- sb.append('<');
- if (i == head)
- sb.append("h");
- if (i == tail)
- sb.append("t");
- }
- sb.append("\n");
- }
-
- sb.append("count = [");
- sb.append(count);
- sb.append("]");
-
- sb.append("\nhead = [");
- sb.append(head);
- sb.append("]");
-
- sb.append("\ntail = [");
- sb.append(tail);
- sb.append("]");
-
- return sb.toString();
- }
-
- public String toString() {
- Object[] oa = toArray();
- Object o;
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- for (int i = 0; i < oa.length; i++) {
- o = oa[i];
- if (i > 0) {
- sb.append(", ");
- }
- if (o == null) {
- sb.append("null");
- } else {
- sb.append(o.toString());
- }
- }
- sb.append("]");
- return sb.toString();
- }
-}
diff --git a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/util/CircularArrayTest.java b/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/util/CircularArrayTest.java
deleted file mode 100644
index 0426e7efa..000000000
--- a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/util/CircularArrayTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*****************************************************************
- * 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
- *
- * https://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 org.apache.cayenne.modeler.util;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class CircularArrayTest {
-
- @Test
- public void testArraySize5() {
-
- String a = "A", b = "B", c = "C", d = "D", e = "E", f = "F", g = "G", h = "H";
- CircularArray<String> q = new CircularArray<>(5);
-
- assertAdd(q, a, "[A, null, null, null, null]");
- assertRemove(q, a, "[null, null, null, null, null]");
- assertAdd(q, a, "[A, null, null, null, null]");
-
- assertAdd(q, b, "[A, B, null, null, null]");
- assertRemove(q, b, "[A, null, null, null, null]");
- assertAdd(q, b, "[A, B, null, null, null]");
-
- assertAdd(q, c, "[A, B, C, null, null]");
- assertRemove(q, c, "[A, B, null, null, null]");
- assertAdd(q, c, "[A, B, C, null, null]");
-
- assertAdd(q, d, "[A, B, C, D, null]");
- assertRemove(q, d, "[A, B, C, null, null]");
- assertAdd(q, d, "[A, B, C, D, null]");
-
- assertAdd(q, e, "[A, B, C, D, E]");
- assertRemove(q, e, "[A, B, C, D, null]");
- assertAdd(q, e, "[A, B, C, D, E]");
-
- assertAdd(q, f, "[B, C, D, E, F]");
- assertRemove(q, f, "[B, C, D, E, null]");
- assertAdd(q, f, "[B, C, D, E, F]");
-
- assertAdd(q, g, "[C, D, E, F, G]");
- assertRemove(q, e, "[C, D, F, G, null]");
- assertAdd(q, h, "[C, D, F, G, H]");
-
- assertRemove(q, c, "[D, F, G, H, null]");
- assertRemove(q, h, "[D, F, G, null, null]");
- assertRemove(q, f, "[D, G, null, null, null]");
- assertRemove(q, g, "[D, null, null, null, null]");
- assertRemove(q, d, "[null, null, null, null, null]");
- }
-
- @Test
- public void testArraySize3() {
- String a = "A", b = "B", c = "C", d = "D", e = "E";
- CircularArray<String> q = new CircularArray<>(3);
-
- assertEquals(0, q.size());
- assertEquals(3, q.capacity());
-
- q.add(a);
-
- assertEquals(0, q.indexOf(a));
- assertEquals(a, q.get(0));
- assertEquals(1, q.size());
-
- q.add(b);
-
- assertEquals(1, q.indexOf(b));
- assertEquals(a, q.get(0));
- assertEquals(b, q.get(1));
- assertEquals(2, q.size());
-
- q.add(c);
-
- assertEquals(2, q.indexOf(c));
- assertEquals(a, q.get(0));
- assertEquals(b, q.get(1));
- assertEquals(c, q.get(2));
- assertEquals(3, q.size());
-
- q.add(d);
-
- assertEquals(3, q.size());
-
- q.add(e);
-
- assertEquals(3, q.size());
- assertFalse("A should not be in the q", q.contains(a));
- assertEquals(0, q.indexOf(c));
- assertEquals(c, q.get(0));
- assertEquals(1, q.indexOf(d));
- assertEquals(d, q.get(1));
- assertEquals(2, q.indexOf(e));
- assertEquals(e, q.get(2));
-
- // should be the same after resizing
- q.resize(5);
-
- assertEquals(5, q.capacity());
- assertEquals(3, q.size());
- assertEquals(2, q.indexOf(e));
- assertEquals(e, q.get(2));
-
- q.resize(2);
-
- assertEquals(2, q.capacity());
- }
-
- @Test
- public void testToString() {
- CircularArray<String> a = new CircularArray<>(5);
- assertEquals("[null, null, null, null, null]", a.toString());
- }
-
- public void assertAdd(CircularArray<String> a, String obj, String expected) {
- a.add(obj);
- assertEquals(expected, a.toString());
- }
-
- public void assertRemove(CircularArray<String> a, String obj, String expected) {
- a.indexOf(obj);
- a.remove(obj);
- assertEquals(expected, a.toString());
- }
-}