pip-services3-commons-node
Version:
Portable abstractions and patterns for Pip.Services in Node.js
178 lines (149 loc) • 5.88 kB
text/typescript
/** @module data */
import { AnyValueArray } from "./AnyValueArray";
/** @hidden */
const _ = require('lodash');
/**
* Defines projection parameters with list if fields to include into query results.
*
* The parameters support two formats: dot format and nested format.
*
* The dot format is the standard way to define included fields and subfields using
* dot object notation: <code>"field1,field2.field21,field2.field22.field221"</code>.
*
* As alternative the nested format offers a more compact representation:
* <code>"field1,field2(field21,field22(field221))"</code>.
*
* ### Example ###
*
* let filter = FilterParams.fromTuples("type", "Type1");
* let paging = new PagingParams(0, 100);
* let projection = ProjectionParams.fromString("field1,field2(field21,field22)")
*
* myDataClient.getDataByFilter(filter, paging, projection, (err, page) => {...});
*
*/
export class ProjectionParams extends Array<string> {
/**
* Creates a new instance of the projection parameters and assigns its value.
*
* @param value (optional) values to initialize this object.
*/
public constructor(values: any[] = null) {
super();
// Set the prototype explicitly.
// https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
(<any>this).__proto__ = ProjectionParams.prototype;
if (values != null) {
for (let value of values)
this.push("" + value);
}
}
/**
* Gets a string representation of the object.
* The result is a comma-separated list of projection fields
* "field1,field2.field21,field2.field22.field221"
*
* @returns a string representation of the object.
*/
public toString(): string {
let builder = "";
for (let index = 0; index < this.length; index++) {
if (index > 0) {
builder += ',';
}
builder += this[index];
}
return builder;
}
private static parseValue(prefix: string, result: ProjectionParams, value: string): void {
value = value.trim();
let openBracket = 0;
let openBracketIndex = -1;
let closeBracketIndex = -1;
let commaIndex = -1;
let breakCycleRequired = false;
for (let index = 0; index < value.length; index++) {
switch (value[index]) {
case '(':
if (openBracket == 0) {
openBracketIndex = index;
}
openBracket++;
break;
case ')':
openBracket--;
if (openBracket == 0) {
closeBracketIndex = index;
if (openBracketIndex >= 0 && closeBracketIndex > 0) {
let previousPrefix = prefix;
if (prefix && prefix.length > 0) {
prefix = prefix + "." + value.substring(0, openBracketIndex);
} else {
prefix = value.substring(0, openBracketIndex);
}
let subValue = value.substring(openBracketIndex + 1, closeBracketIndex);
this.parseValue(prefix, result, subValue);
subValue = value.substring(closeBracketIndex + 1);
this.parseValue(previousPrefix, result, subValue);
breakCycleRequired = true;
}
}
break;
case ',':
if (openBracket == 0) {
commaIndex = index;
let subValue = value.substring(0, commaIndex);
if (subValue && subValue.length > 0) {
if (prefix && prefix.length > 0) {
result.push(prefix + "." + subValue);
} else {
result.push(subValue);
}
}
subValue = value.substring(commaIndex + 1);
if (subValue && subValue.length > 0) {
this.parseValue(prefix, result, subValue);
breakCycleRequired = true;
}
}
break;
}
if (breakCycleRequired) {
break;
}
}
if (value && value.length > 0 && openBracketIndex == -1 && commaIndex == -1) {
if (prefix && prefix.length > 0) {
result.push(prefix + "." + value);
} else {
result.push(value);
}
}
}
/**
* Converts specified value into ProjectionParams.
*
* @param value value to be converted
* @returns a newly created ProjectionParams.
*
* @see [[AnyValueArray.fromValue]]
*/
public static fromValue(value: any): ProjectionParams {
if (!_.isArray(value))
value = AnyValueArray.fromValue(value);
return new ProjectionParams(value);
}
/**
* Parses comma-separated list of projection fields.
*
* @param values one or more comma-separated lists of projection fields
* @returns a newly created ProjectionParams.
*/
public static fromString(...values: string[]) {
let result = new ProjectionParams();
for (let value of values) {
this.parseValue("", result, value);
}
return result;
}
}