001package jmri.jmrit.operations.rollingstock.cars;
002
003import org.jdom2.Element;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007import jmri.InstanceManager;
008import jmri.InstanceManagerAutoDefault;
009import jmri.jmrit.operations.rollingstock.RollingStockAttribute;
010import jmri.jmrit.operations.setup.Setup;
011
012/**
013 * Represents the types of cars a railroad can have.
014 *
015 * @author Daniel Boudreau Copyright (C) 2008, 2014
016 */
017public class CarTypes extends RollingStockAttribute implements InstanceManagerAutoDefault {
018
019    private static final String TYPES = Bundle.getMessage("carTypeNames");
020    private static final String CONVERT_TYPES = Bundle.getMessage("carTypeConvert"); // Used to convert from ARR to
021    // Descriptive
022    private static final String ARR_TYPES = Bundle.getMessage("carTypeARR");
023    // for property change
024    public static final String CARTYPES_CHANGED_PROPERTY = "CarTypes Length"; // NOI18N
025    public static final String CARTYPES_NAME_CHANGED_PROPERTY = "CarTypes Name"; // NOI18N
026
027    public CarTypes() {
028    }
029
030    @Override
031    protected String getDefaultNames() {
032        if (Setup.getCarTypes().equals(Setup.AAR)) {
033            return ARR_TYPES;
034        }
035        return TYPES;
036    }
037
038    /**
039     * Changes the car types from descriptive to AAR, or the other way. Only
040     * removes the default car type names from the list
041     * @param type Setup.DESCRIPTIVE or Setup.AAR
042     */
043    public void changeDefaultNames(String type) {
044        String[] convert = CONVERT_TYPES.split(","); // NOI18N
045        String[] types = TYPES.split(","); // NOI18N
046        // this conversion has internationalization problems, so we can't call
047        // this an error.
048        if (convert.length != types.length) {
049            log.warn(
050                    "Properties file doesn't have equal length conversion strings, carTypeNames {}, carTypeConvert {}", // NOI18N
051                    types.length, convert.length);
052            return;
053        }
054        if (type.equals(Setup.DESCRIPTIVE)) {
055            // first replace the types
056            for (int i = 0; i < convert.length; i++) {
057                replaceName(convert[i], types[i]);
058            }
059            // remove AAR types
060            String[] aarTypes = ARR_TYPES.split(","); // NOI18N
061            for (int i = 0; i < aarTypes.length; i++) {
062                list.remove(aarTypes[i]);
063            }
064            // add descriptive types
065            for (int i = 0; i < types.length; i++) {
066                if (!list.contains(types[i])) {
067                    list.add(types[i]);
068                }
069            }
070        } else {
071            // first replace the types
072            for (int i = 0; i < convert.length; i++) {
073                replaceName(types[i], convert[i]);
074            }
075            // remove descriptive types
076            for (int i = 0; i < types.length; i++) {
077                list.remove(types[i]);
078            }
079            // add AAR types
080            types = ARR_TYPES.split(","); // NOI18N
081            for (int i = 0; i < types.length; i++) {
082                if (!list.contains(types[i])) {
083                    list.add(types[i]);
084                }
085            }
086        }
087    }
088
089    @Override
090    public void addName(String type) {
091        super.addName(type);
092        setDirtyAndFirePropertyChange(CARTYPES_CHANGED_PROPERTY, null, type);
093    }
094
095    @Override
096    public void deleteName(String type) {
097        super.deleteName(type);
098        setDirtyAndFirePropertyChange(CARTYPES_CHANGED_PROPERTY, type, null);
099    }
100
101    public void replaceName(String oldName, String newName) {
102        super.addName(newName);
103        setDirtyAndFirePropertyChange(CARTYPES_NAME_CHANGED_PROPERTY, oldName, newName);
104        // need to keep old name so location manager can replace properly
105        super.deleteName(oldName);
106    }
107
108    /**
109     * Get the maximum character length of a car type when printing on a
110     * manifest or switch list. Car "subtypes" or characters after the hyphen are
111     * ignored.
112     *
113     * @return the maximum character length of a car type
114     */
115    @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( value="SLF4J_FORMAT_SHOULD_BE_CONST",
116            justification="I18N of Info Message")
117    @Override
118    public int getMaxNameLength() {
119        if (maxNameSubStringLength == 0) {
120            super.getMaxNameSubStringLength();
121            log.info(Bundle.getMessage("InfoMaxType", maxName, maxNameSubStringLength));
122        }
123        return maxNameSubStringLength;
124    }
125
126    /**
127     * Get the maximum character length of a car type including the sub type
128     * characters.
129     *
130     * @return the maximum character length of a car type
131     */
132    public int getMaxFullNameLength() {
133        return super.getMaxNameLength();
134    }
135
136    /**
137     * Create an XML element to represent this Entry. This member has to remain
138     * synchronized with the detailed DTD in operations-cars.dtd.
139     * @param root The common Element for operations-cars.dtd.
140     *
141     */
142    public void store(Element root) {
143        store(root, Xml.TYPES, Xml.TYPE);
144    }
145
146    public void load(Element root) {
147        load(root, Xml.TYPES, Xml.TYPE, Xml.CAR_TYPES);
148    }
149
150    protected void setDirtyAndFirePropertyChange(String p, Object old, Object n) {
151        // Set dirty
152        InstanceManager.getDefault(CarManagerXml.class).setDirty(true);
153        super.firePropertyChange(p, old, n);
154    }
155
156    private final static Logger log = LoggerFactory.getLogger(CarTypes.class);
157
158}