001package jmri.jmrit.ussctc; 002 003import java.util.*; 004import javax.annotation.Nonnull; 005import jmri.*; 006 007/** 008 * Lock if any of the SignalHeads controlling traffic over a turnout are not at stop. 009 * <p> 010 * This checks SignalHeads for RED; it locks against Restricting (FLASHRED) but you can 011 * change that by overriding the checkSignalClear() method. 012 * 013 * @author Bob Jacobsen Copyright (C) 2007, 2017 014 */ 015public class RouteLock implements Lock { 016 017 /** 018 * @param list SignalHeads that cover this route 019 */ 020 public RouteLock(@Nonnull List<NamedBeanHandle<SignalHead>> list) { 021 this.list = list; 022 this.beans = null; 023 } 024 025 /** 026 * @param list SignalHeads that cover this route 027 * @param beans Defines the specific route 028 */ 029 public RouteLock(@Nonnull List<NamedBeanHandle<SignalHead>> list, @Nonnull List<BeanSetting> beans) { 030 this.list = list; 031 this.beans = beans; 032 } 033 034 /** 035 * @param array User or system names of SignalHeads that cover this route 036 */ 037 public RouteLock(@Nonnull String[] array) { 038 NamedBeanHandleManager hm = InstanceManager.getDefault(NamedBeanHandleManager.class); 039 SignalHeadManager sm = InstanceManager.getDefault(SignalHeadManager.class); 040 041 ArrayDeque<NamedBeanHandle<SignalHead>> q = new ArrayDeque<>(); 042 for (String s : array) { 043 SignalHead sig = sm.getSignalHead(s); 044 if (sig != null) { 045 q.add(hm.getNamedBeanHandle(s, sig)); 046 } 047 } 048 this.list = q; 049 this.beans = null; 050 } 051 052 /** 053 * @param array User or system names of SignalHeads that cover this route 054 * @param beans Defines the specific route 055 */ 056 public RouteLock(@Nonnull String[] array, @Nonnull BeanSetting[] beans) { 057 NamedBeanHandleManager hm = InstanceManager.getDefault(NamedBeanHandleManager.class); 058 SignalHeadManager sm = InstanceManager.getDefault(SignalHeadManager.class); 059 060 ArrayDeque<NamedBeanHandle<SignalHead>> q1 = new ArrayDeque<>(); 061 for (String s : array) { 062 SignalHead sig = sm.getSignalHead(s); 063 if (sig != null) { 064 q1.add(hm.getNamedBeanHandle(s, sig)); 065 } 066 } 067 this.list = q1; 068 069 ArrayDeque<BeanSetting> q2 = new ArrayDeque<>(); 070 for (BeanSetting bean : beans) { 071 q2.add(bean); 072 } 073 this.beans = q2; 074 075 } 076 077 /** 078 * @param head User or system name of a SignalHead that covers this route 079 */ 080 public RouteLock(@Nonnull String head) { 081 this(new String[]{head}); 082 } 083 084 Iterable<NamedBeanHandle<SignalHead>> list; 085 Iterable<BeanSetting> beans; 086 087 /** 088 * Test the lock conditions 089 * @return True if lock is clear and operation permitted 090 */ 091 @Override 092 public boolean isLockClear(LockLogger lockLogger) { 093 // if this route isn't in effect, then permitted 094 if (beans != null) { 095 for (BeanSetting bean : beans) { 096 if ( ! bean.check()) { 097 lockLogger.setStatus(this, ""); 098 log.debug("RouteLock OK because {} doesn't match, route not engaged", bean.getBeanName()); 099 return true; 100 } 101 } 102 } 103 104 for (NamedBeanHandle<SignalHead> handle : list) { 105 if ( isSignalClear(handle) ) { 106 lockLogger.setStatus(this, "Locked due to route including signal "+handle.getBean().getDisplayName()); 107 log.debug("RouteLock locked due to route including signal {} set clear", handle.getBean().getDisplayName()); 108 return false; 109 } 110 } 111 lockLogger.setStatus(this, ""); 112 log.debug("RouteLock OK, no signals set clear"); 113 return true; 114 } 115 116 boolean isSignalClear(@Nonnull NamedBeanHandle<SignalHead> handle) { 117 return handle.getBean().getState() != SignalHead.RED; 118 } 119 120 @Override 121 public String toString() { 122 String retval = isLockClear(debugLockLogger) ? "clear " : "locked"; 123 retval = retval+debugLockLogger.memory.getValue(); 124 return retval; 125 } 126 127 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteLock.class); 128}