public PrivateGroupsIndex(Dataset ds) {
      this.ds = ds;
      cs = ds.getSpecificCharacterSet();
      index = new Hashtable<Integer, PrivateGroupIndex>();

      for (Iterator it = ds.iterator(); it.hasNext(); ) {
        DcmElement el = (DcmElement) it.next();
        int tag = el.tag();
        int group = (tag >> 16) & 0xFFFF;
        int element = tag & 0xFFFF;
        if (((group & 1) != 0) && (element < 0x100)) {

          // This is a private group element that claims a block.
          try {
            String blockOwnerID = el.getString(cs);
            if ((blockOwnerID != null) && !(blockOwnerID = blockOwnerID.trim()).equals("")) {

              // Get the index of this group
              Integer gpInteger = new Integer(group);
              PrivateGroupIndex idx = index.get(gpInteger);
              if (idx == null) {
                idx = new PrivateGroupIndex();
                index.put(gpInteger, idx);
              }

              // Store the mapping for this block.
              // Note: this implementation requires that all blocks
              // within a single private group be claimed with unique IDs.
              // The standard doesn't seem to require this constraint, but
              // objects in practice seem to observe it. There is a CP
              // inprocess to require it.
              idx.put(blockOwnerID, new Integer(tag));
            }
          } catch (Exception skip) {
          }
        }
      }
    }
  private boolean checkDataset(Dataset ds) {
    boolean ok = true;
    for (Iterator it = ds.iterator(); it.hasNext(); ) {
      DcmElement el = (DcmElement) it.next();
      int tag = 0;
      try {
        tag = el.tag();
      } catch (Exception useZero) {
      }
      String command = scriptTable.get(new Integer(tag));
      if (command != null) {
        if (el.vr() == VRs.SQ) {
          Matcher processMatcher = processPattern.matcher(command);
          if (processMatcher.find()) {
            int i = 0;
            Dataset child;
            while ((child = el.getItem(i++)) != null) {
              ok &= checkDataset(child);
            }
          }
        } else {
          Matcher lookupMatcher = lookupPattern.matcher(command);
          // logger.info("Parsing: "+command);
          while (lookupMatcher.find()) {

            int nGroups = lookupMatcher.groupCount();
            String element = lookupMatcher.group(1).trim();
            String keyType = lookupMatcher.group(2).trim() + "/";
            String action = (nGroups > 2) ? lookupMatcher.group(3).trim() : "";
            String regex = (nGroups > 3) ? lookupMatcher.group(4).trim() : "";

            // logger.info("...nGroups  = "+nGroups);
            // logger.info("...element: |"+element+"|");
            // logger.info("...keyType: |"+keyType+"|");
            // logger.info("...action : |"+action+"|");
            // logger.info("...regex:   |"+regex+"|");

            int targetTag = (element.equals("this") ? tag : DicomObject.getElementTag(element));
            String targetValue = handleNull(ds.getString(targetTag));

            if (!targetValue.equals("")) {
              String key = keyType + targetValue;
              if (lutProps.getProperty(key) == null) {
                boolean there = false;
                if (action.equals("keep")
                    || action.equals("skip")
                    || action.equals("remove")
                    || action.equals("empty")
                    || action.equals("default")) there = true;
                else if (action.equals("ignore")) {
                  regex = removeQuotes(regex);
                  there = targetValue.matches(regex);
                }
                try {
                  if (!there) {
                    index.insert(key, keyType, true);
                    ok = false;
                  }
                } catch (Exception ignore) {
                }
              }
            }
          }
        }
      }
    }
    return ok;
  }