UNPKG

lib-utils-ts

Version:

<img src="https://img.shields.io/npm/v/lib-utils-ts"/> <img src="https://img.shields.io/snyk/vulnerabilities/npm/lib-utils-ts"/> <img src="https://img.shields.io/npm/l/lib-utils-ts"/> <img src="https://img.shields.io/github/languages/top/devGnode/lib-util

306 lines (281 loc) 9.51 kB
import {iterator, MapEntries, predicateFn, properties, Set} from "../Interface"; import {Define} from "../Define"; import {IllegalArgumentException, NullPointerException} from "../Exception"; import {Iterator} from "../utils/Iterator"; import {HashMap} from "../utils/HashMap"; import {InputStreamReader} from "./InputStreamReader"; import {Reader} from "./Reader"; import {Objects} from "../type/Objects"; import {Optional} from "../utils/Optional"; import {PrintStream} from "./PrintStream"; import {PrintWriter} from "./PrintWriter"; import {OutputStream} from "./OutputStream"; import * as os from "os"; class LineReader { private readonly ins:InputStreamReader; private readonly reader:Reader; public line:string[] = []; constructor(value:InputStreamReader|Reader) { if(value instanceof InputStreamReader ) this.ins = value; else{ this.reader = value; } } /*** * @returns {number} */ public getLine():number{ let tmp:string = "", reader:Reader = this.reader? this.reader : this.ins, skipWhiteSpace:boolean = true, isComment:boolean = false, isBackSlash:boolean = false, i:number = 0; this.line = []; while( true ){ // read next byte try {tmp = String.fromCharCode(reader.read());}catch (e) { if(this.line.length>0)return this.line.length; return -1; } // white space if(skipWhiteSpace) { if(tmp==" "||tmp=="\t"||tmp=="\f") continue; if(isBackSlash&&(tmp == '\r' || tmp == '\n')) continue; skipWhiteSpace = false; } // skip comment if(tmp == "#" || tmp == "\!"){ isComment=true; continue; } if(isComment&&tmp!="\n") continue; if(tmp!="\r"&&tmp!=="\n"){ if(tmp!="\\")isBackSlash = false; else{ isBackSlash = skipWhiteSpace = true; continue; } this.line[i++] = tmp; }else{ if(isComment) { isComment = false; skipWhiteSpace = true; i = 0; }else{ if(i==0) skipWhiteSpace=true; if(i>0)return i; } } } } } export abstract class AbstractProperties implements properties{ /*** * */ protected prop : HashMap<string, Object> = new HashMap(); protected path : string; /** * @type {string} */ private readonly lineSeparator:string = os.EOL; /*** * */ protected constructor() {} /*** * @Throw NullPointerException - when key value is null. * @param key * @param defaultValue */ public getProperty(key: string, defaultValue?: Object):Object { return Optional .ofNullable(this.prop.get(Objects.requireNotNull(key))) .orElse(defaultValue); } /*** * @Throw NullPointerException - when key value is null. * @param key * @param value */ public setProperty(key: string, value: Object ): void { this.prop.put(Objects.requireNotNull(key),value); } /*** * @containsKey * @param key */ public hasKey( key: string ):boolean{return this.prop.keySet().contains(key);} /*** * */ public stringPropertiesName( ) : Set<string>{return this.prop.keySet();} /*** * * @Throws NullPointerException - when InputStreamReader is null * IOException * IllegalArgumentException - wrong quote into string * @param input */ public load( input : InputStreamReader ) : void{ Objects.requireNotNull(input); this.prop = new HashMap(); let lineReader:LineReader = new LineReader(input), sz:number,i:number = 0, skipWhiteSpace:boolean = true, grow:boolean,hasKey:boolean = false, key:string = null, value:string = null, chr:string; while ( (sz = lineReader.getLine()) >= 0 ){ i = 0; hasKey = false; key = ""; value = ""; while( ( i < sz && (chr = lineReader.line[i]) ) ) { grow = true; if(skipWhiteSpace){ if((chr==" "||chr=="\t"||chr=="\f"))grow=false; else skipWhiteSpace = false; } if(!hasKey&&chr=="="){ skipWhiteSpace = hasKey = true; grow = false; } // key if(!hasKey&&chr!=" ") key += chr; // value if(hasKey&&grow)value+=chr; i++; } i = 0; let prohibited:string, strParsed:string = null; while((chr = value[i])){ grow=true; if(( i==0&&(chr!="'"&&chr!="\"") ) || ( !value[i+1] &&(chr=="'"||chr=="\"") )) break; else if(i==0&&(chr=="'"||chr=="\"")){ strParsed = ""; prohibited = chr; grow = false; } if( grow && prohibited && chr === prohibited && (chr!="\'"&&chr!="\"") ){ throw new IllegalArgumentException(`Bad quoted string [${prohibited}] for '${key}' property.`); } else if(grow){ strParsed += chr; } i++; } this.prop.put(key,strParsed!=null ? strParsed : value ); } } /*** * * @param {PrintStream | PrintWriter} writer */ public list(writer:PrintStream|PrintWriter):void{ let itr: iterator<MapEntries<string,Object>>, entry:MapEntries<string,Object>, value:string; Objects.requireNotNull(writer); itr = this.prop.entrySet().iterator(); writer.println('======== Properties listing ========'); while( itr.hasNext() ){ entry = itr.next(); value = <string>Optional .ofNullable(entry.getValue()) .orElse(""); if(value.length>40){ value = value.substr(0,37)+`... and more(s) ${value.length-40}`; } writer.println(entry.getKey()+"="+value ); } writer.println('======== End of properties listing ========'); writer.close(); } /*** * @remove * @param * */ public remove(key:string):Object{ return this.prop.remove(key); } /*** * */ public store( output: OutputStream ): void{ let out:string="", next:MapEntries<string, Object>, itr: iterator<MapEntries<string, Object>>; output.write(`# ${new Date().toISOString()}\r\n`); itr = this.prop.entrySet().iterator(); while (itr.hasNext()){ next = itr.next(); output.write(`${next.getKey()}=${next.getValue().toString()}${this.lineSeparator}`); } output.close(); } public merge<T,Object>( properties:AbstractProperties, exclude: predicateFn<T> = null ):void{ let key:Iterator<string> = <Iterator<string>>properties.stringPropertiesName().iterator(), value:string, pass:boolean=false,dexclude:Define<predicateFn<T>> = Define.of(exclude); while( key.hasNext() ){ value = key.next(); if(dexclude.isNull()||(!dexclude.isNull()&&dexclude.get().call(null,value)))pass=true; if(pass)this.setProperty(value,properties.getProperty(value)); pass=false; } } } /*** * */ export class Properties extends AbstractProperties{constructor() {super();}} Object.package(this); /** * * * */ export class PropertiesJson extends AbstractProperties{ /*** * */ private truncate:boolean = false; /*** * */ constructor() {super();} /*** * Throw : * - NullPointerException * - IOException * - JSONException * @param input */ public load( input : InputStreamReader ) : void{ Define.of(input).orElseThrow(new NullPointerException("target is null !")); //this.path = input.getPath(); try{this.prop = HashMap.of<string, Object>(JSON.parse(input.toString()));}catch (e) { //throw new JSONException(`Wrong parsing file : ${input.getPath()}`); } } /*** * */ public store( output: OutputStream ): void{ Objects.requireNotNull(output,"target output stream is null !"); let out:string="", itr: iterator<MapEntries<string, Object>> = this.prop.entrySet().iterator(), next:MapEntries<string, Object>; while (itr.hasNext()){ next = itr.next(); out+= `${next.getKey()}=${next.getValue().toString()}\n`; } //output.write("{\n%s\n}".format(out.replace(/,\n*$/,"")),this.truncate); this.truncate=false; } /*** * As Json properties file doesn't support comment * just make a store with truncate file */ //public update( ) :void{ this.truncate=true; this.store(new FileWriter(this.path));} }