From 8a264064684ceac2f6596defdf071c41ac272bf9 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Thu, 23 Jun 2016 13:24:41 -0400 Subject: [PATCH] Add MultiDelimited formatter trait This will simplify, through composition, a number of other validator-formatters. * src/validate/formatter/MultiDelimited.js: Added * test/validate/formatter/MultiDelimitedTest.js: Added --- src/validate/formatter/MultiDelimited.js | 149 ++++++++++++++++++ test/validate/formatter/MultiDelimitedTest.js | 71 +++++++++ 2 files changed, 220 insertions(+) create mode 100644 src/validate/formatter/MultiDelimited.js create mode 100644 test/validate/formatter/MultiDelimitedTest.js diff --git a/src/validate/formatter/MultiDelimited.js b/src/validate/formatter/MultiDelimited.js new file mode 100644 index 0000000..31c2c49 --- /dev/null +++ b/src/validate/formatter/MultiDelimited.js @@ -0,0 +1,149 @@ +/** + * Apply styles to each delimited item individaully + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +var Trait = require( 'easejs' ).Trait, + ValidatorFormatter = require( '../ValidatorFormatter' ); + + +/** + * Applies supertype for each item in a delimited string + */ +module.exports = Trait( 'MultiDelimited' ) + .implement( ValidatorFormatter ) + .extend( +{ + /** + * Delimited to used in parse input + * @type {string} + */ + 'private _parse_delim': '', + + /** + * Delimited to used in retrieve result + * @type {string} + */ + 'private _retrieve_delim': '', + + + /** + * Initialize with parse and retrieve delimiters + * + * Parsing is intended for storage of data, retrieval is intended + * for display. When parsing, RETRIEVE_DELIM will be added + * between parts, and when parsing, PARSE_DELIM will be used + * instead. + * + * If RETRIEVE_DELIM is undefined, it will default to PARSE_DELIM. + * + * @param {string} parse_delim delimiter on input data for parsing + * @param {?string} retrieve_delim delimiter on input data for retrieval + */ + __mixin: function( parse_delim, retrieve_delim ) + { + this._parse_delim = ''+parse_delim; + + this._retrieve_delim = ( retrieve_delim === undefined ) + ? this._parse_delim + : ''+retrieve_delim; + }, + + + /** + * Parse each item in a delimited string + * + * @param {string} data data to parse + * + * @return {string} data formatted for storage + */ + 'virtual abstract override public parse': function( data ) + { + var _self = this, + _super = this.__super; + + return this.forEachPart( this._parse_delim, data, function( part ) + { + return _super.call( _self, part ); + } ).join( this._retrieve_delim ); + }, + + + /** + * Format each item in a delimited string + * + * @param {string} data data to format for display + * + * @return {string} data formatted for display + */ + 'virtual abstract override public retrieve': function( data ) + { + var _self = this, + _super = this.__super; + + return this.forEachPart( this._retrieve_delim, data, function( part ) + { + return _super.call( _self, part ); + } ).join( this._parse_delim ); + }, + + + /** + * Determine DATA parts from the given delimiter DELIM + * + * Subtypes may override this method to change behavior or provide + * more sophisticated handling. + * + * @param {string} delim part delimiter + * @param {string} data delimited data + * + * @return {Array.} items split by DELIM + */ + 'virtual protected getParts': function( delim, data ) + { + return ( ''+data ).split( delim ); + }, + + + /** + * Invoke CALLBACK for each part in DATA delimited by DELIM + * + * TODO: This can go away once ES3 compatibility can be dropped. + * + * @param {string} delim part delimiter + * @param {string} data delimited data + * + * @param {function(string)} callback formatter + * + * @return {Array.} formatetd DATA parts as split by DELIM + */ + 'virtual protected forEachPart': function( delim, data, callback ) + { + var result = [], + parts = this.getParts( delim, data ); + + // maintain ES3 compatibility + for ( var i = 0; i < parts.length; i++ ) + { + result.push( callback( parts[ i ] ) ); + } + + return result; + } +} ); \ No newline at end of file diff --git a/test/validate/formatter/MultiDelimitedTest.js b/test/validate/formatter/MultiDelimitedTest.js new file mode 100644 index 0000000..cc411db --- /dev/null +++ b/test/validate/formatter/MultiDelimitedTest.js @@ -0,0 +1,71 @@ +/** + * Tests delimited formatting + * + * Copyright (C) 2016 LoVullo Associates, Inc. + * + * This file is part of liza. + * + * liza is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +var Class = require( 'easejs' ).Class, + liza = require( '../../../' ), + formatter = liza.validate.formatter, + Sut = formatter.MultiDelimited, + EchoFormatter = formatter.EchoFormatter, + ValidatorFormatter = liza.validate.ValidatorFormatter, + common = require( './common' ), + expect = require( 'chai' ).expect; + +var DummyFormatter = Class.implement( ValidatorFormatter ) + .extend( +{ + 'virtual parse': function( data ) + { + return '+' + data; + }, + + 'virtual retrieve': function( data ) + { + return '-' + data; + }, +} ); + + +describe( 'validate.formatter.MultiDelimited', function() +{ + var sut = DummyFormatter.use( Sut( ',', '|' ) )(); + + common.testValidate( sut, { + "": [ "+", "-+" ], + "abc": [ "+abc", "-+abc" ], + "abc,123": [ "+abc|+123", "-+abc,-+123" ], + " 1122 ": [ "+ 1122 ", "-+ 1122 " ], + " 1122 ,34": [ "+ 1122 |+34", "-+ 1122 ,-+34" ], + } ); + + + // sane default behavior + it( 'defaults retrieve delimeter to parse delimiter', function() + { + var sut = DummyFormatter.use( Sut( '!' ) )(); + + expect( sut.parse( "abc!123" ) ) + .to.equal( "+abc!+123" ); + + expect( sut.retrieve( "abc!123" ) ) + .to.equal( "-abc!-123" ); + } ); +} );