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() {
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                    return true;
099                }
100            }
101        }
102        
103        for (NamedBeanHandle<SignalHead> handle : list) {
104            if ( isSignalClear(handle) ) {
105                lockLogger.setStatus(this, "Locked due to route including signal "+handle.getBean().getDisplayName());
106                return false;
107            }
108        }
109        lockLogger.setStatus(this, "");
110        return true;
111    }
112    
113    boolean isSignalClear(@Nonnull NamedBeanHandle<SignalHead> handle) {
114        return handle.getBean().getState() != SignalHead.RED;
115    }
116}