API Docs for: 0.0.1
Show:

File: lib/parsers/caaml.slf.js

/*
 * niViz -- snow profiles visualization
 * Copyright (C) 2015 WSL/SLF - Fluelastrasse 11 - 7260 Davos Dorf - Switzerland.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

(function (niviz, moment) {
  'use strict';

  // --- Module Dependencies ---
  var Station  = niviz.Station;
  var Profile  = niviz.Profile;

  var Parser   = niviz.Parser;

  var util     = niviz.util;
  var round    = util.round;
  var alias    = util.alias;
  var assert   = util.assert;
  var inherits = util.inherits;

  /** @module niviz */

  /**
   * CAAML SLF file parser.
   *
   * @class CAAMLSLFParser
   * @constructor
   *
   * @extends CAAMLParser
   */
  function CAAMLSLFParser(ctx, profile) {
    CAAMLSLFParser.uber.call(this, ctx.data);

    this.ctx = ctx;
    this.station = ctx.station;
    this.profile = profile;

    this._parse(); // call XMLParser _parser method
  }

  inherits(CAAMLSLFParser, Parser.format['xml']);

  // /**
  //  * A list of date/time formats
  //  * recognized by the parser.
  //  *
  //  * @property dates
  //  * @type Array<String>
  //  * @static
  //  */
  // CAAMLParser.dates = [
  //   moment.ISO_8601
  // ];


  // /**
  //  * Conversion table for Profile Features.
  //  *
  //  * @property features
  //  * @type Object
  //  * @static
  //  */
  // CAAMLParser.features = {

  //   temperature: {
  //     layer: 'tempProfile Obs',
  //     top:   'depth',
  //     value: 'snowTemp'
  //   },

  //   hardness: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     value: ':scope > hardness',
  //     ignorenoval: true
  //   },

  //   wetness: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     value: 'lwc',
  //     ignorenoval: true
  //   },

  //   lwc: {
  //     multiple: true,
  //     nodes: 'lwcProfile',
  //     layer: 'Layer',
  //     top:   'depthTop',
  //     value: 'lwc',
  //     ignorenoval: true,
  //     proxy: 'wetness',
  //     offset: 1
  //   },

  //   ssa: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     value: ':scope > specSurfArea',
  //     ignorenoval: true
  //   },

  //   ssa2: {
  //     multiple: true,
  //     nodes: 'specSurfAreaProfile',
  //     layer: 'Layer',
  //     top:   'depthTop',
  //     value: 'specSurfArea',
  //     ignorenoval: true,
  //     proxy: 'ssa',
  //     offset: 1
  //   },

  //   comments: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     value: 'comment'
  //   },

  //   grainshape: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     ignorenoval: true,

  //     value: function (node) {
  //       return {
  //         primary: this.text('grainFormPrimary', node),
  //         secondary: this.text('grainFormSecondary', node)
  //       };
  //     }
  //   },

  //   grainsize: {
  //     layer: 'stratProfile Layer',
  //     top:   'depthTop',
  //     ignorenoval: true,

  //     value: function (node) {
  //       return {
  //         avg: this.text('grainSize avg', node),
  //         max: this.text('grainSize avgMax', node)
  //       };
  //     }
  //   },

  //   ramm: {
  //     nodes: 'hardnessProfile',
  //     layer: 'Layer',
  //     multiple: true,
  //     top:   'depthTop',

  //     value: function (node) {
  //       return {
  //         value: this.text('hardness', node),
  //         depth: this.text('depthTop', node),
  //         height: this.text('thickness', node),
  //         weightHammer: this.text('weightHammer', node),
  //         weightTube: this.text('weightTube', node),
  //         nDrops: this.text('nDrops', node),
  //         dropHeight: this.text('dropHeight', node)
  //       };
  //     }
  //   },

  //   ct: {
  //     layer:  'stbTests ComprTest',
  //     top: 'failedOn depthTop',
  //     value: function (node) {
  //       return {
  //         nofailure: this.$('noFailure', node) ? true : false,
  //         value: this.text('Results testScore', node),
  //         character: this.text('Results fractureCharacter', node),
  //         comment: this.text('comment', node),
  //         order: this.text('customData order-number', node)
  //       };
  //     }
  //   },

  //   ect: {
  //     layer: 'stbTests ExtColumnTest',
  //     top:   'failedOn depthTop',
  //     value: function (node) {
  //       return {
  //         nofailure: this.$('noFailure', node) ? true : false,
  //         value: this.text('Results testScore', node),
  //         order: this.text('customData order-number', node),
  //         comment: this.text('comment', node),
  //         swiss: this.text('customData score1', node) === '' ? '' :
  //           this.text('customData score1', node) + '/' + this.text('customData score2', node)
  //       };
  //     }
  //   },

  //   rb: {
  //     layer:  'stbTests RBlockTest',
  //     top: 'failedOn depthTop',
  //     value: function (node) {
  //       return {
  //         nofailure: this.$('noFailure', node) ? true : false,
  //         value: this.text('Results testScore', node),
  //         releasetype: this.text('Results releaseType', node),
  //         character: this.text('Results fractureCharacter', node),
  //         comment: this.text('comment', node)
  //       };
  //     }
  //   },

  //   sf: {
  //     layer:  'stbTests ShearFrameTest',
  //     top: 'failedOn depthTop',
  //     value: function (node) {
  //       return {
  //         nofailure: this.$('noFailure', node) ? true : false,
  //         value: this.text('Results failureForce', node),
  //         character: this.text('Results fractureCharacter', node),
  //         comment: this.text('comment', node)
  //       };
  //     }
  //   },

  //   saw: {
  //     layer: 'stbTests PropSawTest',
  //     top:   'failedOn depthTop',
  //     value: function (node) {
  //       return {
  //         value: this.text('Results fracturePropagation', node),
  //         cutlength: this.text('Results cutLength', node),
  //         columnlength: this.text('Results columnLength', node),
  //         comment: this.text('comment', node)
  //       };
  //     }
  //   },

  //   density: {
  //     layer: 'densityProfile Layer',
  //     top:   'depthTop',
  //     value: 'density'
  //   },

  //   thickness: {
  //     layer: 'densityProfile Layer',
  //     top:   'depthTop',
  //     value: 'thickness'
  //   },

  //   threads: {
  //     layer: 'thread-profile layer',
  //     top:   'top',
  //     value: 'thread-color'
  //   }

  // };

  /**
   * Main CAAML parser routine.
   *
   * @method parse_xml
   * @private
   */
  CAAMLSLFParser.prototype.parse_xml = function () {
    assert(this.document, 'No XML document to parse!');

    // var type;
    // var profile = new Profile(this.parse_date());

    // this.version = this.parse_caaml_version() || 5;

    // this.parse_gml_id();
    // this.parse_name();
    // this.parse_position();

    this.parse_general_data(this.profile);

    // for (type in CAAMLParser.features)
    //   this.parse_feature(type, profile);

    // if (profile.features.length === 0)
    //   throw new Error('No features detected or parsed');

    // this.station.push(profile);
    // this.emit('profile', profile);

    return this;
  };

  /**
   * @method comment
   * @private
   */
  CAAMLSLFParser.prototype.comment = function (key) {
    if (this.ctx.version === 5)
      return this.text('customData profiletext-list profiletext[key="' + key + '"] > text');
    else
      return this.text('metaData customData profiletext-list profiletext[key="' + key + '"] > text');
  };

  /**
   * @method parse_general_data
   * @private
   */
  CAAMLSLFParser.prototype.parse_general_data = function (profile) {
    var basenode = '';
    if (this.ctx.version !== 5) basenode = 'metaData ';

    profile.info.slf = {};

    profile.info.slf.hasty = (this.text(basenode + 'customData header > hastyPit') === 'true');
    profile.info.slf.profilenr = this.text(basenode + 'customData header > profile-number');

    profile.info.slf.txt = {
      default: this.comment('TEXT_BLOCK_DEFAULT'),
      ss: this.comment('TEXT_BLOCK_SNOW_SURFACE'),
      rb: this.comment('TEXT_BLOCK_RUTSCHBLOCK'),
      loc: this.comment('TEXT_BLOCK_PROFILE_LOCATION'),
      profile: this.comment('TEXT_BLOCK_PROFILE'),
      drift: this.comment('TEXT_BLOCK_SNOW_DRIFT'),
      signals: this.comment('TEXT_BLOCK_ALARM_SIGNS'),
      avalanches: this.comment('TEXT_BLOCK_AVALANCHES'),
      danger: this.comment('TEXT_BLOCK_AVALANCHE_DANGER'),
      confidential: this.comment('TEXT_BLOCK_REMARK_CONFIDENTIAL'),
      weather: this.text('customData header weather > description'),
      remarks: this.comment('TEXT_BLOCK_REMARK')
    };
  };

  // /**
  //  * @property parse_caaml_version
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_caaml_version = function () {
  //   var root = this.document, version;
  //   if (root && root.attributes && root.attributes.getNamedItem('xmlns:caaml'))
  //     version = root.attributes.getNamedItem('xmlns:caaml').value;

  //   if (version) version = parseInt(version.match(/\d+/)[0]);

  //   return version;
  // };

  // /**
  //  * @property parse_date
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_date = function () {
  //   return moment.parseZone(
  //     this.text('validTime timePosition'),
  //     CAAMLParser.dates,
  //     true
  //   );
  // };

  // /**
  //  * @property parse_gml_id
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_gml_id = function () {
  //   var root = this.document, id;
  //   if (root && root.attributes && root.attributes.getNamedItem('gml:id'))
  //     id = root.attributes.getNamedItem('gml:id').value;

  //   this.station.gmlid = id;
  //   return this;
  // };

  // /**
  //  * @property parse_name
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_name = function () {
  //   this.station.name = this.text('locRef ObsPoint > name');
  //   return this;
  // };

  // /**
  //  * @property parse_position
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_position = function () {
  //   var p = this.station.position, uom = 'm', uomattr, coord;
  //   console.dir('version: ' + this.version);

  //   var basenode = 'locRef ObsPoint ';
  //   if (this.version !== 5) basenode = 'locRef ';

  //   uomattr = this.$(basenode + 'validElevation ElevationPosition');
  //   if (uomattr && uomattr.attributes && uomattr.attributes.getNamedItem('uom'))
  //     uom = uomattr.attributes.getNamedItem('uom').value;

  //   p.aspect   = this.text(basenode + 'validAspect position');
  //   p.altitude = this.text(basenode + 'validElevation position');
  //   p.angle    = this.text(basenode + 'validSlopeAngle position') || 0;
  //   p.subtype  = this.text(basenode + 'obsPointSubType');
  //   p.uom      = uom;

  //   coord  = this.text(basenode + 'pointLocation pos');

  //   if (coord) {
  //     coord = coord.split(/\s+/);

  //     p.latitude  = parseFloat(coord[1]);
  //     p.longitude = parseFloat(coord[0]);
  //   }

  //   var x = this.text(basenode + 'customData location position > x');
  //   var y = this.text(basenode + 'customData location position > y');

  //   if (x && y) {
  //     p.x = x;
  //     p.y = y;
  //   }

  //   if (this.version === 5) {
  //     p.description = this.text('locRef ObsPoint > description');
  //   } else {
  //     p.description = this.text('locRef metaData > comment');
  //   }

  //   return this;
  // };

  // /**
  //  * @property add_feature
  //  * @private
  //  */
  // CAAMLParser.prototype.add_feature = function (type, profile, q, nodes, extrai) {
  //   var top, value, bottom, i, ii;

  //   for (i = 0, ii = nodes.length; i < ii; ++i) {
  //     top    = this.convert(q.top, nodes[i]);
  //     value  = this.convert(q.value, nodes[i]);
  //     bottom = this.convert('thickness', nodes[i]);

  //     if (q.ignorenoval && value === '') continue;

  //     if (type === 'threads') { //SLF specific, does not adhere to topdown logic
  //       profile.add(type, [[top, value]], extrai);
  //     } else if (top !== '') {
  //       top = (this.hs - top);
  //       profile.add(type, [[top, value, round(top - bottom, 5)]], extrai);
  //     } else { // Stability tests may not have a top value when no failure occured
  //       profile.add(type, [[top, value]], extrai);
  //     }
  //   }
  // };

  // /**
  //  * @property parse_feature
  //  * @private
  //  */
  // CAAMLParser.prototype.parse_feature = function (type, profile) {
  //   var q = CAAMLParser.features[type], nodes;

  //   if (q.multiple)
  //     nodes = this.$$(q.nodes);
  //   else
  //     nodes = this.$$(q.layer);

  //   if (q.multiple) {
  //     nodes.forEach(function (item, i) {
  //       var n = this.$$(q.layer, nodes[i]), index = q.offset || 0 + i;

  //       if (!i) this.add_feature(q.proxy || type, profile, q, n, index);
  //       else this.add_feature(q.proxy || type, profile, q, n, index);
  //     }, this);

  //   } else {
  //     this.add_feature(type, profile, q, nodes, false);
  //   }
  // };

  // CAAMLParser.prototype.convert = function (query, node) {
  //   switch (typeof query) {

  //   case 'function':
  //     return query.call(this, node);

  //   case 'string':
  //     return this.text(this.$(query, node));

  //   default:
  //     throw new Error('invalid query: ' + query);
  //   }
  // };

  // --- Module Export ---
  niviz.CAAMLSLFParser = CAAMLSLFParser;

}(niviz, moment));