public void testVariableExistsNotOk() {
    HashMap<String, CvValue> v = createCvMap();
    CvValue cv = new CvValue("81", p);
    cv.setValue(3);
    v.put("81", cv);
    // create a variable pointed at CV 81, check name
    VariableValue variable =
        makeVar(
            "label check",
            "comment",
            "",
            false,
            false,
            false,
            false,
            "81",
            "XXVVVVVV",
            0,
            255,
            v,
            null,
            "item check");

    // test Exists
    ArithmeticQualifier aq = new TestArithmeticQualifier(variable, 0, "exists");
    Assert.assertEquals(false, aq.currentDesiredState());
  }
  public void actionPerformed(ActionEvent e) {
    // see if this is from _value itself, or from an alternate rep.
    // if from an alternate rep, it will contain the value to select
    if (log.isDebugEnabled()) {
      log.debug(label() + " start action event: " + e);
    }
    if (!(e.getActionCommand().equals(""))) {
      // is from alternate rep
      _value.setSelectedItem(e.getActionCommand());
      if (log.isDebugEnabled()) {
        log.debug(label() + " action event was from alternate rep");
      }
      // match and select in tree
      for (int i = 0; i < _valueArray.length; i++) {
        if (e.getActionCommand().toString().equals(_itemArray[i])) {
          // now select in the tree
          TreePath path = _pathArray[i];
          for (JTree tree : trees) {
            tree.setSelectionPath(path);
            // ensure selection is in visible portion of JScrollPane
            tree.scrollPathToVisible(path);
          }
          break; // first one is enough
        }
      }
    }

    int oldVal = getIntValue();

    // called for new values - set the CV as needed
    CvValue cv = _cvMap.get(getCvNum());
    // compute new cv value by combining old and request
    int oldCv = cv.getValue();
    int newVal = getIntValue();
    int newCv = newValue(oldCv, newVal, getMask());
    if (newCv != oldCv) {
      cv.setValue(newCv); // to prevent CV going EDITED during loading of decoder file

      // notify  (this used to be before setting the values)
      if (log.isDebugEnabled()) {
        log.debug(label() + " about to firePropertyChange");
      }
      prop.firePropertyChange("Value", null, Integer.valueOf(oldVal));
      if (log.isDebugEnabled()) {
        log.debug(label() + " returned to from firePropertyChange");
      }
    }
    if (log.isDebugEnabled()) {
      log.debug(
          label()
              + " end action event saw oldCv="
              + oldCv
              + " newVal="
              + newVal
              + " newCv="
              + newCv);
    }
  }
 public void lastItem() {
   _value = new JComboBox<String>(_itemArray);
   // finish initialization
   _value.setActionCommand("");
   _defaultColor = _value.getBackground();
   _value.setBackground(COLOR_UNKNOWN);
   _value.setOpaque(true);
   // connect to the JComboBox model and the CV so we'll see changes.
   _value.addActionListener(this);
   CvValue cv = _cvMap.get(getCvNum());
   cv.addPropertyChangeListener(this);
   cv.setState(CvValue.FROMFILE);
 }
  // handle incoming parameter notification
  public void propertyChange(java.beans.PropertyChangeEvent e) {
    // notification from CV; check for Value being changed
    if (e.getPropertyName().equals("Busy")) {
      if (((Boolean) e.getNewValue()).equals(Boolean.FALSE)) {
        setToRead(false);
        setToWrite(false); // some programming operation just finished
        setBusy(false);
      }
    } else if (e.getPropertyName().equals("State")) {
      CvValue cv = _cvMap.get(getCvNum());
      if (cv.getState() == STORED) {
        setToWrite(false);
      }
      if (cv.getState() == READ) {
        setToRead(false);
      }
      setState(cv.getState());
      for (JTree tree : trees) {
        tree.setBackground(_value.getBackground());
        // tree.setOpaque(true);
      }

    } else if (e.getPropertyName().equals("Value")) {
      // update value of Variable
      CvValue cv = _cvMap.get(getCvNum());
      int newVal = (cv.getValue() & maskVal(getMask())) >>> offsetVal(getMask());
      setValue(newVal); // check for duplicate done inside setVal
    }
  }
 // abstract members invoked by tests in parent VariableValueTest class
 VariableValue makeVar(
     String label,
     String comment,
     String cvName,
     boolean readOnly,
     boolean infoOnly,
     boolean writeOnly,
     boolean opsOnly,
     String cvNum,
     String mask,
     int minVal,
     int maxVal,
     HashMap<String, CvValue> v,
     JLabel status,
     String item) {
   // make sure next CV exists
   CvValue cvNext = new CvValue(cvNum + 1, p);
   cvNext.setValue(0);
   v.put(cvNum + 1, cvNext);
   return new CompositeVariableValue(
       label, comment, "", readOnly, infoOnly, writeOnly, opsOnly, cvNum, mask, minVal, maxVal, v,
       status, item);
 }
  // handle incoming parameter notification
  public void propertyChange(java.beans.PropertyChangeEvent e) {
    if (log.isDebugEnabled()) {
      log.debug("property changed event - name: " + e.getPropertyName());
    }
    // notification from CV; check for Value being changed
    if (e.getPropertyName().equals("Busy") && ((Boolean) e.getNewValue()).equals(Boolean.FALSE)) {
      // busy transitions drive the state
      switch (_progState) {
        case IDLE: // no, just a CV update
          if (log.isDebugEnabled()) {
            log.error("Busy goes false with state IDLE");
          }
          return;
        case WRITING_PI4R: // have written the PI, now write SI if needed
        case WRITING_PI4C:
        case WRITING_PI4W:
          if (log.isDebugEnabled()) {
            log.debug("Busy goes false with state WRITING_PI");
          }

          // check for success
          if ((retries < RETRY_MAX)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.STORED)) {
            // need to retry on error; leave progState as it was
            log.debug("retry");
            retries++;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).writePI(_status);
            return;
          }
          // success, move on to next
          retries = 0;

          if (_progState == WRITING_PI4R) {
            _progState = WRITING_SI4R;
          } else if (_progState == WRITING_PI4C) {
            _progState = WRITING_SI4C;
          } else {
            _progState = WRITING_SI4W;
          }
          (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).writeSI(_status);
          return;
        case WRITING_SI4R:
        case WRITING_SI4C:
        case WRITING_SI4W: // have written SI if needed, now read or write CV
          if (log.isDebugEnabled()) {
            log.debug("Busy goes false with state WRITING_SI");
          }

          // check for success
          if ((retries < RETRY_MAX)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.STORED)) {
            // need to retry on error; leave progState as it was
            log.debug("retry");
            retries++;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).writeSI(_status);
            return;
          }
          // success, move on to next
          retries = 0;

          if (_progState == WRITING_SI4R) {
            _progState = READING_CV;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).readIcV(_status);
          } else if (_progState == WRITING_SI4C) {
            _progState = COMPARE_CV;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).confirmIcV(_status);
          } else {
            _progState = WRITING_CV;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).writeIcV(_status);
          }
          return;
        case READING_CV: // now done with the read request
          if (log.isDebugEnabled()) {
            log.debug("Finished reading the Indexed CV");
          }

          // check for success
          if ((retries < RETRY_MAX)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.READ)) {
            // need to retry on error; leave progState as it was
            log.debug("retry");
            retries++;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).readIcV(_status);
            return;
          }
          // success, move on to next
          retries = 0;

          _progState = IDLE;
          if (doHigh) {
            doHigh = false;
            programmingLow = false;
            doRead();
          } else if (doLow) {
            doLow = false;
            programmingLow = true;
            doRead();
          } else {
            programmingLow = true;
            setBusy(false);
          }
          return;
        case COMPARE_CV: // now done with the read request
          if (log.isDebugEnabled()) {
            log.debug("Finished reading the Indexed CV for compare");
          }

          // check for success SAME or DIFF?
          if ((retries < RETRY_MAX)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.SAME)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.DIFF)) {
            // need to retry on error; leave progState as it was
            log.debug("retry");
            retries++;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).confirmIcV(_status);
          }
          return;
        case WRITING_CV: // now done with the write request
          if (log.isDebugEnabled()) {
            log.debug("Finished writing the Indexed CV");
          }

          // check for success
          if ((retries < RETRY_MAX)
              && ((_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).getState()
                  != CvValue.STORED)) {
            // need to retry on error; leave progState as it was
            log.debug("retry");
            retries++;
            (_cvMap.get(programmingLow ? getCvName() : mSecondCVname)).writeIcV(_status);
            return;
          }
          // success, move on to next
          retries = 0;

          _progState = IDLE;
          if (doHigh) {
            doHigh = false;
            programmingLow = false;
            doWrite();
          } else if (doLow) {
            doLow = false;
            programmingLow = true;
            doWrite();
          } else {
            super.setState(STORED);
            setBusy(false);
          }
          return;
        default: // unexpected!
          log.error("Unexpected state found: " + _progState);
          _progState = IDLE;
          return;
      }
    } else if (e.getPropertyName().equals("State")) {
      CvValue cvLow = _cvMap.get(getCvName());
      CvValue cvHigh = _cvMap.get(mSecondCVname);
      if (log.isDebugEnabled()) {
        log.debug("  found cvLow=" + cvLow + "   cvHigh=" + cvHigh);
      }
      if (log.isDebugEnabled()) {
        log.debug("CV State changed to " + cvLow.getState());
      }
      if (cvHigh.getState() == VariableValue.UNKNOWN) {
        if (cvLow.getState() == VariableValue.EDITED) {
          setState(VariableValue.EDITED);
        } else {
          setState(VariableValue.UNKNOWN);
        }
      } else {
        setState(cvLow.getState());
      }
    } else if (e.getPropertyName().equals("Value")) {
      // update value of Variable
      CvValue cv0 = _cvMap.get(getCvName());
      CvValue cv1 = _cvMap.get(mSecondCVname);
      if (log.isDebugEnabled()) {
        log.debug("  found cv0=" + cv0 + "   cv1=" + cv1);
      }
      int newVal =
          ((cv0.getValue() & lowerbitmask) >> lowerbitoffset)
              + (((cv1.getValue() & upperbitmask) * 256) >> upperbitoffset);
      if (log.isDebugEnabled()) {
        log.debug(
            "CV "
                + getCvName()
                + ","
                + getSecondCvNum()
                + " set value to "
                + newVal
                + " based on cv0="
                + cv0.getValue()
                + " cv1="
                + cv1.getValue());
      }
      setValue(newVal); // check for duplicate done inside setVal
      if (log.isDebugEnabled()) {
        log.debug(
            "CV "
                + getCvName()
                + ","
                + getSecondCvNum()
                + " in property change after setValue call, cv0="
                + cv0.getValue()
                + " cv1="
                + cv1.getValue());
      }
      // state change due to CV state change, so propagate that
      if (cv1.getState() == VariableValue.UNKNOWN) {
        if (cv0.getState() == VariableValue.EDITED) {
          setState(VariableValue.EDITED);
        } else {
          setState(VariableValue.UNKNOWN);
        }
      } else {
        setState(cv0.getState());
      }
    }
  }
  public IndexedPairVariableValue(
      String name,
      String comment,
      String cvName,
      boolean readOnly,
      boolean infoOnly,
      boolean writeOnly,
      boolean opsOnly,
      String cvNum,
      String mask,
      int minVal,
      int maxVal,
      HashMap<String, CvValue> v,
      JLabel status,
      String stdname,
      String pSecondCV,
      int pFactor,
      int pOffset,
      String uppermask,
      boolean upperFirst) {
    super(
        name, comment, cvName, readOnly, infoOnly, writeOnly, opsOnly, cvNum, mask, v, status,
        stdname);
    _mask = mask;
    _uppermask = uppermask;
    _maxVal = maxVal;
    _minVal = minVal;
    mSecondCVname = pSecondCV;
    int len = 4;
    if (maxVal > 999) {
      len = 5;
    }
    if (maxVal > 9999) {
      len = 6;
    }
    _value = new JTextField("0", len);
    _defaultColor = _value.getBackground();
    _value.setBackground(COLOR_UNKNOWN);
    _upperFirst = upperFirst;
    mFactor = pFactor;
    mOffset = pOffset;
    if (log.isDebugEnabled()) {
      log.debug(
          "CV "
              + getCvName()
              + ","
              + getSecondCvNum()
              + " mfactor "
              + mFactor
              + " and mOffset="
              + mOffset);
    }

    // connect to the JTextField value, cv
    _value.addActionListener(this);
    _value.addFocusListener(this);

    lowerbitmask = maskVal(mask);
    lowerbitoffset = offsetVal(mask);
    upperbitmask = maskVal(uppermask);

    // upper bit offset includes lower bit offset, and MSB bits missing from upper part
    upperbitoffset = offsetVal(uppermask);
    String t = mask;
    while (t.length() > 0) {
      if (!t.startsWith("V")) {
        upperbitoffset++;
      }
      t = t.substring(1);
    }
    if (log.isDebugEnabled()) {
      log.debug(
          "CV "
              + getCvName()
              + ","
              + getSecondCvNum()
              + " upper mask "
              + uppermask
              + " had offsetVal="
              + offsetVal(uppermask)
              + " so upperbitoffset="
              + upperbitoffset);
    }

    // connect for notification
    CvValue cv = (_cvMap.get(getCvName()));
    cv.addPropertyChangeListener(this);
    cv.setState(CvValue.FROMFILE);
    CvValue cv1 = (_cvMap.get(mSecondCVname));
    cv1.addPropertyChangeListener(this);
    cv1.setState(CvValue.FROMFILE);
  }
  void updatedTextField() {
    if (log.isDebugEnabled()) {
      log.debug(
          "CV " + getCvName() + "," + getSecondCvNum() + " enter updatedTextField in SplitVal");
    }
    // called for new values - set the CV as needed
    CvValue cv1 = _cvMap.get(getCvName());
    CvValue cv2 = _cvMap.get(mSecondCVname);

    int newEntry; // entered value
    try {
      newEntry = Integer.valueOf(_value.getText()).intValue();
    } catch (java.lang.NumberFormatException ex) {
      newEntry = 0;
    }

    // calculate resulting number
    int newVal = (newEntry - mOffset) / mFactor;

    // combine with existing values via mask
    if (log.isDebugEnabled()) {
      log.debug(
          "CV "
              + getCvName()
              + ","
              + getSecondCvNum()
              + " lo cv was "
              + cv1.getValue()
              + " mask="
              + lowerbitmask
              + " offset="
              + lowerbitoffset);
    }
    int newCv1 = ((newVal << lowerbitoffset) & lowerbitmask) | (~lowerbitmask & cv1.getValue());

    if (log.isDebugEnabled()) {
      log.debug(
          "CV "
              + getCvName()
              + ","
              + getSecondCvNum()
              + " hi cv was "
              + cv2.getValue()
              + " mask="
              + upperbitmask
              + " offset="
              + upperbitoffset);
    }
    int newCv2 =
        (((newVal << upperbitoffset) >> 8) & upperbitmask) | (~upperbitmask & cv2.getValue());
    if (log.isDebugEnabled()) {
      log.debug(
          "CV "
              + getCvName()
              + ","
              + getSecondCvNum()
              + " new value "
              + newVal
              + " gives first="
              + newCv1
              + " second="
              + newCv2);
    }

    // cv updates here trigger updated property changes, which means
    // we're going to get notified sooner or later.
    cv1.setValue(newCv1);
    cv2.setValue(newCv2);
    if (log.isDebugEnabled()) {
      log.debug("CV " + getCvName() + "," + getSecondCvNum() + " exit updatedTextField");
    }
  }
  // create and load the an object to test
  protected CompositeVariableValue createTestVar() {

    ProgDebugger p = new ProgDebugger();

    // create 3 CVs
    HashMap<String, CvValue> v = createCvMap();
    cv17 = new CvValue("17", p);
    cv18 = new CvValue("18", p);
    cv19 = new CvValue("19", p);
    cv17.setValue(2);
    cv18.setValue(3);
    cv18.setValue(4);
    v.put("17", cv17);
    v.put("18", cv18);
    v.put("19", cv19);

    // create variables for each CV
    var17 =
        new DecVariableValue(
            "label17",
            "comment17",
            "",
            false,
            false,
            false,
            false,
            "17",
            "VVVVVVVV",
            0,
            255,
            v,
            null,
            null);
    var18 =
        new DecVariableValue(
            "label18",
            "comment18",
            "",
            false,
            false,
            false,
            false,
            "18",
            "VVVVVVVV",
            0,
            255,
            v,
            null,
            null);
    var19 =
        new DecVariableValue(
            "label19",
            "comment19",
            "",
            false,
            false,
            false,
            false,
            "19",
            "VVVVVVVV",
            0,
            255,
            v,
            null,
            null);

    // create composite variable
    CompositeVariableValue testVar =
        new CompositeVariableValue(
            "testVariable",
            "commentTest",
            "",
            false,
            false,
            false,
            false,
            "17",
            "VVVVVVVV",
            0,
            2,
            v,
            null,
            null);

    // two choices
    testVar.addChoice("first");
    testVar.addSetting("first", "label17", var17, "11");
    testVar.addSetting("first", "label18", var18, "12");
    testVar.addSetting("first", "label19", var19, "13");

    testVar.addChoice("second");
    testVar.addSetting("second", "label17", var17, "21");
    testVar.addSetting("second", "label18", var18, "22");
    testVar.addSetting("second", "label19", var19, "23");

    testVar.addChoice("third");
    testVar.addSetting("third", "label17", var17, "123");
    testVar.addSetting("third", "label18", var18, "123");
    testVar.addSetting("third", "label19", var19, "123");

    testVar.lastItem();

    return testVar;
  }