001package jmri.jmrit.logixng.util;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import jmri.InstanceManager;
007import jmri.NamedBean;
008import jmri.NamedBeanUsageReport;
009import jmri.Reference;
010import jmri.jmrit.logixng.*;
011
012/**
013 * List the places where an item is used.
014 *
015 * @author Daniel Bergqvist (C) 2023
016 */
017public class WhereUsed {
018
019
020    private static final String NEW_LINE = System.getProperty("line.separator");
021
022    private static final String PAD = "   ";
023
024
025    private WhereUsed() {
026    }
027
028
029    public static String whereUsed(NamedBean bean) {
030
031        Reference<String> ref = new Reference<>();
032
033        // Iterate all the LogixNGs
034        InstanceManager.getDefault(LogixNG_Manager.class).getNamedBeanSet().forEach((logixNG) -> {
035            StringBuilder sb = new StringBuilder();
036            for (int i=0; i < logixNG.getNumConditionalNGs(); i++) {
037                ConditionalNG conditionalNG = logixNG.getConditionalNG(i);
038                String s = checkFemaleSocket(conditionalNG.getFemaleSocket(), bean, conditionalNG, PAD+PAD);
039                if (s != null) {
040                    sb.append(PAD);
041                    sb.append(conditionalNG.getLongDescription());
042                    sb.append(NEW_LINE);
043                    sb.append(s);
044                }
045            }
046            if (sb.length() > 0) {
047                String str = logixNG.getLongDescription() + NEW_LINE + sb.toString() + NEW_LINE;
048                if (ref.get() != null) ref.set(ref.get() + str);
049                else ref.set(str);
050            }
051        });
052
053        // Iterate all the Modules
054        InstanceManager.getDefault(ModuleManager.class).getNamedBeanSet().forEach((module) -> {
055            String s = checkFemaleSocket(module.getRootSocket(), bean, null, PAD);
056            if (s != null) {
057                String str = module.getLongDescription() + NEW_LINE + s + NEW_LINE;
058                if (ref.get() != null) ref.set(ref.get() + str);
059                else ref.set(str);
060            }
061        });
062
063        String result = ref.get();
064
065        // Iterate the Clipboard
066        String s = checkFemaleSocket(InstanceManager.getDefault(LogixNG_Manager.class).getClipboard().getFemaleSocket(), bean, null, PAD);
067        if (s != null) {
068            String str = Bundle.getMessage("Clipboard") + NEW_LINE + s;
069            if (result != null) result += str;
070            else result = str;
071        }
072
073        return result != null ? result : "";
074    }
075
076    private static String checkFemaleSocket(FemaleSocket femaleSocket, NamedBean bean, ConditionalNG conditionalNG, String pad) {
077
078        if (!femaleSocket.isConnected()) return null;
079
080        Base b = femaleSocket.getConnectedSocket();
081
082        while (b instanceof MaleSocket) {
083            b = ((MaleSocket)b).getObject();
084        }
085
086        if (b == null) {
087            throw new UnsupportedOperationException("object is null");
088        }
089
090        List<NamedBeanUsageReport> report = new ArrayList<>();
091        b.getUsageDetail(0, bean, report, conditionalNG);
092
093        StringBuilder sb = new StringBuilder();
094        if (!report.isEmpty()) {
095            sb.append(pad).append(femaleSocket.getLongDescription()).append(NEW_LINE);
096            sb.append(pad).append(PAD).append(b.getLongDescription()).append("   <<====").append(NEW_LINE);
097            pad += PAD;
098        }
099
100
101        String padding = sb.length() > 0 ? pad+PAD : pad+PAD+PAD;
102
103        for (int i=0; i < b.getChildCount(); i++) {
104            String temp = checkFemaleSocket(b.getChild(i), bean, conditionalNG, padding);
105            if (temp != null) {
106                if (sb.length() == 0) {
107                    sb.append(pad).append(femaleSocket.getLongDescription()).append(NEW_LINE);
108                    sb.append(pad).append(PAD).append(b.getLongDescription()).append(NEW_LINE);
109                    pad += PAD;
110                }
111                sb.append(temp);
112            }
113        }
114
115        if (sb.length() > 0) {
116            return sb.toString();
117        } else {
118            return null;
119        }
120    }
121
122}