예제 #1
0
 /**
  * Update the query coverage component. Call this method if the effective selected table may have
  * changed.
  */
 private void updateQueryCoverage() {
   if (coverageModel_.isSelected()) {
     Coverage coverage;
     if (tcModel_ == null) {
       coverage = null;
     } else {
       int[] rowMap = tcModel_.getViewModel().getRowMap();
       ColumnData raData = raSelector_.getColumnData();
       ColumnData decData = decSelector_.getColumnData();
       ColumnData srData = srSelector_.getColumnData();
       if (raData != null && decData != null) {
         DatasQuerySequenceFactory qsf =
             new DatasQuerySequenceFactory(raData, decData, srData, rowMap);
         try {
           StarTable table = tcModel_.getApparentStarTable();
           ConeQueryRowSequence qseq = qsf.createQuerySequence(table);
           double resDeg = 1.0;
           coverage = new ConeQueryCoverage(qseq, resDeg);
         } catch (IOException e) {
           coverage = null;
         }
       } else {
         coverage = null;
       }
     }
     queryCoverageView_.setCoverage(coverage);
     updateOverlapCoverage();
   } else {
     queryCoverageView_.setCoverage(null);
   }
 }
예제 #2
0
  /**
   * Constructs and returns a worker thread which can perform a match as specified by the current
   * state of this component.
   *
   * @return new worker thread
   * @throws RuntimeException if the current state does not fully specify a multi query job; such
   *     exceptions will have comprehensible messages
   */
  private MatchWorker createMatchWorker() {

    /* Acquire state from this panel's GUI components. */
    String sUrl = urlField_.getText();
    if (sUrl == null || sUrl.trim().length() == 0) {
      throw new IllegalArgumentException("No " + service_.getName() + " URL given");
    }
    URL serviceUrl;
    try {
      serviceUrl = new URL(sUrl);
    } catch (MalformedURLException e) {
      throw (IllegalArgumentException)
          new IllegalArgumentException("Bad " + service_.getName() + " URL syntax: " + sUrl)
              .initCause(e);
    }
    ConeErrorPolicy erract = (ConeErrorPolicy) erractSelector_.getSelectedItem();
    TopcatModel tcModel = tcModel_;
    if (tcModel == null) {
      throw new NullPointerException("No table selected");
    }
    final StarTable inTable = tcModel.getApparentStarTable();
    int[] rowMap = tcModel.getViewModel().getRowMap();
    ColumnData raData = raSelector_.getColumnData();
    ColumnData decData = decSelector_.getColumnData();
    ColumnData srData = srSelector_.getColumnData();
    if (raData == null) {
      throw new NullPointerException("No RA column given");
    }
    if (decData == null) {
      throw new NullPointerException("No Dec column given");
    }
    Number parNum = parallelModel_.getNumber();
    int parallelism = parNum == null ? 1 : parNum.intValue();
    MulticoneMode mcMode = (MulticoneMode) modeSelector_.getSelectedItem();
    StarTableFactory tfact = ControlWindow.getInstance().getTableFactory();

    /* Assemble objects based on this information. */
    ConeSearcher searcher = service_.createSearcher(serviceUrl, tfact);
    Coverage coverage = coverageModel_.isSelected() ? service_.getCoverage(serviceUrl) : null;
    DatasQuerySequenceFactory qsf = new DatasQuerySequenceFactory(raData, decData, srData, rowMap);
    ConeMatcher matcher =
        mcMode.createConeMatcher(searcher, erract, inTable, qsf, coverage, parallelism);
    ResultHandler resultHandler =
        mcMode.createResultHandler(this, tfact.getStoragePolicy(), tcModel, inTable);

    /* Create MatchWorker encapsulating all of this. */
    MatchWorker worker = new MatchWorker(matcher, resultHandler, tcModel, inTable);

    /* Perform post-construction configuration of constituent objects
     * as required. */
    qsf.setMatchWorker(worker);
    resultHandler.setMatchWorker(worker);

    /* Return worker thread. */
    return worker;
  }
예제 #3
0
  /**
   * Takes a bit mask representing selected rows and causes it to become the Current Row Subset for
   * the given table. Usually this means creating a new Row Subset corresponding to that mask prior
   * to applying it. However, in the special case that the mask is identical to an existing subset,
   * that one will be used instead.
   *
   * @param tcModel topcat model
   * @param mask row selection mask
   * @param baseName name of the sending application
   */
  private void applyNewSubset(final TopcatModel tcModel, BitSet mask, String appName) {

    /* See if this is identical to an existing subset.  If so, don't
     * create a new one.  It's arguable whether this is the behaviour
     * that you want, but at least until we have some way to delete
     * subsets it's probably best to do it like this to cut down on
     * subset proliferation. */
    RowSubset matching = null;
    for (Iterator it = tcModel.getSubsets().iterator(); matching == null && it.hasNext(); ) {
      RowSubset rset = (RowSubset) it.next();
      int nrow = Tables.checkedLongToInt(tcModel.getDataModel().getRowCount());
      if (matches(mask, rset, nrow)) {
        matching = rset;
      }
    }

    /* If we've found an existing set with the same content,
     * apply that one. */
    if (matching != null) {
      final RowSubset rset = matching;
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              tcModel.applySubset(rset);
            }
          });
    }

    /* Otherwise make sure we have a unique name for the new subset. */
    else {
      int ipset = 0;
      for (Iterator it = tcModel.getSubsets().iterator(); it.hasNext(); ) {
        String setName = ((RowSubset) it.next()).getName();
        if (setName.matches(appName + "-[0-9]+")) {
          String digits = setName.substring(appName.length() + 1);
          ipset = Math.max(ipset, Integer.parseInt(digits));
        }
      }
      String setName = appName + '-' + (ipset + 1);

      /* Then construct, add and apply the new subset. */
      final RowSubset rset = new BitsRowSubset(setName, mask);
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              tcModel.addSubset(rset);
              tcModel.applySubset(rset);
            }
          });
    }
  }
예제 #4
0
 /**
  * Attempts to locate a table by its ID. This is currently a URL string; either one got from a
  * previous VOT_LOADURL message or one inherent in the table.
  *
  * @param tableId table identifier URL string
  * @return tableWithRows object corresponding to tableId, or null
  */
 private TableWithRows lookupTable(String tableId) {
   TableWithRows tr = (TableWithRows) idMap_.get(tableId);
   if (tr != null) {
     return tr;
   } else {
     ListModel tablesList = ControlWindow.getInstance().getTablesListModel();
     for (int i = 0; i < tablesList.getSize(); i++) {
       TopcatModel tcModel = (TopcatModel) tablesList.getElementAt(i);
       URL url = tcModel.getDataModel().getBaseTable().getURL();
       if (URLUtils.sameResource(url, URLUtils.makeURL(tableId))) {
         return new TableWithRows(tcModel, null);
       }
     }
   }
   return null;
 }
예제 #5
0
  /**
   * Sends a table to a specific list of PLASTIC listeners.
   *
   * @param tcModel the table model to broadcast
   * @param hub hub object
   * @param plasticId registration ID for this application
   * @param recipients listeners to receive it; null means do a broadcast
   */
  private void transmitTable(
      TopcatModel tcModel,
      final PlasticHubListener hub,
      final URI plasticId,
      final URI[] recipients)
      throws IOException {

    /* Write the data as a VOTable to a temporary file preparatory to
     * broadcast. */
    final File tmpfile = File.createTempFile("plastic", ".vot");
    final String tmpUrl = URLUtils.makeFileURL(tmpfile).toString();
    tmpfile.deleteOnExit();
    OutputStream ostrm = new BufferedOutputStream(new FileOutputStream(tmpfile));
    try {
      new VOTableWriter(DataFormat.TABLEDATA, true)
          .writeStarTable(tcModel.getApparentStarTable(), ostrm);
    } catch (IOException e) {
      tmpfile.delete();
      throw e;
    } finally {
      ostrm.close();
    }

    /* Store a record of the table that was broadcast with its
     * state. */
    int[] rowMap = tcModel.getViewModel().getRowMap();
    idMap_.put(tmpUrl, new TableWithRows(tcModel, rowMap));

    /* Do the broadcast, synchronously so that we don't delete the
     * temporary file too early, but in another thread so that we
     * don't block the GUI. */
    new Thread("PLASTIC table broadcast") {
      public void run() {
        List argList = Arrays.asList(new Object[] {tmpUrl, tmpUrl});
        Map responses =
            recipients == null
                ? hub.request(plasticId, MessageId.VOT_LOADURL, argList)
                : hub.requestToSubset(
                    plasticId, MessageId.VOT_LOADURL, argList, Arrays.asList(recipients));

        /* Delete the temp file. */
        tmpfile.delete();
      }
    }.start();
  }
예제 #6
0
 public ResultHandler createResultHandler(
     final JComponent parent, StoragePolicy policy, TopcatModel inTcModel, StarTable inTable) {
   final String tname = service_.getLabel() + "s(" + inTcModel.getID() + ")";
   return new RandomResultHandler(parent, policy, service_) {
     protected void processRandomResult(final StarTable table) {
       addTable(tname, table);
     }
   };
 }
예제 #7
0
  /**
   * Sets the input table whose rows will specify the multiple queries.
   *
   * @param tcModel input table
   */
  private void setInputTable(TopcatModel tcModel) {
    if (tcModel_ != null && tcListener_ != null) {
      tcModel_.removeTopcatListener(tcListener_);
    }
    tcModel_ = tcModel;
    if (tcModel_ != null && tcListener_ != null) {
      tcModel_.addTopcatListener(tcListener_);
    }

    /* Set the column selectors up to select from the correct table. */
    raSelector_.setTable(tcModel);
    decSelector_.setTable(tcModel);

    /* For the size selector, jump through some hoops.
     * Although its value has the same form as for the RA and Dec
     * selectors (value may be a JEL expression or column name),
     * in practice it will often be a constant expression, so
     * making sure that a default constant value is in place should
     * make it more obvious for users rather than leaving it blank.
     * Check if the existing value makes sense for the new table;
     * if it does, leave it, otherwise, set it to a sensible default. */
    if (srSelector_.getModel() == null) {
      srSelector_.setTable(tcModel);
      service_.setSizeDefault(srSelector_);
    } else {
      String txt = srSelector_.getStringValue();
      Object conv = srSelector_.getModel().getConverterModel().getSelectedItem();
      srSelector_.setTable(tcModel);
      ComboBoxModel srColModel = srSelector_.getModel().getColumnModel();
      assert srColModel instanceof ColumnDataComboBoxModel;
      if (srColModel instanceof ColumnDataComboBoxModel) {
        try {
          ((ColumnDataComboBoxModel) srColModel).stringToColumnData(txt);
          srSelector_.setStringValue(txt);
          srSelector_.getModel().getConverterModel().setSelectedItem(conv);
        } catch (CompilationException e) {
          service_.setSizeDefault(srSelector_);
        }
      }
    }
  }
예제 #8
0
    public ResultHandler createResultHandler(
        final JComponent parent,
        StoragePolicy policy,
        final TopcatModel inTcModel,
        StarTable inTable) {
      final int[] rowMap = inTcModel.getViewModel().getRowMap();
      return new ResultHandler() {
        public void processResult(StarTable streamTable) throws IOException {
          RowSequence rseq = streamTable.getRowSequence();
          final BitSet matchMask = new BitSet();
          try {
            while (rseq.next()) {
              long irow = ((Number) rseq.getCell(0)).longValue();
              if (irow < Integer.MAX_VALUE) {
                int jrow = rowMap == null ? (int) irow : rowMap[(int) irow];
                matchMask.set(jrow);
              }
            }
          } finally {
            rseq.close();
          }
          schedule(
              new Runnable() {
                public void run() {
                  addSubset(parent, inTcModel, matchMask);
                }
              });
        }

        /**
         * Using input from the user, adds a new (or reused) Row Subset to the given TopcatModel
         * based on a given BitSet.
         *
         * @param parent parent component
         * @param tcModel topcat model
         * @param matchMask mask for included rows
         */
        public void addSubset(JComponent parent, TopcatModel tcModel, BitSet matchMask) {
          int nmatch = matchMask.cardinality();
          Box nameLine = Box.createHorizontalBox();
          JComboBox nameSelector = tcModel.createNewSubsetNameSelector();
          nameSelector.setSelectedItem("multi" + service_.getLabel());
          nameLine.add(new JLabel("Subset name: "));
          nameLine.add(nameSelector);
          Object msg =
              new Object[] {
                "Multiple "
                    + service_.getName()
                    + " successful; "
                    + "matches found for "
                    + nmatch
                    + " rows.",
                " ",
                "Define new subset for matched rows",
                nameLine,
              };
          int opt =
              JOptionPane.showOptionDialog(
                  parent,
                  msg,
                  "Multi-" + service_.getName() + " Success",
                  JOptionPane.OK_CANCEL_OPTION,
                  JOptionPane.QUESTION_MESSAGE,
                  null,
                  null,
                  null);
          String name = getSubsetName(nameSelector);
          if (opt == JOptionPane.OK_OPTION && name != null) {
            tcModel.addSubset(new BitsRowSubset(name, matchMask));
          }
        }

        /**
         * Returns the subset name corresponding to the currently selected value of a row subset
         * selector box.
         *
         * @param rsetSelector combo box returned by TopcatModel.createNewSubsetNameSelector
         * @return subset name as string, or null
         */
        private String getSubsetName(JComboBox rsetSelector) {
          Object item = rsetSelector.getSelectedItem();
          if (item == null) {
            return null;
          } else if (item instanceof String) {
            String name = (String) item;
            return name.trim().length() > 0 ? name : null;
          } else if (item instanceof RowSubset) {
            return ((RowSubset) item).getName();
          } else {
            assert false;
            return item.toString();
          }
        }
      };
    }
예제 #9
0
  /**
   * Transmits a request for listening applications to highlight a given table row.
   *
   * @param tcModel topcat model of table to broadcast
   * @param lrow row index within tcModel
   * @param recipients array of plastic IDs for target applications; if null, broadcast will be to
   *     all
   * @return true iff message was broadcast successfully
   */
  public boolean highlightRow(TopcatModel tcModel, long lrow, URI[] recipients) throws IOException {

    /* Get the hub and ID. */
    register();
    PlasticHubListener hub = getHub();
    URI plasticId = getRegisteredId();
    int irow = Tables.checkedLongToInt(lrow);

    /* See if the table we're broadcasting the row for is any of the
     * tables we've previously broadcast.  If so, send the row using the
     * same ID. */
    boolean done = false;
    int sendRow = -1;
    String tableId = null;
    for (Iterator it = idMap_.entrySet().iterator(); !done && it.hasNext(); ) {
      Map.Entry entry = (Map.Entry) it.next();
      TableWithRows tr = (TableWithRows) entry.getValue();
      TopcatModel tcm = (TopcatModel) tr.tcModelRef_.get();
      if (tcm != null && tcm == tcModel) {
        int[] rowMap = tr.rowMap_;
        if (rowMap == null) {
          sendRow = irow;
        } else {
          for (int j = 0; j < rowMap.length; j++) {
            if (irow == rowMap[j]) {
              sendRow = j;
              break;
            }
          }
        }
        tableId = entry.getKey().toString();
        done = true;
      }
    }

    /* If that didn't result in any sends, try using the basic URL of
     * the table. */
    if (!done) {
      URL url = URLUtils.fixURL(tcModel.getDataModel().getBaseTable().getURL());
      if (url != null) {
        sendRow = irow;
        tableId = url.toString();
        done = true;
      }
    }

    /* Send the message if we've got the arguments. */
    if (done && sendRow >= 0) {
      List args =
          Arrays.asList(
              new Object[] {
                tableId, new Integer(sendRow),
              });
      if (recipients == null) {
        hub.requestAsynch(plasticId, MessageId.VOT_HIGHLIGHTOBJECT, args);
      } else {
        hub.requestToSubsetAsynch(
            plasticId, MessageId.VOT_HIGHLIGHTOBJECT, args, Arrays.asList(recipients));
      }
      return true;
    }

    /* Otherwise return failure status. */
    else {
      return false;
    }
  }
예제 #10
0
  /**
   * Sends a row subset to a specific list of PLASTIC listeners. It uses the <code>
   * ivo://votech.org/votable/showObjects</code> message.
   *
   * @param tcModel topcat model
   * @param rset row subset within tcModel
   * @param hub hub object
   * @param plasticId registration ID for this application
   * @param recipients listeners to receive it; null means do a broadcast
   */
  private void transmitSubset(
      TopcatModel tcModel,
      RowSubset rset,
      PlasticHubListener hub,
      URI plasticId,
      final URI[] recipients)
      throws IOException {

    /* See if the table we're broadcasting the set for is any of the
     * tables we've previously broadcast.  If so, send the rows using
     * the same ID. */
    boolean done = false;
    for (Iterator it = idMap_.entrySet().iterator(); it.hasNext(); ) {
      Map.Entry entry = (Map.Entry) it.next();
      String tableId = entry.getKey().toString();
      TableWithRows tr = (TableWithRows) entry.getValue();
      TopcatModel tcm = (TopcatModel) tr.tcModelRef_.get();
      if (tcm != null && tcm == tcModel) {
        List rowList = new ArrayList();

        /* Assemble a list of rows, possibly modulated by the
         * row order when the table was sent originally. */
        int[] rowMap = tr.rowMap_;
        if (rowMap == null) {
          int nrow = (int) Math.min((long) Integer.MAX_VALUE, tcModel.getDataModel().getRowCount());
          for (int i = 0; i < nrow; i++) {
            if (rset.isIncluded(i)) {
              rowList.add(new Integer(i));
            }
          }
        } else {
          int nrow = rowMap.length;
          for (int i = 0; i < nrow; i++) {
            if (rset.isIncluded(rowMap[i])) {
              rowList.add(new Integer(i));
            }
          }
        }

        /* Send the request. */
        List argList = Arrays.asList(new Object[] {tableId, rowList});
        if (recipients == null) {
          hub.requestAsynch(plasticId, MessageId.VOT_SHOWOBJECTS, argList);
        } else {
          hub.requestToSubsetAsynch(
              plasticId, MessageId.VOT_SHOWOBJECTS, argList, Arrays.asList(recipients));
        }
        done = true;
      }
    }

    /* If that didn't result in any sends, try using the basic URL of
     * the table. */
    if (!done) {
      URL url = URLUtils.fixURL(tcModel.getDataModel().getBaseTable().getURL());
      if (url != null) {
        List rowList = new ArrayList();
        int nrow = (int) Math.min((long) Integer.MAX_VALUE, tcModel.getDataModel().getRowCount());
        for (int i = 0; i < nrow; i++) {
          if (rset.isIncluded(i)) {
            rowList.add(new Integer(i));
          }
        }
        List argList = Arrays.asList(new Object[] {url.toString(), rowList});
        if (recipients == null) {
          hub.requestAsynch(plasticId, MessageId.VOT_SHOWOBJECTS, argList);
        } else {
          hub.requestToSubsetAsynch(
              plasticId, MessageId.VOT_SHOWOBJECTS, argList, Arrays.asList(recipients));
        }
      }
    }
  }