001package jmri.jmrit.whereused;
002
003import jmri.jmrit.blockboss.BlockBossLogicProvider;
004import jmri.jmrit.display.EditorManager;
005
006import java.util.Collections;
007import java.util.Enumeration;
008
009import jmri.*;
010import jmri.jmrit.blockboss.BlockBossLogic;
011import jmri.jmrit.ctc.CtcManager;
012import jmri.jmrit.display.switchboardEditor.SwitchboardEditor;
013import jmri.jmrit.entryexit.EntryExitPairs;
014import jmri.jmrit.logix.OBlockManager;
015import jmri.jmrit.logix.WarrantManager;
016import jmri.jmrit.logixng.LogixNG_Manager;
017import jmri.jmrit.logixng.ModuleManager;
018import jmri.jmrit.display.layoutEditor.LayoutBlockManager;
019/**
020 * Find references.  Each collector method calls a corresponding getUsageReport(NamedBean)
021 * in the main implementation class for the object type.  The matches are returned in an
022 * array list of NamedBeanUsageReport objects.
023 *
024 * Collectors:
025 * <ul>
026 * <li>checkAudio</li>
027 * <li>checkTurnouts</li>
028 * <li>checkLights</li>
029 * <li>checkRoutes</li>
030 * <li>checkBlocks</li>
031 * <li>checkLayoutBlocks</li>
032 * <li>checkSignalHeadLogic</li>
033 * <li>checkSignalMastLogic</li>
034 * <li>checkSignalGroups</li>
035 * <li>checkOBlocks</li>
036 * <li>checkWarrants</li>
037 * <li>checkEntryExit</li>
038 * <li>checkLogixConditionals</li>
039 * <li>checkLogixNGConditionals</li>
040 * <li>checkSections</li>
041 * <li>checkTransits</li>
042 * <li>checkPanels</li>
043 * <li>checkCTC</li>
044 * </ul>
045 *
046 * @author Dave Sand Copyright (C) 2020
047 */
048
049public class WhereUsedCollectors {
050
051    /**
052     * Create the Audio usage string.
053     * Usage keys:
054     * <ul>
055     * <li>AudioBuffer</li>
056     * </ul>
057     * @param bean The requesting bean:  Audio.
058     * @return usage string
059     */
060    static String checkAudio(NamedBean bean) {
061        StringBuilder sb = new StringBuilder();
062        InstanceManager.getDefault(AudioManager.class).getNamedBeanSet().forEach((audio) -> audio.getUsageReport(bean).forEach((report) -> {
063            if (report.usageKey.startsWith("Audio")) {  // NOI18N
064                String name = audio.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
065                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
066            }
067        }));
068        return addHeader(sb, "ReferenceAudio");  // NOI18N
069    }
070
071    /**
072     * Create the Turnout usage string.
073     * Usage keys:
074     * <ul>
075     * <li>TurnoutFeedback1</li>
076     * <li>TurnoutFeedback2</li>
077     * </ul>
078     * @param bean The requesting bean:  Sensor.
079     * @return usage string
080     */
081    static String checkTurnouts(NamedBean bean) {
082        StringBuilder sb = new StringBuilder();
083        InstanceManager.getDefault(TurnoutManager.class).getNamedBeanSet().forEach((turnout) -> {
084            int feedback = turnout.getFeedbackMode();
085            if (feedback == Turnout.ONESENSOR || feedback == Turnout.TWOSENSOR) {
086                turnout.getUsageReport(bean).forEach((report) -> {
087                    if (report.usageKey.startsWith("TurnoutFeedback")) {  // NOI18N
088                        String name = turnout.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
089                        sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
090                    }
091                });
092            }
093        });
094        return addHeader(sb, "ReferenceFeedback");  // NOI18N
095    }
096
097    /**
098     * Create the Light usage string.
099     * Usage keys:
100     * <ul>
101     * <li>LightControlSensor1</li>
102     * <li>LightControlSensor2</li>
103     * <li>LightControlSensorTimed</li>
104     * <li>LightControlTurnout</li>
105     * </ul>
106     * @param bean The requesting bean:  Sensor, Turnout.
107     * @return usage string
108     */
109    static String checkLights(NamedBean bean) {
110        StringBuilder sb = new StringBuilder();
111        InstanceManager.getDefault(LightManager.class).getNamedBeanSet().forEach((light) -> light.getUsageReport(bean).forEach((report) -> {
112            if (report.usageKey.startsWith("LightControl")) {  // NOI18N
113                String name = light.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
114                sb.append(Bundle.getMessage("ReferenceLineData", name, report.usageData));  // NOI18N
115            }
116        }));
117        return addHeader(sb, "ReferenceLightControl");  // NOI18N
118    }
119
120    /**
121     * Create the Route usage string.
122     * Usage keys:
123     * <ul>
124     * <li>RouteTurnoutOutput</li>
125     * <li>RouteSensorOutput</li>
126     * <li>RouteSensorControl</li>
127     * <li>RouteSensorAligned</li>
128     * <li>RouteTurnoutControl</li>
129     * <li>RouteTurnoutLock</li>
130     * </ul>
131     * @param bean The requesting bean:  Sensor, Turnout.
132     * @return usage string
133     */
134    static String checkRoutes(NamedBean bean) {
135        StringBuilder sb = new StringBuilder();
136        InstanceManager.getDefault(RouteManager.class).getNamedBeanSet().forEach((route) -> route.getUsageReport(bean).forEach((report) -> {
137            if (report.usageKey.startsWith("Route")) {  // NOI18N
138                String name = route.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
139                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
140            }
141        }));
142        return addHeader(sb, "ReferenceRoutes");  // NOI18N
143    }
144
145    /**
146     * Create the Block usage string.
147     * Usage keys:
148     * <ul>
149     * <li>BlockSensor</li>
150     * <li>BlockReporter</li>
151     * <li>BlockPathNeighbor</li>
152     * <li>BlockPathTurnout</li>
153     * </ul>
154     * @param bean The requesting bean:  Block (Path neighbor), Sensor, Reporter, Turnout (Path).
155     * @return usage string
156     */
157    static String checkBlocks(NamedBean bean) {
158        StringBuilder sb = new StringBuilder();
159        InstanceManager.getDefault(BlockManager.class).getNamedBeanSet().forEach((block) -> block.getUsageReport(bean).forEach((report) -> {
160            if (report.usageKey.startsWith("Block")) {  // NOI18N
161                String name = block.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
162                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
163            }
164        }));
165        return addHeader(sb, "ReferenceBlock");  // NOI18N
166    }
167
168    /**
169     * Create the LayoutBlock usage string.
170     * Usage keys:
171     * <ul>
172     * <li>LayoutBlockBlock</li>
173     * <li>LayoutBlockMemory</li>
174     * <li>LayoutBlockSensor</li>
175     * <li>LayoutBlockNeighbor</li>
176     * </ul>
177     * @param bean The requesting bean:  Block, Memory, Sensor.
178     * @return usage string
179     */
180    static String checkLayoutBlocks(NamedBean bean) {
181        StringBuilder sb = new StringBuilder();
182        InstanceManager.getDefault(LayoutBlockManager.class).getNamedBeanSet().forEach((layoutBlock) -> layoutBlock.getUsageReport(bean).forEach((report) -> {
183            if (report.usageKey.startsWith("LayoutBlock")) {  // NOI18N
184                String name = layoutBlock.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
185                sb.append(Bundle.getMessage("ReferenceLineData", name, report.usageData));  // NOI18N
186            }
187        }));
188        return addHeader(sb, "ReferenceLayoutBlock");  // NOI18N
189    }
190
191    /**
192     * Create the Signal Head Logic usage string.
193     * Usage keys:
194     * <ul>
195     * <li>SSLSignal</li>
196     * <li>SSLSensor1-5</li>
197     * <li>SSLTurnout</li>
198     * <li>SSLSignal1</li>
199     * <li>SSLSignal1Alt</li>
200     * <li>SSLSignal2</li>
201     * <li>SSLSignal2Alt</li>
202     * <li>SSLSensorWatched1</li>
203     * <li>SSLSensorWatched1Alt</li>
204     * <li>SSLSensorWatched2</li>
205     * <li>SSLSensorWatched2Alt</li>
206     * <li>SSLSensorApproach</li>
207     * </ul>
208     * @param bean The requesting bean:  Sensor, Signal Head, Turnout.
209     * @return usage string
210     */
211    static String checkSignalHeadLogic(NamedBean bean) {
212        StringBuilder sb = new StringBuilder();
213        Enumeration<BlockBossLogic> e = Collections.enumeration(InstanceManager.getDefault(BlockBossLogicProvider.class).provideAll());
214        while (e.hasMoreElements()) {
215            BlockBossLogic ssl = e.nextElement();
216            ssl.getUsageReport(bean).forEach((report) -> {
217                if (report.usageKey.startsWith("SSL")) {  // NOI18N
218                    String name = report.usageBean.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
219                    sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
220                }
221            });
222        }
223        return addHeader(sb, "ReferenceHeadSSL");  // NOI18N
224    }
225
226    /**
227     * Create the Signal Mast Logic usage string.
228     * Usage keys:
229     * <ul>
230     * <li>SMLSourceMast</li>
231     * <li>SMLDestinationMast</li>
232     * <li>SMLBlockAuto</li>
233     * <li>SMLBlockUser</li>
234     * <li>SMLTurnoutAuto</li>
235     * <li>SMLTurnoutUser</li>
236     * <li>SMLSensor</li>
237     * <li>SMLMastAuto</li>
238     * <li>SMLMastUser</li>
239     * </ul>
240     * @param bean The requesting bean:  Block, Turnout, Sensor, Signal Mast.
241     * @return usage string
242     */
243    static String checkSignalMastLogic(NamedBean bean) {
244        StringBuilder sb = new StringBuilder();
245        InstanceManager.getDefault(SignalMastLogicManager.class).getNamedBeanSet().forEach((sml) -> sml.getUsageReport(bean).forEach((report) -> {
246            String name = bean.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
247            if (report.usageKey.startsWith("SMLSource")) {  // NOI18N
248                sb.append(Bundle.getMessage("ReferenceLineData", name, Bundle.getMessage("SourceMast")));  // NOI18N
249                return;
250            }
251            if (report.usageKey.startsWith("SMLDest")) {  // NOI18N
252                sb.append(Bundle.getMessage("ReferenceLineData", name, Bundle.getMessage("DestMast")));  // NOI18N
253                return;
254            }
255            if (report.usageKey.startsWith("SML")) {  // NOI18N
256                sb.append(Bundle.getMessage("ReferenceLinePair", sml.getSourceMast().getDisplayName(), report.usageBean.getDisplayName()));  // NOI18N
257            }
258        }));
259        return addHeader(sb, "ReferenceMastSML");  // NOI18N
260    }
261
262    /**
263     * Create the Signal Group usage string.
264     * Usage keys:
265     * <ul>
266     * <li>SignalGroupMast</li>
267     * <li>SignalGroupHead</li>
268     * <li>SignalGroupHeadSensor</li>
269     * <li>SignalGroupHeadTurnout</li>
270     * </ul>
271     * @param bean The requesting bean:  Sensor, Signal Head, Signal Mast, Turnout.
272     * @return usage string
273     */
274    static String checkSignalGroups(NamedBean bean) {
275        StringBuilder sb = new StringBuilder();
276        InstanceManager.getDefault(SignalGroupManager.class).getNamedBeanSet().forEach((group) -> group.getUsageReport(bean).forEach((report) -> {
277            if (report.usageKey.startsWith("SignalGroup")) {  // NOI18N
278                String name = group.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
279                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
280            }
281        }));
282        return addHeader(sb, "ReferenceSignalGroup");  // NOI18N
283    }
284
285    /**
286     * Create the OBlock usage string.
287     * Usage keys:
288     * <ul>
289     * <li>OBlockSensor</li>
290     * <li>OBlockSensorError</li>
291     * <li>OBlockPortalNeighborOBlock</li>
292     * <li>OBlockPortalSignal</li>
293     * <li>OBlockPortalPathTurnout</li>
294     * <li>OBlockWarrant</li>
295     * </ul>
296     * @param bean The requesting bean:  OBlock (Neightbor), Sensor, SignalHead, SignalMast, Turnout, Warrant.
297     * @return usage string
298     */
299    static String checkOBlocks(NamedBean bean) {
300        StringBuilder sb = new StringBuilder();
301        InstanceManager.getDefault(OBlockManager.class).getNamedBeanSet().forEach((oblock) -> oblock.getUsageReport(bean).forEach((report) -> {
302            if (report.usageKey.startsWith("OBlock")) {  // NOI18N
303                String name = oblock.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
304                sb.append(Bundle.getMessage("ReferenceLineData", name, report.usageData));  // NOI18N
305            }
306        }));
307        return addHeader(sb, "ReferenceOBlock");  // NOI18N
308    }
309
310    /**
311     * Create the Warrant usage string.
312     * Usage keys:
313     * <ul>
314     * <li>WarrantBlocking</li>
315     * <li>WarrantBlock</li>
316     * <li>WarrantSignal</li>
317     * </ul>
318     * @param bean The requesting bean:  OBlock SignalHead, SignalMast, Warrant.
319     * @return usage string
320     */
321    static String checkWarrants(NamedBean bean) {
322        StringBuilder sb = new StringBuilder();
323        InstanceManager.getDefault(WarrantManager.class).getNamedBeanSet().forEach((warrant) -> warrant.getUsageReport(bean).forEach((report) -> {
324            if (report.usageKey.startsWith("Warrant")) {  // NOI18N
325                String name = warrant.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
326                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
327            }
328        }));
329        return addHeader(sb, "ReferenceWarrant");  // NOI18N
330    }
331
332    /**
333     * Create the Entry/Exit usage string.
334     * Usage keys:
335     * <ul>
336     * <li>EntryExitSourceSensor</li>
337     * <li>EntryExitSourceSignal</li>
338     * <li>EntryExitDestinationSensor</li>
339     * <li>EntryExitDestinationSignal</li>
340     * </ul>
341     * @param bean The requesting bean:  Sensor SignalHead, SignalMast.
342     * @return usage string
343     */
344    static String checkEntryExit(NamedBean bean) {
345        StringBuilder sb = new StringBuilder();
346        InstanceManager.getDefault(EntryExitPairs.class).getNamedBeanSet().forEach((destPoint) -> destPoint.getUsageReport(bean).forEach((report) -> {
347            if (report.usageKey.startsWith("EntryExit")) {  // NOI18N
348                String name = destPoint.getDisplayName();
349                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
350            }
351        }));
352        return addHeader(sb, "ReferenceEntryExit");  // NOI18N
353    }
354
355    /**
356     * Create the Logix/Conditional usage string.
357     * Usage keys:
358     * <ul>
359     * <li>ConditionalAction</li>
360     * <li>ConditionalVariable</li>
361     * <li>ConditionalVariableData</li>
362     * </ul>
363     * @param bean The requesting bean:  Many.
364     * @return usage string
365     */
366    static String checkLogixConditionals(NamedBean bean) {
367        StringBuilder sb = new StringBuilder();
368        InstanceManager.getDefault(LogixManager.class).getNamedBeanSet().forEach((logix) -> logix.getUsageReport(bean).forEach((report) -> {
369            if (report.usageKey.startsWith("ConditionalVariable") || report.usageKey.startsWith("ConditionalAction")) {  // NOI18N
370                String name = logix.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
371                String cdlName = report.usageBean.getDisplayName();
372                sb.append(Bundle.getMessage("ReferenceLineConditional", name, cdlName, Bundle.getMessage(report.usageKey), report.usageData));  // NOI18N
373            }
374        }));
375        return addHeader(sb, "ReferenceConditionals");  // NOI18N
376    }
377
378    /**
379     * Create the LogixNG/ConditionalNG usage string.
380     * Usage keys:
381     * <ul>
382     * <li>LogixNGAction</li>
383     * <li>LogixNGExpression</li>
384     * </ul>
385     * @param bean The requesting bean:  Many.
386     * @return usage string
387     */
388    static String checkLogixNGConditionals(NamedBean bean) {
389        StringBuilder sb = new StringBuilder();
390        InstanceManager.getDefault(LogixNG_Manager.class).getNamedBeanSet().forEach((logixng) -> logixng.getUsageReport(bean).forEach((report) -> {
391            if (report.usageKey.startsWith("LogixNG")) {  // NOI18N
392                String name = logixng.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
393                String cdlName = report.usageBean != null ? report.usageBean.getDisplayName() : "";
394                sb.append(Bundle.getMessage("ReferenceLineLogixNG", name, cdlName, Bundle.getMessage(report.usageKey), report.usageData));  // NOI18N
395            }
396        }));
397        InstanceManager.getDefault(ModuleManager.class).getNamedBeanSet().forEach((module) -> module.getUsageReport(bean).forEach((report) -> {
398            if (report.usageKey.startsWith("LogixNG")) {  // NOI18N
399                String name = module.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
400                sb.append(Bundle.getMessage("ReferenceLineModule", name, Bundle.getMessage(report.usageKey), report.usageData));  // NOI18N
401            }
402        }));
403        return addHeader(sb, "ReferenceLogixNG");  // NOI18N
404    }
405
406    /**
407     * Create the Section usage string.
408     * Usage keys:
409     * <ul>
410     * <li>SectionBlock</li>
411     * <li>SectionSensorForwardBlocking</li>
412     * <li>SectionSensorForwardStopping</li>
413     * <li>SectionSensorReverseBlocking</li>
414     * <li>SectionSensorReverseStopping</li>
415     * </ul>
416     * @param bean The requesting bean:  Block, Sensor.
417     * @return usage string
418     */
419    static String checkSections(NamedBean bean) {
420        StringBuilder sb = new StringBuilder();
421        InstanceManager.getDefault(SectionManager.class).getNamedBeanSet().forEach((section) -> section.getUsageReport(bean).forEach((report) -> {
422            if (report.usageKey.startsWith("SectionSensor")) {  // NOI18N
423                String name = section.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
424                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
425            }
426        }));
427        return addHeader(sb, "ReferenceSections");  // NOI18N
428    }
429
430    /**
431     * Create the Transit usage string.
432     * Usage keys:
433     * <ul>
434     * <li>TransitSection</li>
435     * <li>TransitSensorStopAllocation</li>
436     * <li>TransitActionSensorWhen</li>
437     * <li>TransitActionSensorWhat</li>
438     * <li>TransitActionSignalHeadWhat</li>
439     * <li>TransitActionSignalMastWhat</li>
440     * </ul>
441     * @param bean The requesting bean:  Section, Sensor, Signal Head, Signal Mast.
442     * @return usage string
443     */
444    static String checkTransits(NamedBean bean) {
445        StringBuilder sb = new StringBuilder();
446        InstanceManager.getDefault(TransitManager.class).getNamedBeanSet().forEach((transit) -> transit.getUsageReport(bean).forEach((report) -> {
447            String name = transit.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME);
448            if (report.usageKey.startsWith("TransitSensor") || report.usageKey.startsWith("TransitSection")) {  // NOI18N
449                sb.append(Bundle.getMessage("ReferenceLineName", name));  // NOI18N
450            }
451            if (report.usageKey.startsWith("TransitAction")) {  // NOI18N
452                sb.append(Bundle.getMessage("ReferenceLineAction", name, report.usageBean.getDisplayName()));  // NOI18N
453            }
454        }));
455        return addHeader(sb, "ReferenceTransits");  // NOI18N
456    }
457
458    /**
459     * Create the Panel usage string.  The string includes the icon class name.
460     * Usage keys:
461     * <ul>
462     * <li>PositionalIcon</li>
463     * <li>LayoutEditorTurnout</li>
464     * <li>LayoutEditorTurnout2</li>
465     * <li>LayoutEditorTurnoutBlock</li>
466     * <li>LayoutEditorTurnoutSensor</li>
467     * <li>LayoutEditorTurnoutSignalHead</li>
468     * <li>LayoutEditorTurnoutSignalMast</li>
469     * <li>LayoutEditorPointSensor</li>
470     * <li>LayoutEditorPointSignalHead</li>
471     * <li>LayoutEditorPointSignalMast</li>
472     * <li>LayoutEditorSegmentBlock</li>
473     * <li>LayoutEditorXingBlock</li>
474     * <li>LayoutEditorXingOther (sensor, head, mast)</li>
475     * <li>Switchboard (sensor, turnout, light)</li>
476     * </ul>
477     * Note:  The getUsageReport is invoked at either Editor or LayoutEditor depending on the
478     * panel type.  The LayoutEditor version does a super call and then does special turnout
479     * checking since LE turnouts are not icons.
480     * @param bean The requesting bean:  Many.
481     * @return usage string
482     */
483    static String checkPanels(NamedBean bean) {
484        StringBuilder sb = new StringBuilder();
485        InstanceManager.getDefault(EditorManager.class).getAll().forEach(panel ->
486            panel.getUsageReport(bean).forEach(report -> {
487                if (panel instanceof SwitchboardEditor) {
488                    sb.append(Bundle.getMessage("ReferenceLineName", report.usageData));  // NOI18N
489                } else {
490                    sb.append(Bundle.getMessage("ReferenceLinePanel", panel.getTitle(), report.usageData));  // NOI18N
491                }
492            }));
493        return addHeader(sb, "ReferencePanels");  // NOI18N
494    }
495
496    /**
497     * Create the CTC usage string.
498     * The CTC manager is found using the ConfigureManager instead of the InstanceManager.
499     * The CTC manager uses InstanceManagerAutoDefault which can result in unnecessary
500     * XML content when CTC is not being used.
501     * Usage keys:
502     * <ul>
503     * <li>CtcWhereUsedOther</li>
504     * <li>CtcWhereUsedCBHD</li>
505     * </ul>
506     * @param bean The requesting bean:  Block, Sensor, Signal Head, Signal Mast, Turnout.
507     * @return usage string
508     */
509    static String checkCTC(NamedBean bean) {
510        StringBuilder sb = new StringBuilder();
511
512        // Get the CTC manager via the ConfigureManager to avoid auto default.
513        InstanceManager.getOptionalDefault(ConfigureManager.class).ifPresent(cm -> {
514            cm.getInstanceList(CtcManager.class).forEach(m -> {
515                mgr = (CtcManager) m;
516            });
517        });
518
519        if (mgr != null) {
520            mgr.getUsageReport(bean).forEach((report) -> {
521                sb.append(Bundle.getMessage("ReferenceLineName", report.usageData));  // NOI18N
522            });
523        }
524        return addHeader(sb, "ReferenceCTC");  // NOI18N
525    }
526    static CtcManager mgr = null;
527
528    /**
529     * Add the specified section to the beginning of the string builder if there is data.
530     * @param sb The current string builder.
531     * @param bundleKey The key for the section header.
532     * @return the resulting string.
533     */
534    static String addHeader(StringBuilder sb, String bundleKey) {
535        if (sb.length() > 0) {
536            sb.insert(0, Bundle.getMessage("ReferenceHeader", Bundle.getMessage(bundleKey)));  // NOI18N
537            sb.append("\n");
538        }
539        return sb.toString();
540    }
541
542//     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WhereUsedCollectors.class);
543}