Cleanup code, refactor presenter

This commit is contained in:
Bane Stojkovic
2022-10-23 22:09:49 +02:00
parent 55c91faaf7
commit 37b1d1dbd9
9 changed files with 756 additions and 785 deletions
@@ -313,13 +313,6 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
*/
void setNewComponentTypeSlot(ComponentType componentType, Template template, boolean forceInstatiate);
/**
* Changes default size notation, true for metric, false for imperial.
*
* @param isMetric
*/
void setMetric(boolean isMetric);
/**
* Locks or unlocks the specified layer. All components within +- 0.5 range will be affected by
* the change as well.
@@ -51,15 +51,6 @@ public abstract class NetlistAnalyzer {
Tree tree = new Tree(TreeConnectionType.Parallel);
connectNodes(netlist, nodeA, nodeB, tree.getChildren(), new Tree(TreeConnectionType.Series), new HashSet<Node>());
// System.out.println(netlist.getSwitchSetup());
// System.out.println(tree);
//
// System.out.println("opposite:");
// Tree tree1 = new Tree(TreeConnectionType.Parallel);
// connectNodes(netlist, nodeB, nodeA, tree1.getChildren(), new Tree(TreeConnectionType.Series),
// new HashSet<Node>());
// System.out.println(tree1);
return tree;
}
@@ -112,7 +103,6 @@ public abstract class NetlistAnalyzer {
if (newConcurrentPaths.size() == 0)
return;
if (newConcurrentPaths.size() == 1) {
if (newConcurrentPaths.get(0).getConnectionType() == TreeConnectionType.Series) {
currentPath.getChildren().clear();
@@ -214,45 +204,6 @@ public abstract class NetlistAnalyzer {
paths.addAll(unmerged);
}
}
//
// protected void findAllPaths(Netlist netlist, Node nodeA, Node nodeB, List<TreeLeaf> currentPath,
// List<List<TreeLeaf>> allPaths, Set<Node> visited) {
// if (nodeA == nodeB) {
// allPaths.add(currentPath);
// return;
// }
//
// // System.out.println("Finding path between " + nodeA + " and " + nodeB);
//
// Group groupA = findGroup(netlist, nodeA);
//
// if (groupA == null)
// return;
//
// if (groupA.getNodes().contains(nodeB)) {
// allPaths.add(currentPath);
// return;
// }
//
// for (Node n : groupA.getNodes()) {
// IDIYComponent<?> c = n.getComponent();
// for (int i = 0; i < c.getControlPointCount(); i++) {
// if (i != n.getPointIndex() && c.getInternalLinkName(i, n.getPointIndex()) != null) {
// TreeLeaf l = new TreeLeaf(c, i, n.getPointIndex());
// Node newNodeA = new Node(c, i);
// if (!visited.contains(newNodeA)) {
// List<TreeLeaf> newCurrentPath = new ArrayList<TreeLeaf>(currentPath);
// if (!currentPath.contains(l))
// newCurrentPath.add(l);
// Set<Node> newVisited = new HashSet<Node>(visited);
// newVisited.add(nodeA);
// newVisited.add(newNodeA);
// findAllPaths(netlist, newNodeA, nodeB, newCurrentPath, allPaths, newVisited);
// }
// }
// }
// }
// }
protected Group findGroup(Netlist netlist, Node node) {
for (Group g : netlist.getGroups())
@@ -261,63 +212,6 @@ public abstract class NetlistAnalyzer {
return null;
}
// protected List<Group> trace(Set<String> typeNames, String nodeName, Netlist netlist) {
// List<Group> res = new ArrayList<Group>();
// for (Group g : netlist.getGroups()) {
// for (Node n : g.getNodes()) {
// if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(g);
// break;
// }
// }
// }
// return res;
// }
// protected List<Node> find(Set<String> typeNames, String nodeName, Group group) {
// List<Node> res = new ArrayList<Node>();
//
// for (Node n : group.getNodes()) {
// if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(n);
// }
// }
//
// return res;
// }
// protected List<Group> findGroups(Set<String> typeNames, String nodeName, Netlist netlist) {
// List<Group> res = new ArrayList<Group>();
// for (Group g : netlist.getGroups()) {
// for (Node n : g.getNodes()) {
// if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(g);
// break;
// }
// }
// }
// return res;
// }
// protected List<Group> findGroups(Set<String> typeNames, String nodeName, Netlist netlist,
// Collection<IDIYComponent<?>> belongTo) {
// List<Group> res = new ArrayList<Group>();
// for (Group g : netlist.getGroups()) {
// for (Node n : g.getNodes()) {
// if ((belongTo == null || belongTo.contains(n.getComponent()))
// && (typeNames.contains(n.getComponent().getClass().getCanonicalName()))
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(g);
// break;
// }
// }
// }
// return res;
// }
protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist) {
List<Node> res = new ArrayList<Node>();
for (Group g : netlist.getGroups()) {
@@ -331,68 +225,6 @@ public abstract class NetlistAnalyzer {
return res;
}
// protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist, List<Node> inGroupWith) {
// List<Node> res = new ArrayList<Node>();
// for (Group g : netlist.getGroups()) {
//
// boolean inGroup;
// if (inGroupWith == null) {
// inGroup = true;
// } else {
// inGroup = true;
// for (Node n1 : inGroupWith)
// if (!g.getNodes().contains(n1)) {
// inGroup = false;
// break;
// }
// }
//
// for (Node n : g.getNodes()) {
// if (inGroup && typeNames.contains(n.getComponent().getClass().getCanonicalName())
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(n);
// }
// }
// }
// return res;
// }
// protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist,
// Collection<IDIYComponent<?>> belongTo) {
// List<Node> res = new ArrayList<Node>();
// for (Group g : netlist.getGroups()) {
//
// for (Node n : g.getNodes()) {
// if ((belongTo == null || belongTo.contains(n.getComponent()))
// && typeNames.contains(n.getComponent().getClass().getCanonicalName())
// && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
// res.add(n);
// }
// }
// }
// return res;
// }
// protected boolean allMatch(Collection<Node> nodes, String name) {
// for (Node n : nodes)
// if (!n.getDisplayName().equalsIgnoreCase(name))
// return false;
//
// return true;
// }
// protected boolean allComponentsMatch(Collection<Node> nodes, Set<IDIYComponent<?>> components) {
// Set<IDIYComponent<?>> extracted = extractComponents(nodes);
// return extracted.containsAll(components);
// }
//
// protected Set<IDIYComponent<?>> extractComponents(Collection<Node> nodes) {
// Set<IDIYComponent<?>> components = new HashSet<IDIYComponent<?>>();
// for (Node n : nodes)
// components.add(n.getComponent());
// return components;
// }
protected String extractName(IDIYComponent<?> c) {
return c.getName() + " " + c.getValueForDisplay();
}
@@ -423,53 +255,6 @@ public abstract class NetlistAnalyzer {
return -1;
}
// protected List<String> extractNames(Collection<IDIYComponent<?>> components) {
// List<String> names = new ArrayList<String>();
// for (IDIYComponent<?> c : components)
// names.add(c.getName() + " " + c.getValueForDisplay());
// Collections.sort(names);
// return names;
// }
//
// protected Netlist simplify(Netlist netlist, Set<Node> nodesToMerge, Collection<Node> nodesToPurge) {
// Netlist res = new Netlist();
// res.getSwitchSetup().addAll(netlist.getSwitchSetup());
//
// Group merged = new Group();
//
// // merge
// for (Group g : netlist.getGroups()) {
// boolean needsMerging = false;
// for (Node n : nodesToMerge) {
// if (g.getNodes().contains(n)) {
// needsMerging = true;
// break;
// }
// }
// if (needsMerging) {
// for (Node n : g.getNodes()) {
// if (!nodesToMerge.contains(n))
// merged.getNodes().add(n);
// }
// } else {
// res.getGroups().add(g.clone());
// }
// }
//
// if (!merged.getNodes().isEmpty())
// res.getGroups().add(merged);
//
// // purge
// for (Group g : res.getGroups()) {
// g.getNodes().removeAll(nodesToPurge);
// }
//
// System.out.println("Before:\n" + netlist);
// System.out.println("After:\n" + res);
//
// return res;
// }
//
protected boolean intersect(List<Group> groups, Node node) {
for (Group g : groups)
if (g.getNodes().contains(node))
@@ -21,14 +21,22 @@ import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.diylc.common.ComponentType;
import org.diylc.core.IContinuity;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ISwitch;
import org.diylc.core.Project;
import org.diylc.lang.LangUtil;
import org.diylc.netlist.ContinuityGraph.ContinuityNode;
import org.diylc.presenter.ComponentProcessor;
import org.diylc.presenter.Connection;
import org.diylc.utils.RTree;
import com.google.common.graph.GraphBuilder;
@@ -40,6 +48,121 @@ public class NetlistBuilder {
public static final float eps = 4; // consider any nodes closer than this as connected
private static final int MAX_SWITCH_COMBINATIONS = 64;
private static final String MAX_SWITCH_COMBINATIONS_ERROR = LangUtil
.translate("Maximum number of switching combinations exceeded. Allowed: %s, actual: %s");
@SuppressWarnings("unchecked")
public static List<Netlist> extractNetlists(boolean includeSwitches, Project project, List<Area> continuityAreas)
throws NetlistException {
Map<Netlist, Netlist> result = new HashMap<Netlist, Netlist>();
List<Node> nodes = new ArrayList<Node>();
List<ISwitch> switches = new ArrayList<ISwitch>();
for (IDIYComponent<?> c : project.getComponents()) {
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// extract nodes
if (!(c instanceof IContinuity)) {
for (int i = 0; i < c.getControlPointCount(); i++) {
String nodeName = c.getControlPointNodeName(i);
if (nodeName != null
&& (!includeSwitches || !ISwitch.class.isAssignableFrom(type.getInstanceClass()))) {
nodes.add(new Node(c, i));
}
}
}
// extract switches
if (includeSwitches && ISwitch.class.isAssignableFrom(type.getInstanceClass()))
switches.add((ISwitch) c);
}
// save us the trouble
if (nodes.isEmpty())
return null;
// if there are no switches, make one with 1 position so we get 1 result back
if (switches.isEmpty())
switches.add(new ISwitch() {
@Override
public String getPositionName(int position) {
return "Default";
}
@Override
public int getPositionCount() {
return 1;
}
@Override
public boolean arePointsConnected(int index1, int index2, int position) {
return false;
}
});
// construct all possible combinations
int[] positions = new int[switches.size()];
for (int i = 0; i < switches.size(); i++)
positions[i] = 0;
int i = switches.size() - 1;
int totalSwitchCombinations =
switches.stream().map(sw -> sw.getPositionCount()).reduce(1, (a, b) -> a * b);
if (totalSwitchCombinations > MAX_SWITCH_COMBINATIONS) {
throw new NetlistException(String.format(MAX_SWITCH_COMBINATIONS_ERROR,
MAX_SWITCH_COMBINATIONS, totalSwitchCombinations));
}
while (i >= 0) {
// process the current combination
Map<ISwitch, Integer> switchPositions = new HashMap<ISwitch, Integer>();
List<Position> posList = new ArrayList<Position>();
for (int j = 0; j < positions.length; j++) {
switchPositions.put(switches.get(j), positions[j]);
posList.add(new Position(switches.get(j), positions[j]));
}
List<Connection> connections = getConnections(project, switchPositions);
Netlist netlist = NetlistBuilder.buildNetlist(project.getComponents(), nodes,
continuityAreas, connections);
// merge graphs that are effectively the same
if (result.containsKey(netlist)) {
result.get(netlist).getSwitchSetup().add(new SwitchSetup(posList));
} else {
netlist.getSwitchSetup().add(new SwitchSetup(posList));
result.put(netlist, netlist);
}
// find the next combination if possible
if (positions[i] < switches.get(i).getPositionCount() - 1) {
positions[i]++;
} else {
while (i >= 0 && positions[i] == switches.get(i).getPositionCount() - 1)
i--;
if (i >= 0) {
positions[i]++;
for (int j = i + 1; j < positions.length; j++)
positions[j] = 0;
i = switches.size() - 1;
}
}
}
// sort everything alphabetically
List<Netlist> netlists = new ArrayList<Netlist>(result.keySet());
Collections.sort(netlists);
return netlists;
}
public static Netlist buildNetlist(List<IDIYComponent<?>> components, Collection<Node> nodes,
Collection<Area> continuityAreas, Collection<Connection> connections) {
ImmutableGraph<ProjectGraphNode> graph = buildGraph(nodes, continuityAreas, connections);
@@ -75,17 +198,19 @@ public class NetlistBuilder {
return netlist;
}
public static ContinuityGraph buildContinuityGraph(Collection<Area> continuityAreas, Collection<Connection> connections) {
ImmutableGraph<ProjectGraphNode> graph = buildGraph(new ArrayList<Node>(), continuityAreas, connections);
public static ContinuityGraph buildContinuityGraph(Collection<Area> continuityAreas,
Collection<Connection> connections) {
ImmutableGraph<ProjectGraphNode> graph =
buildGraph(new ArrayList<Node>(), continuityAreas, connections);
Traverser<ProjectGraphNode> traverser = Traverser.forGraph(graph);
Set<ProjectGraphNode> visited = new HashSet<ProjectGraphNode>();
ProjectGraphNode[] nodeArr = graph.nodes().toArray(new ProjectGraphNode[0]);
int groupId = 1;
RTree<ContinuityNode> groupTree = new RTree<ContinuityGraph.ContinuityNode>();
Map<Integer, List<Area>> areaGroupMap = new HashMap<Integer, List<Area>>();
@@ -97,7 +222,7 @@ public class NetlistBuilder {
if (i == graph.nodes().size())
break;
final int finalGroupId = groupId;
List<Area> areaList = new ArrayList<Area>();
@@ -178,7 +303,7 @@ public class NetlistBuilder {
for (Area area : continuityAreas) {
ProjectGraphNode areaNode = new ProjectGraphNode(area);
builder.addNode(areaNode);
builder.addNode(areaNode);
ProjectGraphNode[] nodeArr = nodeTree.search(area).stream()
.filter(graphNode -> area.contains(graphNode.getPoint())
@@ -206,11 +331,39 @@ public class NetlistBuilder {
}).forEach(graphNode -> {
builder.putEdge(graphNode, areaNode);
});
areaTree.insert(area, areaNode);
}
return builder.build();
return builder.build();
}
@SuppressWarnings({"unchecked", "unlikely-arg-type"})
private static List<Connection> getConnections(Project project, Map<ISwitch, Integer> switchPositions) {
Set<Connection> connections = new TreeSet<Connection>();
for (IDIYComponent<?> c : project.getComponents()) {
ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// handle direct connections
if (c instanceof IContinuity) {
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (((IContinuity) c).arePointsConnected(i, j))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
}
// handle switches
if (ISwitch.class.isAssignableFrom(type.getInstanceClass()) && switchPositions.containsKey(c)) {
int position = switchPositions.get(c);
ISwitch s = (ISwitch) c;
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (s.arePointsConnected(i, j, position))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
}
}
return new ArrayList<Connection>(connections);
}
private static Point2D snapToEps(Point2D point, double eps) {
@@ -0,0 +1,216 @@
/*
*
* l * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.presenter;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.common.BuildingBlockPackage;
import org.diylc.common.IBlockProcessor;
import org.diylc.common.IBlockProcessor.InvalidBlockException;
import org.diylc.common.IPlugInPort;
import org.diylc.core.IDIYComponent;
import org.diylc.serialization.ProjectFileManager;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;
public class BuildingBlockManager {
private static final String BLOCKS_FILE_NAME = "blocks.xml";
private static final Logger LOG = Logger.getLogger(VariantManager.class);
private IConfigurationManager<?> configManager;
private XStream xStream;
private InstantiationManager instantiationManager;
public BuildingBlockManager(IConfigurationManager<?> configManager, XStream xStream,
InstantiationManager instantiationManager) {
super();
this.configManager = configManager;
this.xStream = xStream;
this.instantiationManager = instantiationManager;
}
@SuppressWarnings("unchecked")
public void importDefaultBlocks() {
// import default templates from variants.xml file only if we didn't do it already
if (!configManager.readBoolean(IPlugInPort.DEFAULT_BLOCKS_IMPORTED_KEY, false)) {
try {
URL resource = Presenter.class.getResource(BLOCKS_FILE_NAME);
if (resource != null) {
BufferedInputStream in = new BufferedInputStream(resource.openStream());
Map<String, List<IDIYComponent<?>>> defaults =
(Map<String, List<IDIYComponent<?>>>) ProjectFileManager.xStreamSerializer
.fromXML(in);
in.close();
Map<String, List<IDIYComponent<?>>> blocksMap =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(IPlugInPort.BLOCKS_KEY,
null);
if (blocksMap == null)
blocksMap = new HashMap<String, List<IDIYComponent<?>>>();
// merge default blocks with user's
for (Map.Entry<String, List<IDIYComponent<?>>> entry : defaults.entrySet()) {
if (!blocksMap.containsKey(entry.getKey()))
blocksMap.put(entry.getKey(), entry.getValue());
}
// update templates and a flag marking that we imported them
configManager.writeValue(IPlugInPort.DEFAULT_BLOCKS_IMPORTED_KEY, true);
configManager.writeValue(IPlugInPort.BLOCKS_KEY, blocksMap);
LOG.info(String.format("Imported %d default building blocks",
defaults == null ? 0 : defaults.size()));
}
} catch (Exception e) {
LOG.error("Could not load default blocks", e);
}
}
}
@SuppressWarnings("unchecked")
public int importBlocks(String fileName) throws IOException {
LOG.debug(String.format("importBlocks(%s)", fileName));
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName));
BuildingBlockPackage pkg = (BuildingBlockPackage) xStream.fromXML(in);
in.close();
if (pkg == null || pkg.getBlocks().isEmpty())
return 0;
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(IBlockProcessor.BLOCKS_KEY, null);
if (blocks == null) {
blocks = new HashMap<String, List<IDIYComponent<?>>>();
}
for (Map.Entry<String, List<IDIYComponent<?>>> entry : pkg.getBlocks().entrySet()) {
blocks.put(entry.getKey() + " [" + pkg.getOwner() + "]", entry.getValue());
}
configManager.writeValue(IBlockProcessor.BLOCKS_KEY, blocks);
LOG.info(String.format("Loaded building blocks for %d components", pkg.getBlocks().size()));
return pkg.getBlocks().size();
}
@SuppressWarnings("unchecked")
public List<IDIYComponent<?>> loadBlock(String blockName,
List<IDIYComponent<?>> existingComponents) throws InvalidBlockException {
LOG.debug(String.format("loadBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks = (Map<String, List<IDIYComponent<?>>>) configManager
.readObject(IPlugInPort.BLOCKS_KEY, null);
if (blocks != null) {
Collection<IDIYComponent<?>> components = blocks.get(blockName);
if (components == null)
throw new InvalidBlockException();
// clear potential control point every time!
instantiationManager.setPotentialControlPoint(null);
// clone components
List<IDIYComponent<?>> clones = new ArrayList<IDIYComponent<?>>();
List<IDIYComponent<?>> testComponents = new ArrayList<IDIYComponent<?>>(existingComponents);
for (IDIYComponent<?> c : components)
try {
IDIYComponent<?> clone = c.clone();
clone.setName(instantiationManager.createUniqueName(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) clone.getClass()),
testComponents));
testComponents.add(clone);
clones.add(clone);
} catch (CloneNotSupportedException e) {
LOG.error("Could not clone component: " + c);
}
return clones;
} else
throw new InvalidBlockException();
}
@SuppressWarnings("unchecked")
public void saveSelectionAsBlock(String blockName,
Collection<IDIYComponent<?>> selectedComponents, List<IDIYComponent<?>> allComponents) {
LOG.debug(String.format("saveSelectionAsBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks = (Map<String, List<IDIYComponent<?>>>) configManager
.readObject(IBlockProcessor.BLOCKS_KEY, null);
if (blocks == null)
blocks = new HashMap<String, List<IDIYComponent<?>>>();
List<IDIYComponent<?>> blockComponents = new ArrayList<IDIYComponent<?>>(selectedComponents);
Collections.sort(blockComponents, new Comparator<IDIYComponent<?>>() {
@Override
public int compare(IDIYComponent<?> o1, IDIYComponent<?> o2) {
return new Integer(allComponents.indexOf(o1)).compareTo(allComponents.indexOf(o2));
}
});
blocks.put(blockName, blockComponents);
if (System.getProperty("org.diylc.WriteStaticBlocks", "false").equalsIgnoreCase("true")) {
Map<String, List<IDIYComponent<?>>> defaultBlockMap =
new HashMap<String, List<IDIYComponent<?>>>();
// unify default and user-variants
for (Map.Entry<String, List<IDIYComponent<?>>> entry : blocks.entrySet()) {
if (defaultBlockMap.containsKey(entry.getKey())) {
defaultBlockMap.get(entry.getKey()).addAll(entry.getValue());
} else {
defaultBlockMap.put(entry.getKey(), entry.getValue());
}
}
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(BLOCKS_FILE_NAME));
XStream xStream = new XStream(new DomDriver());
xStream.addPermission(AnyTypePermission.ANY);
xStream.toXML(defaultBlockMap, out);
out.close();
// no more user variants
configManager.writeValue(IBlockProcessor.BLOCKS_KEY, null);
LOG.info("Saved default blocks");
} catch (IOException e) {
LOG.error("Could not save default blocks", e);
}
} else {
configManager.writeValue(IBlockProcessor.BLOCKS_KEY, blocks);
}
}
@SuppressWarnings("unchecked")
public void deleteBlock(String blockName) {
LOG.debug(String.format("deleteBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(IBlockProcessor.BLOCKS_KEY, null);
if (blocks != null) {
blocks.remove(blockName);
configManager.writeValue(IBlockProcessor.BLOCKS_KEY, blocks);
}
}
}
@@ -29,7 +29,6 @@ import java.awt.geom.Rectangle2D;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
@@ -45,8 +44,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Supplier;
import javax.swing.JOptionPane;
import org.apache.log4j.Logger;
@@ -57,7 +54,6 @@ import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.appframework.update.Version;
import org.diylc.appframework.update.VersionNumber;
import org.diylc.clipboard.ComponentTransferable;
import org.diylc.common.BuildingBlockPackage;
import org.diylc.common.ComponentType;
import org.diylc.common.DrawOption;
import org.diylc.common.EventType;
@@ -69,11 +65,8 @@ import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.common.IProjectEditor;
import org.diylc.common.PropertyWrapper;
import org.diylc.common.VariantPackage;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IContinuity;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ISwitch;
import org.diylc.core.IView;
import org.diylc.core.Project;
import org.diylc.core.Template;
@@ -88,13 +81,11 @@ import org.diylc.netlist.Netlist;
import org.diylc.netlist.NetlistAnalyzer;
import org.diylc.netlist.NetlistBuilder;
import org.diylc.netlist.NetlistException;
import org.diylc.netlist.Node;
import org.diylc.netlist.Position;
import org.diylc.netlist.SwitchSetup;
import org.diylc.serialization.ProjectFileManager;
import org.diylc.test.DIYTest;
import org.diylc.test.Snapshot;
import org.diylc.utils.Constants;
import org.diylc.utils.ReflectionUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;
@@ -131,7 +122,6 @@ public class Presenter implements IPlugInPort {
private static final String ERROR_NEW = LangUtil.translate("Could not create a new file. Check the log for details.");
private static final String ERROR = LangUtil.translate("Error");
private static final String APPLY_ERROR = LangUtil.translate("Could not apply changes. Check the log for details.");
private static final String MAX_SWITCH_COMBINATIONS_ERROR = LangUtil.translate("Maximum number of switching combinations exceeded. Allowed: %s, actual: %s");
private static final Logger LOG = Logger.getLogger(Presenter.class);
@@ -169,16 +159,11 @@ public class Presenter implements IPlugInPort {
public static final int ICON_SIZE = 32;
private static final int MAX_RECENT_FILES = 20;
private static final int MAX_SWITCH_COMBINATIONS = 64;
private static final int MAX_RECENT_FILES = 20;
private Project currentProject;
private Map<String, List<ComponentType>> componentTypes;
/**
* {@link List} of {@link IAutoCreator} objects that are capable of creating more components
* automatically when a component is created, e.g. Solder Pads.
*/
private List<IAutoCreator> autoCreators;
// Maps component class names to ComponentType objects.
private List<IPlugIn> plugIns;
@@ -193,6 +178,8 @@ public class Presenter implements IPlugInPort {
private DrawingManager drawingManager;
private ProjectFileManager projectFileManager;
private InstantiationManager instantiationManager;
private VariantManager variantManager;
private BuildingBlockManager buildingBlockManager;
private Rectangle selectionRect;
@@ -232,13 +219,15 @@ public class Presenter implements IPlugInPort {
drawingManager = new DrawingManager(messageDispatcher, configManager);
projectFileManager = new ProjectFileManager(messageDispatcher);
instantiationManager = new InstantiationManager();
variantManager = new VariantManager(configManager, projectFileManager.getXStream());
buildingBlockManager = new BuildingBlockManager(configManager, projectFileManager.getXStream(), instantiationManager);
// lockedLayers = EnumSet.noneOf(ComponentLayer.class);
// visibleLayers = EnumSet.allOf(ComponentLayer.class);
if (importVariantsAndBlocks) {
upgradeVariants();
importDefaultVariants();
importDefaultBlocks();
variantManager.upgradeVariants(getComponentTypes());
variantManager.importDefaultVariants();
buildingBlockManager.importDefaultBlocks();
}
}
@@ -491,25 +480,6 @@ public class Presenter implements IPlugInPort {
return componentTypes;
}
public List<IAutoCreator> getAutoCreators() {
if (autoCreators == null) {
autoCreators = new ArrayList<IAutoCreator>();
Set<Class<?>> classes = null;
try {
classes = Utils.getClasses("org.diylc.components.autocreate");
for (Class<?> clazz : classes) {
if (IAutoCreator.class.isAssignableFrom(clazz)) {
autoCreators.add((IAutoCreator) clazz.newInstance());
LOG.debug("Loaded auto-creator: " + clazz.getName());
}
}
} catch (Exception e) {
LOG.error("Error loading auto-creator types", e);
}
}
return autoCreators;
}
@SuppressWarnings({"unchecked"})
private boolean isComponentVisible(IDIYComponent<?> component) {
ComponentType componentType =
@@ -1798,11 +1768,6 @@ public class Presenter implements IPlugInPort {
configManager.writeValue(DEFAULTS_KEY_PREFIX + clazz.getName() + ":" + propertyName, value);
}
@Override
public void setMetric(boolean isMetric) {
configManager.writeValue(Presenter.METRIC_KEY, isMetric);
}
@Override
public void groupSelectedComponents() {
LOG.info("groupSelectedComponents()");
@@ -2310,23 +2275,6 @@ public class Presenter implements IPlugInPort {
return new Point2D[] {inSize, cmSize};
}
// @Override
// public Rectangle2D getSelectedAreaRect() {
// if (selectedComponents.isEmpty()) {
// return null;
// }
// Area area = new Area();
// for (IDIYComponent<?> component : selectedComponents) {
// Area componentArea = drawingManager.getComponentArea(component);
// if (componentArea != null) {
// area.add(componentArea);
// } else {
// LOG.warn("No area found for: " + component.getName());
// }
// }
// return area.getBounds2D();
// }
/**
* Adds a component to the project taking z-order into account.
*
@@ -2351,7 +2299,7 @@ public class Presenter implements IPlugInPort {
}
// Check if we should auto-create something.
for (IAutoCreator creator : this.getAutoCreators()) {
for (IAutoCreator creator : ReflectionUtils.getAutoCreators()) {
List<IDIYComponent<?>> newComponents = creator.createIfNeeded(component);
if (newComponents != null) {
for (IDIYComponent<?> c : newComponents)
@@ -2624,108 +2572,9 @@ public class Presenter implements IPlugInPort {
}
}
@SuppressWarnings("unchecked")
private void importDefaultVariants() {
// import default templates from variants.xml file only if we didn't do it already
if (!configManager.readBoolean(DEFAULT_TEMPLATES_IMPORTED_KEY, false)) {
try {
URL resource = Presenter.class.getResource("variants.xml");
if (resource != null) {
BufferedInputStream in = new BufferedInputStream(resource.openStream());
Map<String, List<Template>> defaults = (Map<String, List<Template>>) ProjectFileManager.xStreamSerializer.fromXML(in);
in.close();
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(TEMPLATES_KEY, null);
if (variantMap == null)
variantMap = new HashMap<String, List<Template>>();
// merge default variants with user's
for (Map.Entry<String, List<Template>> entry : defaults.entrySet()) {
List<Template> templates = variantMap.getOrDefault(entry.getKey(), null);
if (templates == null) {
templates = new ArrayList<Template>();
variantMap.put(entry.getKey(), templates);
}
templates.addAll(entry.getValue());
}
// update templates and a flag marking that we imported them
configManager.writeValue(DEFAULT_TEMPLATES_IMPORTED_KEY, true);
configManager.writeValue(TEMPLATES_KEY, variantMap);
LOG.info(String.format("Imported default variants for %d components",
defaults == null ? 0 : defaults.size()));
}
} catch (Exception e) {
LOG.error("Could not load default variants", e);
}
}
}
@SuppressWarnings("unchecked")
private void importDefaultBlocks() {
// import default templates from variants.xml file only if we didn't do it already
if (!configManager.readBoolean(DEFAULT_BLOCKS_IMPORTED_KEY, false)) {
try {
URL resource = Presenter.class.getResource("blocks.xml");
if (resource != null) {
BufferedInputStream in = new BufferedInputStream(resource.openStream());
Map<String, List<IDIYComponent<?>>> defaults = (Map<String, List<IDIYComponent<?>>>) ProjectFileManager.xStreamSerializer.fromXML(in);
in.close();
Map<String, List<IDIYComponent<?>>> blocksMap =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(BLOCKS_KEY, null);
if (blocksMap == null)
blocksMap = new HashMap<String, List<IDIYComponent<?>>>();
// merge default blocks with user's
for (Map.Entry<String, List<IDIYComponent<?>>> entry : defaults.entrySet()) {
if (!blocksMap.containsKey(entry.getKey()))
blocksMap.put(entry.getKey(), entry.getValue());
}
// update templates and a flag marking that we imported them
configManager.writeValue(DEFAULT_BLOCKS_IMPORTED_KEY, true);
configManager.writeValue(BLOCKS_KEY, blocksMap);
LOG.info(String.format("Imported %d default building blocks", defaults == null ? 0 : defaults.size()));
}
} catch (Exception e) {
LOG.error("Could not load default blocks", e);
}
}
}
@SuppressWarnings("unchecked")
@Override
public List<Template> getVariantsFor(ComponentType type) {
Map<String, List<Template>> lookupMap = new TreeMap<String, List<Template>>(String.CASE_INSENSITIVE_ORDER);
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(TEMPLATES_KEY, null);
if (variantMap != null)
lookupMap.putAll(variantMap);
// try by class name and then by old category.type format
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
List<Template> variants = new ArrayList<Template>();
if (variantMap != null) {
List<Template> userVariants = variantMap.get(key1);
if (userVariants != null && !userVariants.isEmpty())
variants.addAll(userVariants);
userVariants = variantMap.get(key2);
if (userVariants != null && !userVariants.isEmpty())
variants.addAll(userVariants);
}
Collections.sort(variants, new Comparator<Template>() {
@Override
public int compare(Template o1, Template o2) {
return o1.getName().compareTo(o2.getName());
}
});
return variants;
return variantManager.getVariantsFor(type);
}
@SuppressWarnings("unchecked")
@@ -2773,40 +2622,10 @@ public class Presenter implements IPlugInPort {
}
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
@SuppressWarnings("unchecked")
@Override
public void deleteVariant(ComponentType type, String templateName) {
LOG.debug(String.format("deleteTemplate(%s, %s)", type, templateName));
Map<String, List<Template>> templateMap =
(Map<String, List<Template>>) configManager.readObject(TEMPLATES_KEY, null);
if (templateMap != null) {
// try by class name and then by old category.type format
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
List<Template> templates = templateMap.get(key1);
if (templates != null) {
Iterator<Template> i = templates.iterator();
while (i.hasNext()) {
Template t = i.next();
if (t.getName().equalsIgnoreCase(templateName)) {
i.remove();
}
}
}
templates = templateMap.get(key2);
if (templates != null) {
Iterator<Template> i = templates.iterator();
while (i.hasNext()) {
Template t = i.next();
if (t.getName().equalsIgnoreCase(templateName)) {
i.remove();
}
}
}
}
configManager.writeValue(TEMPLATES_KEY, templateMap);
variantManager.deleteVariant(type, templateName);
}
@SuppressWarnings("unchecked")
@@ -2833,21 +2652,9 @@ public class Presenter implements IPlugInPort {
configManager.writeValue(DEFAULT_TEMPLATES_KEY, defaultTemplateMap);
}
@SuppressWarnings("unchecked")
@Override
public String getDefaultVariant(ComponentType type) {
Map<String, String> defaultTemplateMap =
(Map<String, String>) configManager.readObject(DEFAULT_TEMPLATES_KEY, null);
if (defaultTemplateMap == null)
return null;
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
if (defaultTemplateMap.containsKey(key1))
return defaultTemplateMap.get(key1);
return defaultTemplateMap.get(key2);
return variantManager.getDefaultVariant(type);
}
private Set<IDIYComponent<?>> getLockedComponents() {
@@ -2920,94 +2727,21 @@ public class Presenter implements IPlugInPort {
}
return p;
}
@SuppressWarnings("unchecked")
@Override
public void saveSelectionAsBlock(String blockName) {
LOG.debug(String.format("saveSelectionAsBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(BLOCKS_KEY, null);
if (blocks == null)
blocks = new HashMap<String, List<IDIYComponent<?>>>();
List<IDIYComponent<?>> blockComponents = new ArrayList<IDIYComponent<?>>(this.selectedComponents);
Collections.sort(blockComponents, new Comparator<IDIYComponent<?>>() {
@Override
public int compare(IDIYComponent<?> o1, IDIYComponent<?> o2) {
return new Integer(currentProject.getComponents().indexOf(o1)).compareTo(currentProject.getComponents()
.indexOf(o2));
}
});
blocks.put(blockName, blockComponents);
if (System.getProperty("org.diylc.WriteStaticBlocks", "false").equalsIgnoreCase("true")) {
Map<String, List<IDIYComponent<?>>> defaultBlockMap = new HashMap<String, List<IDIYComponent<?>>>();
// unify default and user-variants
for (Map.Entry<String, List<IDIYComponent<?>>> entry : blocks.entrySet()) {
if (defaultBlockMap.containsKey(entry.getKey())) {
defaultBlockMap.get(entry.getKey()).addAll(entry.getValue());
} else {
defaultBlockMap.put(entry.getKey(), entry.getValue());
}
}
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("blocks.xml"));
XStream xStream = new XStream(new DomDriver());
xStream.addPermission(AnyTypePermission.ANY);
xStream.toXML(defaultBlockMap, out);
out.close();
// no more user variants
configManager.writeValue(BLOCKS_KEY, null);
LOG.info("Saved default blocks");
} catch (IOException e) {
LOG.error("Could not save default blocks", e);
}
} else {
configManager.writeValue(BLOCKS_KEY, blocks);
}
buildingBlockManager.saveSelectionAsBlock(blockName, this.getSelectedComponents(), this.currentProject.getComponents());
}
@SuppressWarnings("unchecked")
@Override
public void loadBlock(String blockName) throws InvalidBlockException {
LOG.debug(String.format("loadBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(BLOCKS_KEY, null);
if (blocks != null) {
Collection<IDIYComponent<?>> components = blocks.get(blockName);
if (components == null)
throw new InvalidBlockException();
// clear potential control point every time!
instantiationManager.setPotentialControlPoint(null);
// clone components
List<IDIYComponent<?>> clones = new ArrayList<IDIYComponent<?>>();
List<IDIYComponent<?>> testComponents = new ArrayList<IDIYComponent<?>>(currentProject.getComponents());
for (IDIYComponent<?> c : components)
try {
IDIYComponent<?> clone = c.clone();
clone.setName(instantiationManager.createUniqueName(ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) clone.getClass()), testComponents));
testComponents.add(clone);
clones.add(clone);
} catch (CloneNotSupportedException e) {
LOG.error("Could not clone component: " + c);
}
// paste them to the project
pasteComponents(new ComponentTransferable(clones), true, true);
} else
throw new InvalidBlockException();
public void loadBlock(String blockName) throws InvalidBlockException {
List<IDIYComponent<?>> components = buildingBlockManager.loadBlock(blockName, currentProject.getComponents());
pasteComponents(new ComponentTransferable(components), true, true);
}
@SuppressWarnings("unchecked")
@Override
public void deleteBlock(String blockName) {
LOG.debug(String.format("deleteBlock(%s)", blockName));
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(BLOCKS_KEY, null);
if (blocks != null) {
blocks.remove(blockName);
configManager.writeValue(BLOCKS_KEY, blocks);
}
buildingBlockManager.deleteBlock(blockName);
}
@Override
@@ -3026,260 +2760,21 @@ public class Presenter implements IPlugInPort {
return extraSpace;
}
@SuppressWarnings("unchecked")
@Override
public int importVariants(String fileName) throws IOException {
LOG.debug(String.format("importVariants(%s)", fileName));
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName));
XStream xStream = projectFileManager.getXStream();
VariantPackage pkg = (VariantPackage) xStream.fromXML(in);
in.close();
if (pkg == null || pkg.getVariants().isEmpty())
return 0;
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(TEMPLATES_KEY, null);
if (variantMap == null) {
variantMap = new HashMap<String, List<Template>>();
}
for (Map.Entry<String, List<Template>> entry : pkg.getVariants().entrySet()) {
List<Template> templates;
templates = variantMap.get(entry.getKey());
if (templates == null) {
templates = new ArrayList<Template>();
variantMap.put(entry.getKey(), templates);
}
for (Template t : entry.getValue()) {
templates.add(new Template(t.getName() + " [" + pkg.getOwner() + "]", t.getValues(), t.getPoints()));
}
}
configManager.writeValue(TEMPLATES_KEY, variantMap);
LOG.info(String.format("Loaded variants for %d components", pkg.getVariants().size()));
return pkg.getVariants().size();
return variantManager.importVariants(fileName);
}
@SuppressWarnings("unchecked")
@Override
public int importBlocks(String fileName) throws IOException {
LOG.debug(String.format("importBlocks(%s)", fileName));
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName));
XStream xStream = projectFileManager.getXStream();
BuildingBlockPackage pkg = (BuildingBlockPackage) xStream.fromXML(in);
in.close();
if (pkg == null || pkg.getBlocks().isEmpty())
return 0;
Map<String, List<IDIYComponent<?>>> blocks =
(Map<String, List<IDIYComponent<?>>>) configManager.readObject(BLOCKS_KEY, null);
if (blocks == null) {
blocks = new HashMap<String, List<IDIYComponent<?>>>();
}
for (Map.Entry<String, List<IDIYComponent<?>>> entry : pkg.getBlocks().entrySet()) {
blocks.put(entry.getKey() + " [" + pkg.getOwner() + "]", entry.getValue());
}
configManager.writeValue(BLOCKS_KEY, blocks);
LOG.info(String.format("Loaded building blocks for %d components", pkg.getBlocks().size()));
return pkg.getBlocks().size();
return buildingBlockManager.importBlocks(fileName);
}
private static boolean upgradedVariants = false;
@SuppressWarnings("unchecked")
private synchronized void upgradeVariants() {
if (upgradedVariants)
return;
upgradedVariants = true;
LOG.info("Checking if variants need to be updated");
Map<String, List<Template>> lookupMap = new TreeMap<String, List<Template>>(String.CASE_INSENSITIVE_ORDER);
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(TEMPLATES_KEY, null);
if (variantMap == null)
return;
Map<String, ComponentType> typeMap = new TreeMap<String, ComponentType>(String.CASE_INSENSITIVE_ORDER);
Map<String, List<ComponentType>> componentTypes = getComponentTypes();
for (Map.Entry<String, List<ComponentType>> entry : componentTypes.entrySet())
for (ComponentType type : entry.getValue()) {
typeMap.put(type.getInstanceClass().getCanonicalName(), type);
typeMap.put(type.getCategory() + "." + type.getName(), type);
if (type.getCategory().contains("Electro-Mechanical"))
typeMap.put(type.getCategory().replace("Electro-Mechanical", "Electromechanical") + "." + type.getName(),
type);
}
Map<String, List<Template>> newVariantMap = new HashMap<String, List<Template>>();
lookupMap.putAll(variantMap);
for (Map.Entry<String, List<Template>> entry : variantMap.entrySet()) {
if (typeMap.containsKey(entry.getKey())) {
newVariantMap.put(typeMap.get(entry.getKey()).getInstanceClass().getCanonicalName(), entry.getValue()); // great,
// nothing
// to
// upgrade
} else {
LOG.warn("Could not upgrade variants for: " + entry.getKey());
}
}
configManager.writeValue(TEMPLATES_KEY, newVariantMap);
}
@SuppressWarnings("unchecked")
@Override
public List<Netlist> extractNetlists(boolean includeSwitches) throws NetlistException {
Map<Netlist, Netlist> result = new HashMap<Netlist, Netlist>();
List<Node> nodes = new ArrayList<Node>();
List<ISwitch> switches = new ArrayList<ISwitch>();
for (IDIYComponent<?> c : currentProject.getComponents()) {
ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// extract nodes
if (!(c instanceof IContinuity)) {
for (int i = 0; i < c.getControlPointCount(); i++) {
String nodeName = c.getControlPointNodeName(i);
if (nodeName != null && (!includeSwitches || !ISwitch.class.isAssignableFrom(type.getInstanceClass()))) {
nodes.add(new Node(c, i));
}
}
}
// extract switches
if (includeSwitches && ISwitch.class.isAssignableFrom(type.getInstanceClass()))
switches.add((ISwitch) c);
}
// save us the trouble
if (nodes.isEmpty())
return null;
// if there are no switches, make one with 1 position so we get 1 result back
if (switches.isEmpty())
switches.add(new ISwitch() {
@Override
public String getPositionName(int position) {
return "Default";
}
@Override
public int getPositionCount() {
return 1;
}
@Override
public boolean arePointsConnected(int index1, int index2, int position) {
return false;
}
});
// construct all possible combinations
int[] positions = new int[switches.size()];
for (int i = 0; i < switches.size(); i++)
positions[i] = 0;
// grab continuity areas
List<Area> continuityAreas = drawingManager.getContinuityAreas(currentProject);
int i = switches.size() - 1;
int totalSwitchCombinations = switches.stream()
.map(sw -> sw.getPositionCount())
.reduce(1, (a, b) -> a * b);
if (totalSwitchCombinations > MAX_SWITCH_COMBINATIONS) {
throw new NetlistException(String.format(MAX_SWITCH_COMBINATIONS_ERROR, MAX_SWITCH_COMBINATIONS, totalSwitchCombinations));
}
while (i >= 0) {
// process the current combination
Map<ISwitch, Integer> switchPositions = new HashMap<ISwitch, Integer>();
List<Position> posList = new ArrayList<Position>();
for (int j = 0; j < positions.length; j++) {
switchPositions.put(switches.get(j), positions[j]);
posList.add(new Position(switches.get(j), positions[j]));
}
List<Connection> connections = getConnections(switchPositions);
Netlist netlist = NetlistBuilder.buildNetlist(currentProject.getComponents(), nodes, continuityAreas, connections);
// merge graphs that are effectively the same
if (result.containsKey(netlist)) {
result.get(netlist).getSwitchSetup().add(new SwitchSetup(posList));
} else {
netlist.getSwitchSetup().add(new SwitchSetup(posList));
result.put(netlist, netlist);
}
// find the next combination if possible
if (positions[i] < switches.get(i).getPositionCount() - 1) {
positions[i]++;
} else {
while (i >= 0 && positions[i] == switches.get(i).getPositionCount() - 1)
i--;
if (i >= 0) {
positions[i]++;
for (int j = i + 1; j < positions.length; j++)
positions[j] = 0;
i = switches.size() - 1;
}
}
}
// sort everything alphabetically
List<Netlist> netlists = new ArrayList<Netlist>(result.keySet());
Collections.sort(netlists);
return netlists;
}
@SuppressWarnings({"unchecked", "unlikely-arg-type"})
private List<Connection> getConnections(Map<ISwitch, Integer> switchPositions) {
Set<Connection> connections = new TreeSet<Connection>();
for (IDIYComponent<?> c : currentProject.getComponents()) {
ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// handle direct connections
if (c instanceof IContinuity) {
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (((IContinuity) c).arePointsConnected(i, j))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
}
// handle switches
if (ISwitch.class.isAssignableFrom(type.getInstanceClass()) && switchPositions.containsKey(c)) {
int position = switchPositions.get(c);
ISwitch s = (ISwitch) c;
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (s.arePointsConnected(i, j, position))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
}
}
return new ArrayList<Connection>(connections);
return NetlistBuilder.extractNetlists(includeSwitches, currentProject, continuityAreas);
}
@Override
@@ -3312,30 +2807,7 @@ public class Presenter implements IPlugInPort {
@Override
public List<INetlistParser> getNetlistParserDefinitions() {
Set<Class<?>> classes;
try {
classes = Utils.getClasses("org.diylc.netlist");
List<INetlistParser> result = new ArrayList<INetlistParser>();
for (Class<?> clazz : classes) {
if (!Modifier.isAbstract(clazz.getModifiers()) && INetlistParser.class.isAssignableFrom(clazz)) {
result.add((INetlistParser) clazz.newInstance());
}
}
Collections.sort(result, new Comparator<INetlistParser>() {
@Override
public int compare(INetlistParser o1, INetlistParser o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
return result;
} catch (Exception e) {
LOG.error("Could not load INetlistParserDefinition implementations", e);
return null;
}
return ReflectionUtils.getNetlistParserDefinitions();
}
// Test stuff
@@ -0,0 +1,258 @@
/*
*
l * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.presenter;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.common.ComponentType;
import org.diylc.common.IPlugInPort;
import org.diylc.common.VariantPackage;
import org.diylc.core.Template;
import org.diylc.serialization.ProjectFileManager;
import com.thoughtworks.xstream.XStream;
public class VariantManager {
private static final String VARIANTS_FILE_NAME = "variants.xml";
private static final Logger LOG = Logger.getLogger(VariantManager.class);
private IConfigurationManager<?> configManager;
private XStream xStream;
public VariantManager(IConfigurationManager<?> configManager, XStream xStream) {
super();
this.configManager = configManager;
this.xStream = xStream;
}
@SuppressWarnings("unchecked")
public void importDefaultVariants() {
// import default templates from variants.xml file only if we didn't do it already
if (!configManager.readBoolean(IPlugInPort.DEFAULT_TEMPLATES_IMPORTED_KEY, false)) {
try {
URL resource = Presenter.class.getResource(VARIANTS_FILE_NAME);
if (resource != null) {
BufferedInputStream in = new BufferedInputStream(resource.openStream());
Map<String, List<Template>> defaults = (Map<String, List<Template>>) ProjectFileManager.xStreamSerializer.fromXML(in);
in.close();
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(IPlugInPort.TEMPLATES_KEY, null);
if (variantMap == null)
variantMap = new HashMap<String, List<Template>>();
// merge default variants with user's
for (Map.Entry<String, List<Template>> entry : defaults.entrySet()) {
List<Template> templates = variantMap.getOrDefault(entry.getKey(), null);
if (templates == null) {
templates = new ArrayList<Template>();
variantMap.put(entry.getKey(), templates);
}
templates.addAll(entry.getValue());
}
// update templates and a flag marking that we imported them
configManager.writeValue(IPlugInPort.DEFAULT_TEMPLATES_IMPORTED_KEY, true);
configManager.writeValue(IPlugInPort.TEMPLATES_KEY, variantMap);
LOG.info(String.format("Imported default variants for %d components",
defaults == null ? 0 : defaults.size()));
}
} catch (Exception e) {
LOG.error("Could not load default variants", e);
}
}
}
private static boolean upgradedVariants = false;
@SuppressWarnings("unchecked")
public synchronized void upgradeVariants(Map<String, List<ComponentType>> componentTypes) {
if (upgradedVariants)
return;
upgradedVariants = true;
LOG.info("Checking if variants need to be updated");
Map<String, List<Template>> lookupMap = new TreeMap<String, List<Template>>(String.CASE_INSENSITIVE_ORDER);
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(IPlugInPort.TEMPLATES_KEY, null);
if (variantMap == null)
return;
Map<String, ComponentType> typeMap = new TreeMap<String, ComponentType>(String.CASE_INSENSITIVE_ORDER);
for (Map.Entry<String, List<ComponentType>> entry : componentTypes.entrySet())
for (ComponentType type : entry.getValue()) {
typeMap.put(type.getInstanceClass().getCanonicalName(), type);
typeMap.put(type.getCategory() + "." + type.getName(), type);
if (type.getCategory().contains("Electro-Mechanical"))
typeMap.put(type.getCategory().replace("Electro-Mechanical", "Electromechanical") + "." + type.getName(),
type);
}
Map<String, List<Template>> newVariantMap = new HashMap<String, List<Template>>();
lookupMap.putAll(variantMap);
for (Map.Entry<String, List<Template>> entry : variantMap.entrySet()) {
if (typeMap.containsKey(entry.getKey())) {
newVariantMap.put(typeMap.get(entry.getKey()).getInstanceClass().getCanonicalName(), entry.getValue()); // great,
// nothing
// to
// upgrade
} else {
LOG.warn("Could not upgrade variants for: " + entry.getKey());
}
}
configManager.writeValue(IPlugInPort.TEMPLATES_KEY, newVariantMap);
}
@SuppressWarnings("unchecked")
public List<Template> getVariantsFor(ComponentType type) {
Map<String, List<Template>> lookupMap = new TreeMap<String, List<Template>>(String.CASE_INSENSITIVE_ORDER);
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(IPlugInPort.TEMPLATES_KEY, null);
if (variantMap != null)
lookupMap.putAll(variantMap);
// try by class name and then by old category.type format
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
List<Template> variants = new ArrayList<Template>();
if (variantMap != null) {
List<Template> userVariants = variantMap.get(key1);
if (userVariants != null && !userVariants.isEmpty())
variants.addAll(userVariants);
userVariants = variantMap.get(key2);
if (userVariants != null && !userVariants.isEmpty())
variants.addAll(userVariants);
}
Collections.sort(variants, new Comparator<Template>() {
@Override
public int compare(Template o1, Template o2) {
return o1.getName().compareTo(o2.getName());
}
});
return variants;
}
@SuppressWarnings("unchecked")
public int importVariants(String fileName) throws IOException {
LOG.debug(String.format("importVariants(%s)", fileName));
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName));
VariantPackage pkg = (VariantPackage) xStream.fromXML(in);
in.close();
if (pkg == null || pkg.getVariants().isEmpty())
return 0;
Map<String, List<Template>> variantMap =
(Map<String, List<Template>>) configManager.readObject(IPlugInPort.TEMPLATES_KEY, null);
if (variantMap == null) {
variantMap = new HashMap<String, List<Template>>();
}
for (Map.Entry<String, List<Template>> entry : pkg.getVariants().entrySet()) {
List<Template> templates;
templates = variantMap.get(entry.getKey());
if (templates == null) {
templates = new ArrayList<Template>();
variantMap.put(entry.getKey(), templates);
}
for (Template t : entry.getValue()) {
templates.add(new Template(t.getName() + " [" + pkg.getOwner() + "]", t.getValues(), t.getPoints()));
}
}
configManager.writeValue(IPlugInPort.TEMPLATES_KEY, variantMap);
LOG.info(String.format("Loaded variants for %d components", pkg.getVariants().size()));
return pkg.getVariants().size();
}
@SuppressWarnings("unchecked")
public String getDefaultVariant(ComponentType type) {
Map<String, String> defaultTemplateMap =
(Map<String, String>) configManager.readObject(IPlugInPort.DEFAULT_TEMPLATES_KEY, null);
if (defaultTemplateMap == null)
return null;
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
if (defaultTemplateMap.containsKey(key1))
return defaultTemplateMap.get(key1);
return defaultTemplateMap.get(key2);
}
@SuppressWarnings("unchecked")
public void deleteVariant(ComponentType type, String templateName) {
LOG.debug(String.format("deleteTemplate(%s, %s)", type, templateName));
Map<String, List<Template>> templateMap =
(Map<String, List<Template>>) configManager.readObject(IPlugInPort.TEMPLATES_KEY, null);
if (templateMap != null) {
// try by class name and then by old category.type format
String key1 = type.getInstanceClass().getCanonicalName();
String key2 = type.getCategory() + "." + type.getName();
List<Template> templates = templateMap.get(key1);
if (templates != null) {
Iterator<Template> i = templates.iterator();
while (i.hasNext()) {
Template t = i.next();
if (t.getName().equalsIgnoreCase(templateName)) {
i.remove();
}
}
}
templates = templateMap.get(key2);
if (templates != null) {
Iterator<Template> i = templates.iterator();
while (i.hasNext()) {
Template t = i.next();
if (t.getName().equalsIgnoreCase(templateName)) {
i.remove();
}
}
}
}
configManager.writeValue(IPlugInPort.TEMPLATES_KEY, templateMap);
}
}
@@ -65,6 +65,7 @@ public class Pair<A, B> {
return false;
if (getClass() != obj.getClass())
return false;
@SuppressWarnings("rawtypes")
Pair other = (Pair) obj;
if (first == null) {
if (other.first != null)
@@ -0,0 +1,91 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2018 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.utils;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.Utils;
import org.diylc.core.annotations.IAutoCreator;
import org.diylc.netlist.INetlistParser;
import org.diylc.presenter.Presenter;
public class ReflectionUtils {
private static final Logger LOG = Logger.getLogger(Presenter.class);
/**
* {@link List} of {@link IAutoCreator} objects that are capable of creating more components
* automatically when a component is created, e.g. Solder Pads.
*/
private static List<IAutoCreator> autoCreators;
public static List<IAutoCreator> getAutoCreators() {
if (autoCreators == null) {
autoCreators = new ArrayList<IAutoCreator>();
Set<Class<?>> classes = null;
try {
classes = Utils.getClasses("org.diylc.components.autocreate");
for (Class<?> clazz : classes) {
if (IAutoCreator.class.isAssignableFrom(clazz)) {
autoCreators.add((IAutoCreator) clazz.newInstance());
LOG.debug("Loaded auto-creator: " + clazz.getName());
}
}
} catch (Exception e) {
LOG.error("Error loading auto-creator types", e);
}
}
return autoCreators;
}
public static List<INetlistParser> getNetlistParserDefinitions() {
Set<Class<?>> classes;
try {
classes = Utils.getClasses("org.diylc.netlist");
List<INetlistParser> result = new ArrayList<INetlistParser>();
for (Class<?> clazz : classes) {
if (!Modifier.isAbstract(clazz.getModifiers()) && INetlistParser.class.isAssignableFrom(clazz)) {
result.add((INetlistParser) clazz.newInstance());
}
}
Collections.sort(result, new Comparator<INetlistParser>() {
@Override
public int compare(INetlistParser o1, INetlistParser o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
return result;
} catch (Exception e) {
LOG.error("Could not load INetlistParserDefinition implementations", e);
return null;
}
}
}
@@ -36,6 +36,7 @@ import org.diylc.components.guitar.JazzBassPickup;
import org.diylc.components.guitar.P90Pickup;
import org.diylc.components.guitar.PBassPickup;
import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.guitar.StingrayBassPickup;
import org.diylc.components.passive.AxialFilmCapacitor;
import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.RadialCeramicDiskCapacitor;
@@ -60,6 +61,7 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
PICKUP_TYPES.add(P90Pickup.class.getCanonicalName());
PICKUP_TYPES.add(JazzBassPickup.class.getCanonicalName());
PICKUP_TYPES.add(PBassPickup.class.getCanonicalName());
PICKUP_TYPES.add(StingrayBassPickup.class.getCanonicalName());
CAP_TYPES.add(RadialCeramicDiskCapacitor.class.getCanonicalName());
CAP_TYPES.add(RadialFilmCapacitor.class.getCanonicalName());