public boolean syncExtend() {
    if (!this.ncfile.hasUnlimitedDimension()) return false;
    try {
      if (!this.ncfile.syncExtend()) return false;
    } catch (IOException e) {
      return false;
    }

    // Update number of points in this TrajectoryObsDataset and in the child TrajectoryObsDatatype.
    int newNumPoints = this.timeDim.getLength();
    if (this.trajectoryNumPoint >= newNumPoints) return false;
    this.trajectoryNumPoint = newNumPoints;
    ((SingleTrajectory) this.trajectory).setNumPoints(this.trajectoryNumPoint);

    // Update end date in this TrajectoryObsDataset and in the child TrajectoryObsDatatype.
    try {
      endDate = trajectory.getTime(trajectoryNumPoint - 1);
    } catch (IOException e) {
      return false;
    }
    ((SingleTrajectory) trajectory).setEndDate(endDate);

    return true;
  }
  /**
   * Setup needed for all SingleTrajectoryObsDatatypes. Can only be called once.
   *
   * <p>Units of time varible must be udunits time units. Units of latitude variable must be
   * convertible to "degrees_north" by udunits. Units of longitude variable must be convertible to
   * "degrees_east" by udunits. Units of altitude variable must be convertible to "meters" by
   * udunits.
   *
   * @throws IllegalArgumentException if units of time, latitude, longitude, or altitude variables
   *     are not as required.
   * @throws IllegalStateException if this method has already been called.
   */
  public void setTrajectoryInfo(Config trajConfig) throws IOException {
    if (timeDim != null)
      throw new IllegalStateException("The setTrajectoryInfo() method can only be called once.");

    this.trajectoryId = trajConfig.getTrajectoryId();
    this.timeDim = trajConfig.getTimeDim();
    this.timeVar = trajConfig.getTimeVar();
    this.latVar = trajConfig.getLatVar();
    this.lonVar = trajConfig.getLonVar();
    this.elevVar = trajConfig.getElevVar();

    trajectoryNumPoint = this.timeDim.getLength();
    timeVarUnitsString = this.timeVar.findAttribute("units").getStringValue();

    // Check that time, lat, lon, elev units are acceptable.
    if (DateUnit.getStandardDate(timeVarUnitsString) == null) {
      throw new IllegalArgumentException(
          "Units of time variable <" + timeVarUnitsString + "> not a date unit.");
    }
    String latVarUnitsString = this.latVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(latVarUnitsString, "degrees_north")) {
      throw new IllegalArgumentException(
          "Units of lat var <" + latVarUnitsString + "> not compatible with \"degrees_north\".");
    }
    String lonVarUnitsString = this.lonVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(lonVarUnitsString, "degrees_east")) {
      throw new IllegalArgumentException(
          "Units of lon var <" + lonVarUnitsString + "> not compatible with \"degrees_east\".");
    }
    String elevVarUnitsString = this.elevVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(elevVarUnitsString, "meters")) {
      throw new IllegalArgumentException(
          "Units of elev var <" + elevVarUnitsString + "> not compatible with \"meters\".");
    }

    try {
      elevVarUnitsConversionFactor = getMetersConversionFactor(elevVarUnitsString);
    } catch (Exception e) {
      throw new IllegalArgumentException(
          "Exception on getMetersConversionFactor() for the units of elev var <"
              + elevVarUnitsString
              + ">.");
    }

    if (this.ncfile.hasUnlimitedDimension()
        && this.ncfile.getUnlimitedDimension().equals(timeDim)) {
      Object result = this.ncfile.sendIospMessage(NetcdfFile.IOSP_MESSAGE_ADD_RECORD_STRUCTURE);
      if ((result != null) && (Boolean) result)
        this.recordVar = (Structure) this.ncfile.getRootGroup().findVariable("record");
      else this.recordVar = new StructurePseudo(this.ncfile, null, "record", timeDim);
    } else {
      this.recordVar = new StructurePseudo(this.ncfile, null, "record", timeDim);
    }

    // @todo HACK, HACK, HACK - remove once addRecordStructure() deals with ncd attribute changes.
    Variable elevVarInRecVar = this.recordVar.findVariable(this.elevVar.getFullNameEscaped());
    if (!elevVarUnitsString.equals(elevVarInRecVar.findAttribute("units").getStringValue())) {
      elevVarInRecVar.addAttribute(new Attribute("units", elevVarUnitsString));
    }

    trajectoryVarsMap = new HashMap();
    // for ( Iterator it = this.recordVar.getVariables().iterator(); it.hasNext(); )
    for (Iterator it = this.ncfile.getRootGroup().getVariables().iterator(); it.hasNext(); ) {
      Variable curVar = (Variable) it.next();
      if (curVar.getRank() > 0
          && !curVar.equals(this.timeVar)
          && !curVar.equals(this.latVar)
          && !curVar.equals(this.lonVar)
          && !curVar.equals(this.elevVar)
          && (this.recordVar == null ? true : !curVar.equals(this.recordVar))) {
        MyTypedDataVariable typedVar = new MyTypedDataVariable(new VariableDS(null, curVar, true));
        dataVariables.add(typedVar);
        trajectoryVarsMap.put(typedVar.getShortName(), typedVar);
      }
    }

    trajectory =
        new SingleTrajectory(
            this.trajectoryId,
            trajectoryNumPoint,
            this.timeVar,
            timeVarUnitsString,
            this.latVar,
            this.lonVar,
            this.elevVar,
            dataVariables,
            trajectoryVarsMap);

    startDate = trajectory.getTime(0);
    endDate = trajectory.getTime(trajectoryNumPoint - 1);

    ((SingleTrajectory) trajectory).setStartDate(startDate);
    ((SingleTrajectory) trajectory).setEndDate(endDate);
  }