//
// BasicSSCell.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.ss;

import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.rmi.*;
import java.util.*;
import javax.swing.*;
import visad.*;
import visad.bom.ImageRendererJ3D;
import visad.collab.DisplayMonitor;
import visad.data.*;
import visad.formula.*;
import visad.java2d.*;
import visad.java3d.*;
import visad.util.*;

/**
 * BasicSSCell represents a single spreadsheet display cell.
 * BasicSSCells can be added to a VisAD user interface to provide some of the
 * capabilities presented in the VisAD SpreadSheet. Other capabilities, like
 * the file loader and data mapping dialog boxes, are available only with a
 * FancySSCell.
 */
public class BasicSSCell extends JPanel
  implements DisplayListener, MessageListener
{

  /**
   * Debugging flag.
   */
  public static boolean DEBUG = false;

  /**
   * Debugging level.
   *
   * 
  • 1 = Normal. *
  • 2 = Collaboration messages. *
  • 3 = All exceptions. */ public static int DEBUG_LEVEL = 2; // --- STATIC UTILITY METHODS --- /** * List of SSCells on this JVM. */ protected static final Vector SSCellVector = new Vector(); /** * The number of SSCells currently saving data. */ protected static int Saving = 0; /** * Whether Java3D is possible for this JVM. */ protected static boolean Possible3D; /** * Whether Java3D is enabled for this JVM. */ protected static boolean CanDo3D = enable3D(); /** * Gets the SSCell with the specified name. */ public static BasicSSCell getSSCellByName(String name) { synchronized (SSCellVector) { int len = SSCellVector.size(); for (int i=0; i 0; } // -- Detect, enable & disable Java3D -- /** * Returns true if Java3D is possible for this JVM. */ public static boolean possible3D() { return Possible3D; } /** * Returns true if Java3D is enabled for this JVM. */ public static boolean canDo3D() { return CanDo3D; } /** * Attempts to enable Java3D for this JVM, returning true if successful. */ public static boolean enable3D() { if (Possible3D) { // Java3D test has already succeeded CanDo3D = true; } else { // test for Java3D availability Possible3D = CanDo3D = Util.canDoJava3D(); if (DEBUG && !Possible3D) { if (DEBUG) System.err.println("Warning: Java3D library not found"); } } return CanDo3D; } /** * Disables Java3D for this JVM. */ public static void disable3D() { CanDo3D = false; } // --- CONSTRUCTORS --- /** * Default FormulaManager object used by SSCells. */ protected static final FormulaManager defaultFM = FormulaUtil.createStandardManager(); /** * Name of this cell. */ protected String Name; /** * Formula manager for this cell. */ protected FormulaManager fm; /** * Constructs a new BasicSSCell with the given name. */ public BasicSSCell(String name) throws VisADException, RemoteException { this(name, null, null, false, null); } /** * Constructs a new BasicSSCell with the given name and non-default * formula manager, to allow for custom formulas. */ public BasicSSCell(String name, FormulaManager fman) throws VisADException, RemoteException { this(name, fman, null, false, null); } /** * Constructs a new BasicSSCell with the given name, that gets its * information from the given RemoteServer. The associated SSCell on the * server end must have already invoked its addToRemoteServer method. */ public BasicSSCell(String name, RemoteServer rs) throws VisADException, RemoteException { this(name, null, rs, false, null); } /** * Constructs a new BasicSSCell with the given name and save string, * used to reconstruct this cell's configuration. */ public BasicSSCell(String name, String save) throws VisADException, RemoteException { this(name, null, null, false, save); } /** * Constructs a new BasicSSCell with the given name, formula manager, * and remote server. */ public BasicSSCell(String name, FormulaManager fman, RemoteServer rs, String save) throws VisADException, RemoteException { this(name, fman, rs, false, save); } /** * Constructs a new, possibly slaved, BasicSSCell with the given name, * formula manager, and remote server. */ public BasicSSCell(String name, FormulaManager fman, RemoteServer rs, boolean slave, String save) throws VisADException, RemoteException { // set name if (name == null) { throw new VisADException("BasicSSCell: name cannot be null"); } synchronized (SSCellVector) { int len = SSCellVector.size(); for (int i=0; iid to server and all clients * of this cell. */ void sendMessage(int id, String msg, Data data) throws RemoteException { // convert data to remote data RemoteData d; if (data instanceof RemoteData) d = (RemoteData) data; else d = new RemoteDataImpl((DataImpl) data); MDisplay.sendMessage(new MessageEvent(MAX_ID * CollabID + id, msg, d)); if (DEBUG && DEBUG_LEVEL >= 2) { System.out.println(Name + "[" + CollabID + "]: sent " + messages[id] + ": msg=" + msg + ", data=" + (data == null ? "null" : data.getClass().getName())); } } /** * Handles VisAD messages. This method is the heart of BasicSSCell's * collaboration support. */ public void receiveMessage(MessageEvent msg) throws RemoteException { int id = msg.getId(); int mid = id % MAX_ID; int oid = id / MAX_ID; if (oid == CollabID && mid != UPDATE_DEPENDENCIES) { // cells ignore their own updates, except for UPDATE_DEPENDENCIES return; } String m = msg.getString(); RemoteData data = msg.getData(); if (DEBUG && DEBUG_LEVEL >= 2) { DataImpl ld = DataUtility.makeLocal(data, DEBUG); System.out.println(Name + "[" + CollabID + "]: received " + messages[mid] + " from " + oid + ": msg=" + m + ", data=" + (ld == null ? "null" : ld.getClass().getName())); } try { if (mid == ADD_DATA) { // add data from remote URL_SOURCE or DIRECT_SOURCE synchronized (CellData) { SSCellData cellData = addReferenceImpl(0, null, null, m, m.equals("") ? DIRECT_SOURCE : URL_SOURCE, false, false); cellData.setData(data, false); } } else if (mid == ADD_SOURCE) { // add data from remote RMI_SOURCE or FORMULA_SOURCE synchronized (CellData) { int type = (int) ((Real) DataUtility.makeLocal(data, DEBUG)).getValue(); addDataSource(0, m, type, false); } } else if (mid == REMOVE_DATA) { // remove data synchronized (CellData) { SSCellData cellData = getCellDataByName(m); removeDataImpl(cellData, false, true); } } else if (mid == SET_MAPS) { // set maps if (!IsRemote) { // SERVER: respond to client's SET_MAPS command if (m == null) clearMaps(); else setMaps(DataUtility.convertStringToMaps(m, getData(), true)); } } else if (mid == SET_DIM) { // set dimension int dim = (int) ((Real) DataUtility.makeLocal(data, DEBUG)).getValue(); if (m != null) { // SET_DIM command originates from client if (IsRemote) { // CLIENT: turn on wait dialog beginWait(true); } else { // SERVER: respond to client's SET_DIM command setDimension(dim); } } else if (IsRemote) { // CLIENT: respond to server's SET_DIM command endWait(false); setDimClone(); } } else if (mid == SET_ERRORS) { // set errors Tuple tuple = (Tuple) DataUtility.makeLocal(data, DEBUG); String[] errors = DataUtility.tupleToStrings(tuple, DEBUG); SSCellData cellData; synchronized (CellData) { cellData = getCellDataByName(m); } if (cellData != null) cellData.setErrors(errors, false); } else if (mid == UPDATE_DATA) { // update local data to match data from message SSCellData cellData; synchronized (CellData) { cellData = getCellDataByName(m); } cellData.cell.skipNextErrors(); cellData.setData(data, false); } else if (mid == UPDATE_DEPENDENCIES) { // update local data dependencies to match dependencies from message SSCellData cellData; synchronized (CellData) { cellData = getCellDataByName(m); } if (cellData != null) { cellData.setDependencies( (Real) DataUtility.makeLocal(data, DEBUG)); } } else if (mid == STATUS) { if (m == null) { // status report from server if (IsRemote && NewClient) { Tuple tuple = (Tuple) DataUtility.makeLocal(data, DEBUG); if (tuple != null) { synchronized (CellData) { // add Data objects to cell try { int len = tuple.getDimension(); for (int i=0; i= 3) exc.printStackTrace(); } if (url != null) type = URL_SOURCE; else type = FORMULA_SOURCE; } } } if (type == DIRECT_SOURCE || type == REMOTE_SOURCE) { // direct and remote source types are invalid throw new VisADException("Invalid source type"); } if (type == URL_SOURCE) { // obtain data from filename or URL beginWait(true); Data data = null; boolean success = true; try { // load file or URL DefaultFamily loader = new DefaultFamily("loader", true); if (source.startsWith("file:")) { source = source.substring(5); // if source looks like it starts with a Windows drive spec... if (source.length() > 2 && source.charAt(2) == ':' && source.charAt(0) == '/') { source = source.substring(1); } } data = loader.open(source); // check if source is a local file File file = new File(source); if (file.exists()) { String path = file.getAbsolutePath(); char[] p = path.toCharArray(); for (int i=0; i= 3) exc.printStackTrace(); } } } /** * Blocks until all of this cell's Data objects finish loading. */ public void waitForData() throws VisADException { // compile list of data variable names String[] varNames; int len; synchronized (CellData) { len = CellData.size(); varNames = new String[len]; for (int i=0; i 0) { try { Thread.sleep(POLLING_INTERVAL); } catch (InterruptedException exc) { if (DEBUG && DEBUG_LEVEL >= 3) exc.printStackTrace(); } } // wait for each data object for (int i=0; i= 3) exc.printStackTrace(); } } } } // add reference if (ok && Dim != JAVA2D_2D) { VDisplay.addReferences(new ImageRendererJ3D(), dr[i], cmaps[i]); } else { if (DEBUG) warn("data #" + i + " cannot use ImageRendererJ3D"); VDisplay.addReference(dr[i], cmaps[i]); } } setPartialSaveString(save, true); VDisplay.enableAction(); } HasMappings = true; if (vexc != null) throw vexc; if (rexc != null) throw rexc; } /** * Clears this cell's mappings. */ public void clearMaps() throws VisADException, RemoteException { if (IsRemote) clearMapsClone(true); else if (hasMappings()) { VDisplay.removeAllReferences(); VDisplay.clearMaps(); HasMappings = false; } } /** * Clears this cloned cell's mappings. */ private void clearMapsClone(boolean display) throws VisADException, RemoteException { if (hasMappings()) { RemoteVDisplay.removeAllReferences(); RemoteVDisplay.clearMaps(); if (display) { clearDisplay(); constructDisplay(); initDisplayPanel(); updateDisplay(true); } HasMappings = false; } } // -- Clear cell -- /** * Clears this cell's display. */ public void clearDisplay() throws VisADException, RemoteException { if (!DisplayEnabled) return; HasDisplay = false; Util.invoke(false, DEBUG, new Runnable() { public void run() { removeAll(); refresh(); } }); } /** * Clears this cell completely. */ public void clearCell() throws VisADException, RemoteException { removeAllReferences(); } /** * Clears this cell completely and destroys it, * removing it from the list of created cells. */ public void destroyCell() throws VisADException, RemoteException { RemoteException problem = null; setDisplayEnabled(false); // remove all data objects from this cell removeAllReferences(false, !IsRemote); if (!IsRemote) { // SERVER: stop serving this cell clearCell(); int slen = Servers.size(); for (int i=0; i 0) { maps = new ScalarMap[mvs]; for (int i=0; i iter = ImageIO.getImageWritersByFormatName("jpeg"); ImageWriter writer = iter.next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(1.0f); FileOutputStream fout = new FileOutputStream(f); writer.setOutput(fout); IIOImage iio = new IIOImage(image, null, null); writer.write(null, iio, param); ImageIO.write(image, "image/jpeg", fout); fout.close(); } catch (NoClassDefFoundError err) { throw new VisADException("JPEG codec not found"); } } // --- SAVE STRINGS --- /** * Gets the save string necessary to reconstruct this cell. */ public String getSaveString() { StringBuffer sb = new StringBuffer(); // append data information synchronized (CellData) { int len = CellData.size(); sb.append("# "); sb.append(Name); sb.append(": data information\n"); for (int i=0; i 0 && d < 4) dim = d; else { // invalid dimension value warn("dimension value " + value + " is not valid and will be ignored"); } } // mappings else if (keyword.equalsIgnoreCase("maps") || keyword.equalsIgnoreCase("mappings")) { mapString = value; } // mapping ranges else if (keyword.equalsIgnoreCase("map ranges") || keyword.equalsIgnoreCase("map_ranges") || keyword.equalsIgnoreCase("mapranges")) { StringTokenizer st = new StringTokenizer(value); mapMins = new Vector(); mapMaxs = new Vector(); while (true) { if (!st.hasMoreTokens()) break; String s1 = st.nextToken(); if (!st.hasMoreTokens()) { warn("trailing map range min value " + s1 + " has no corresponding max value and will be ignored"); break; } String s2 = st.nextToken(); Double d1 = null, d2 = null; try { d1 = new Double(s1.equals("NaN") ? Double.NaN : Double.parseDouble(s1)); d2 = new Double(s2.equals("NaN") ? Double.NaN : Double.parseDouble(s2)); } catch (NumberFormatException exc) { if (DEBUG) exc.printStackTrace(); } if (d1 == null || d2 == null) { warn("map range min/max pair (" + s1 + ", " + s2 + ") is not valid and will be ignored"); } else { mapMins.add(d1); mapMaxs.add(d2); } } } // projection matrix else if (keyword.equalsIgnoreCase("projection") || keyword.equalsIgnoreCase("proj")) { proj = value; } // graphics mode settings else if (keyword.equalsIgnoreCase("graphics mode") || keyword.equalsIgnoreCase("graphics_mode") || keyword.equalsIgnoreCase("graphicsmode") || keyword.equalsIgnoreCase("graphics") || keyword.equalsIgnoreCase("mode")) { mode = value; } // color table else if (keyword.equalsIgnoreCase("color") || keyword.equalsIgnoreCase("color table") || keyword.equalsIgnoreCase("color_table") || keyword.equalsIgnoreCase("colortable")) { color.add(value); } // contour data else if (keyword.equalsIgnoreCase("contour") || keyword.equalsIgnoreCase("contours") || keyword.equalsIgnoreCase("iso contour") || keyword.equalsIgnoreCase("iso_contour") || keyword.equalsIgnoreCase("isocontour") || keyword.equalsIgnoreCase("iso contours") || keyword.equalsIgnoreCase("iso_contours") || keyword.equalsIgnoreCase("isocontours")) { contour.add(value); } // range else if (keyword.equalsIgnoreCase("range") || keyword.equalsIgnoreCase("select range") || keyword.equalsIgnoreCase("select_range") || keyword.equalsIgnoreCase("selectrange")) { range.add(value); } // animation else if (keyword.equalsIgnoreCase("anim") || keyword.equalsIgnoreCase("animation")) { anim.add(value); } // select value else if (keyword.equalsIgnoreCase("value") || keyword.equalsIgnoreCase("select value") || keyword.equalsIgnoreCase("select_value") || keyword.equalsIgnoreCase("selectvalue")) { selectVal.add(value); } // unknown keyword else { warn("keyword " + keyword + " is unknown and will be ignored"); } } if (preserveMaps) { // detect which maps are the same and set appropriate ranges maps = DataUtility.convertStringToMaps(mapString, getData(), true); if (maps != null) { int lmin = mapMins == null ? -1 : mapMins.size(); int lmax = mapMaxs == null ? -1 : mapMaxs.size(); int cmin = 0, cmax = 0; Vector mapVector = VDisplay.getMapVector(); for (int j=0; j= 0) { // set map's minimum and maximum range values ScalarMap map = (ScalarMap) mapVector.elementAt(mapIndex); map.setRange( ((Double) mapMins.elementAt(cmin++)).doubleValue(), ((Double) mapMaxs.elementAt(cmax++)).doubleValue()); } else { // skip current minimum and maximum range values cmin++; cmax++; } } } } } } else { // clear old stuff from cell clearCell(); // set up dimension setDimension(dim); // set up data objects int ilen = ids.size(); int slen = sources.size(); int tlen = types.size(); if (ilen != slen || ilen != tlen) { warn("some data object entries are corrupt and will be ignored"); } int len = ilen < slen && ilen < tlen ? ilen : (slen < tlen ? slen : tlen); setDisplayEnabled(false); for (int i=0; i= 3) exc.printStackTrace(); } } else if (!preserveMaps) warn("display has no GraphicsModeControl; " + "the provided graphics mode settings will be ignored"); } // set up color control(s) int len = color.size(); if (len > 0) { for (int i=0; i 0) { for (int i=0; i 0) { for (int i=0; i 0) { for (int i=0; i= 3) exc.printStackTrace(); } ac.setSaveString(s); } else if (!preserveMaps) warn("display has no AnimationControl #" + (i + 1) + "; " + "the provided animation settings will be ignored"); } } // set up value control(s) len = selectVal.size(); if (len > 0) { for (int i=0; i 0 && c[0] == VDPanel; // redraw cell if (Loading > 0) { removeAll(); add(WaitPanel); } else if (ec != null) { removeAll(); add(ec); } else if (HasDisplay) { if (!hasPanel) { // no need to re-add VDPanel if already present removeAll(); add(VDPanel); } } else removeAll(); refresh(); } }); } /** * Enables or disables display updates. */ private void setDisplayEnabled(boolean value) { if (value == DisplayEnabled) return; DisplayEnabled = value; if (DisplayEnabled) updateDisplay(); } // -- Toggle waiting mode -- /** * Increments the loading counter. */ private void beginWait(boolean update) { Loading++; if (update) updateDisplay(); } /** * Decrements the loading counter. */ private void endWait(boolean update) { Loading--; if (update) updateDisplay(); } // --- EVENT HANDLING --- /** * List of SSCellListeners. */ protected Vector SListen = new Vector(); /** * List of DisplayListeners. */ protected Vector DListen = new Vector(); // -- Add & remove DisplayListeners -- /** * Adds a DisplayListener. */ public void addDisplayListener(DisplayListener d) { synchronized (DListen) { if (!DListen.contains(d)) { if (IsSlave) RemoteVSlave.addDisplayListener(d); else VDisplay.addDisplayListener(d); DListen.add(d); } } } /** * Removes a DisplayListener from this cell. */ public void removeDisplayListener(DisplayListener d) { synchronized (DListen) { if (DListen.contains(d)) { if (IsSlave) RemoteVSlave.removeDisplayListener(d); else VDisplay.removeDisplayListener(d); DListen.remove(d); } } } /** * Re-attaches all display listeners after they have been detached. */ private void attachListeners() { int len = DListen.size(); if (IsSlave) { for (int i=0; i 0 ? new ScalarMap[len] : null); for (int i=0; i *
  • BasicSSCell.JAVA3D_3D *
  • BasicSSCell.JAVA2D_2D *
  • BasicSSCell.JAVA3D_2D * */ public int getDimension() { return Dim; } /** * Gets this cell's Data object with the specified variable name. */ public Data getData(String varName) { SSCellData cellData; synchronized (CellData) { cellData = getCellDataByName(varName); } return cellData == null ? null : cellData.getData(); } /** * Gets this cell's Data objects. */ public Data[] getData() { synchronized (CellData) { int len = CellData.size(); Data[] data = new Data[len]; for (int i=0; i 0) { SSCellData cellData = (SSCellData) CellData.firstElement(); varName = cellData.getVariableName(); } } return varName; } /** * Gets the variable name of this cell's last Data object. */ public String getLastVariableName() { String varName = null; synchronized (CellData) { if (CellData.size() > 0) { SSCellData cellData = (SSCellData) CellData.lastElement(); varName = cellData.getVariableName(); } } return varName; } /** * Gets the variable names of this cell's Data objects. */ public String[] getVariableNames() { synchronized (CellData) { int len = CellData.size(); String[] varNames = new String[len]; for (int i=0; i 0; } /** * Whether this cell has a valid display on-screen. */ public boolean hasDisplay() { return HasDisplay; } /** * Whether this cell has any mappings. */ public boolean hasMappings() { if (IsRemote) { // CLIENT: check mappings from remote display Vector v = null; try { v = RemoteVDisplay.getMapVector(); } catch (VisADException exc) { if (DEBUG) exc.printStackTrace(); } catch (RemoteException exc) { if (DEBUG) exc.printStackTrace(); } return v != null && !v.isEmpty(); } else return HasMappings; } /** * Whether other cells are dependent on this cell's Data object * with the specified variable name. */ public boolean othersDepend(String varName) { SSCellData cellData; synchronized (CellData) { cellData = getCellDataByName(varName); } return cellData.othersDepend(); } /** * Whether other cells are dependent on any of this cell's Data objects. */ public boolean othersDepend() { synchronized (CellData) { int len = CellData.size(); for (int i=0; i 0 ? (DataReferenceImpl) getReference(getFirstVariableName()) : null); } /** * @deprecated Use getRemoteReference(String) instead. */ public RemoteDataReferenceImpl getRemoteDataRef() { return (getDataCount() > 0 ? (RemoteDataReferenceImpl) getRemoteReference(getFirstVariableName()) : null); } /** * @deprecated Use getDataSource(String) instead. */ public URL getFileURL() { URL url = null; String varName = getFirstVariableName(); if (getDataCount() > 0 && getDataSourceType(varName) == URL_SOURCE) { try { url = new URL(getDataSource(varName)); } catch (MalformedURLException exc) { if (DEBUG && DEBUG_LEVEL >= 3) exc.printStackTrace(); } } return url; } /** * @deprecated Use getDataSource(String) instead. */ public String getFilename() { String filename = ""; String varName = getFirstVariableName(); if (getDataCount() > 0 && getDataSourceType(varName) == URL_SOURCE) { filename = getDataSource(varName); } return filename; } /** * @deprecated Use getDataSource(String) instead. */ public String getRMIAddress() { String rmi = null; String varName = getFirstVariableName(); if (getDataCount() > 0 && getDataSourceType(varName) == RMI_SOURCE) { rmi = getDataSource(varName); } return rmi; } /** * @deprecated Use getDataSource(String) instead. */ public String getFormula() { String formula = ""; String varName = getFirstVariableName(); if (getDataCount() > 0 && getDataSourceType(varName) == FORMULA_SOURCE) { formula = getDataSource(varName); } return formula; } /** * @deprecated Use addDataSource(String, URL_SOURCE) instead. */ public void loadData(URL u) throws VisADException, RemoteException { addDataSource(u.toString(), URL_SOURCE); } /** * @deprecated Use addDataSource(String, URL_SOURCE) instead. */ public void loadData(String s) throws VisADException, RemoteException { addDataSource(s, URL_SOURCE); } /** * @deprecated Use addDataSource(String, RMI_SOURCE) instead. */ public void loadRMI(String s) throws VisADException, RemoteException { addDataSource(s, RMI_SOURCE); } /** * @deprecated Use setDimension(int) instead. */ public void setDimension(boolean twoD, boolean java2d) throws VisADException, RemoteException { int dim; if (!twoD && java2d) return; if (!twoD && !java2d) dim = JAVA3D_3D; else if (twoD && java2d) dim = JAVA2D_2D; else dim = JAVA3D_2D; // twoD && !java2d setDimension(dim); } /** * @deprecated Use getDataSourceType(String) instead. */ public boolean hasFormula() { return (getDataCount() > 0 && getDataSourceType(getFirstVariableName()) == FORMULA_SOURCE); } /** * @deprecated Use getReference(String) instead. */ public DataReference getReference() { return (getDataCount() > 0 ? getReference(getFirstVariableName()) : null); } /** * @deprecated Use visad.DataUtility.stringsToTuple(String[]) instead. */ public static Tuple stringsToTuple(String[] s) { return DataUtility.stringsToTuple(s, DEBUG); } /** * @deprecated Use visad.DataUtility.tupleToStrings(Tuple) instead. */ public static String[] tupleToStrings(Tuple t) { return DataUtility.tupleToStrings(t, DEBUG); } /** * @deprecated Use visad.DataUtility.makeLocal(data) instead. */ public static DataImpl makeLocal(Data data) { return DataUtility.makeLocal(data, DEBUG && DEBUG_LEVEL >= 3); } /** * @deprecated Use visad.Util.arraysEqual(Object[], Object[]) instead. */ public static boolean arraysEqual(Object[] o1, Object[] o2) { return Util.arraysEqual(o1, o2); } /** * @deprecated Use visad.Util.invoke(boolean, Runnable) instead. */ public static void invoke(boolean wait, Runnable r) { Util.invoke(wait, DEBUG, r); } }
  • Ads help maintain this website.