001package jmri.jmrit.symbolicprog;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.IOException;
006import java.util.Enumeration;
007import java.util.Properties;
008import jmri.JmriException;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012/**
013 * Import CV values from a "PR1" file written by PR1DOS or PR1WIN.
014 *
015 *
016 * <hr>
017 * This file is part of JMRI.
018 * <p>
019 * JMRI is free software; you can redistribute it and/or modify it under the
020 * terms of version 2 of the GNU General Public License as published by the Free
021 * Software Foundation. See the "COPYING" file for a copy of this license.
022 * <p>
023 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
024 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
025 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
026 *
027 * @author Alex Shepherd Copyright (C) 2003
028 */
029public class Pr1Importer {
030
031    private final static Logger log = LoggerFactory.getLogger(Pr1Importer.class);
032    private static final String VERSION_KEY = "Version";
033    private static final String CV_PREFIX = "CV";
034    private static final int CV_INDEX_OFFSET = 2;
035
036    Properties m_CVs;
037    boolean m_packedValues = false;
038
039    public Pr1Importer(File file) throws IOException {
040        m_CVs = new Properties();
041        FileInputStream fileStream = new FileInputStream(file);
042        try {
043            m_CVs.load(fileStream);
044        } finally {
045            fileStream.close();
046        }
047
048        // First check to see if the file contains a Version=x entry and if it
049        // does assume it is a PR1WIN file that has packed values
050        if (m_CVs.containsKey(VERSION_KEY)) {
051            if (m_CVs.get(VERSION_KEY).equals("0")) {
052                m_packedValues = true;
053            } else {
054                throw new IOException("Unsupported PR1 File Version");
055            }
056        } // Have a look at the values and see if there are any entries with values
057        // greater out of the range 0..255. If they are found then also assume PR1WIN
058        else {
059            Enumeration<Object> cvKeys = m_CVs.keys();
060
061            while (cvKeys.hasMoreElements()) {
062                String cvKey = (String) cvKeys.nextElement();
063                if (cvKey.startsWith(CV_PREFIX)) {
064                    String cvValue = (String) m_CVs.get(cvKey);
065                    int cvIntValue = Integer.parseInt(cvValue);
066                    if ((cvIntValue < 0) || (cvIntValue > 255)) {
067                        m_packedValues = true;
068                        return;
069                    }
070                }
071            }
072        }
073    }
074
075    public void setCvTable(CvTableModel pCvTable) {
076        Enumeration<Object> keyIterator = m_CVs.keys();
077        while (keyIterator.hasMoreElements()) {
078            String key = (String) keyIterator.nextElement();
079            if (key.startsWith(CV_PREFIX)) {
080                int Index = Integer.parseInt(key.substring(CV_INDEX_OFFSET));
081
082                int lowCV;
083                int highCV;
084
085                if (m_packedValues) {
086                    lowCV = Index * 4 - 3;
087                    highCV = Index * 4;
088                } else {
089                    lowCV = Index;
090                    highCV = Index;
091                }
092
093                for (int cvNum = lowCV; cvNum <= highCV; cvNum++) {
094                    if (cvNum <= CvTableModel.MAXCVNUM) {   // MAXCVNUM is the highest number, so is included
095                        try {
096                            CvValue cv = pCvTable.allCvMap().get("" + cvNum);
097                            if (cv != null) {
098                                cv.setValue(getCV(cvNum));
099                            }
100                        } catch (JmriException ex) {
101                            log.error("failed to getCV() {}", cvNum);
102                        } catch (ArrayIndexOutOfBoundsException ex) {
103                            log.error("failed to getCvByNumber() {}", cvNum);
104                        }
105                    }
106                }
107            }
108        }
109    }
110
111    public int getCV(int cvNumber) throws JmriException {
112        int result;
113
114        if (m_packedValues) {
115            String cvKey = CV_PREFIX + ((cvNumber / 4) + 1);
116            String cvValueStr = m_CVs.getProperty(cvKey);
117            if (cvValueStr == null) {
118                throw new JmriException("CV not found");
119            }
120
121            int shiftBits = ((cvNumber - 1) % 4) << 3;
122
123            long cvValue = Long.parseLong(cvValueStr);
124
125            if (cvValue < 0) {
126                result = (int) (((cvValue + 0x7FFFFFFF) >> shiftBits) % 256);
127                if (shiftBits > 16) {
128                    result += 127;
129                }
130            } else {
131                result = (int) ((cvValue >> shiftBits) % 256);
132            }
133        } else {
134            String cvKey = CV_PREFIX + cvNumber;
135            String cvValueStr = m_CVs.getProperty(cvKey);
136            if (cvValueStr == null) {
137                throw new JmriException("CV not found");
138            }
139
140            result = Integer.parseInt(cvValueStr);
141        }
142
143        return result;
144    }
145
146}