<commit_before>import { Observable } from "rxjs/Observable";
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import "rxjs/add/observable/combineLatest";
import "rxjs/add/operator/map";
import "rxjs/add/operator/do";
import "rxjs/add/operator/distinctUntilChanged";
import { SchemaValidatorFactory } from "../schemavalidatorfactory";
import { ValidatorRegistry } from "./validatorregistry";
import { PropertyGroup } from "./propertygroup";

export abstract class FormProperty {
	public schemaValidator: Function;
	public required: boolean;

	protected _value: any = null;
	protected _errors: any = null ;
	private _valueChanges = new BehaviorSubject<any>(null);
	private _errorsChanges = new BehaviorSubject<any>(null);
	private _visible = true;
	private _visibilityChanges = new BehaviorSubject<boolean>(true);
	private _root: PropertyGroup;
	private _parent: PropertyGroup;
	private _path: string;

	constructor(
		schemaValidatorFactory: SchemaValidatorFactory,
		private validatorRegistry: ValidatorRegistry,
		public schema: any,

		parent: PropertyGroup,
		path: string
	) {
		this.schemaValidator = schemaValidatorFactory.createValidatorFn(this.schema);

		this._parent = parent;
		if (parent) {
			this._root = parent.root;
		} else if (this instanceof PropertyGroup) {
			this._root = <PropertyGroup><any>this;
		} else {
			throw new Error("")
		}
		this._path = path;
	}

	public get valueChanges() {
		return this._valueChanges;
	}

	public get errorsChanges() {
		return this._errorsChanges;
	}

	public get type(): string {
		return this.schema.type;
	}

	public get parent(): PropertyGroup {
		return this._parent;
	}

	public get root(): PropertyGroup {
		return this._root || <PropertyGroup><any>this;
	}

	public get path(): string {
		return this._path;
	}

	public get value() {
		return this._value;
	}

	public get visible() {
		return this._visible;
	}

	public get valid() {
		return this._errors === null;
	}

	public abstract setValue(value: any, onlySelf: boolean);

	abstract reset(value: any, onlySelf : boolean)

	protected updateValueAndValidity(onlySelf = false, emitEvent = true) {
		this.updateValue();

		if (emitEvent) {
			this.valueChanges.next(this.value);
		}

		this.runValidation();

		if (this.parent && !onlySelf) {
			this.parent.updateValueAndValidity(onlySelf, emitEvent);
		}

	}

	protected abstract updateValue();

	private runValidation() : any {
		let errors = this.schemaValidator(this._value) || [];
		let customValidator = this.validatorRegistry.get(this.path);
		if (customValidator) {
			let customErrors = this.validatorRegistry.get(this.path)(this.value, this, this.findRoot()) ;
			errors.push(...( customErrors || []));
		}
		if (errors.length === 0) {
			errors = null;
		}

		this._errors = errors;
		this.setErrors(this._errors);
	}

	private setErrors(errors) {
		this._errors = errors;
		this._errorsChanges.next(errors);
	}

	protected searchProperty(path: string): FormProperty {
		let prop: FormProperty = this;<commit_msg>Custom validation working.<commit_after>import { Observable } from "rxjs/Observable";
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import "rxjs/add/observable/combineLatest";
import "rxjs/add/operator/map";
import "rxjs/add/operator/do";
import "rxjs/add/operator/distinctUntilChanged";
import { SchemaValidatorFactory } from "../schemavalidatorfactory";
import { ValidatorRegistry } from "./validatorregistry";
import { PropertyGroup } from "./propertygroup";

export abstract class FormProperty {
	public schemaValidator: Function;
	public required: boolean;

	protected _value: any = null;
	protected _errors: any = null ;
	private _valueChanges = new BehaviorSubject<any>(null);
	private _errorsChanges = new BehaviorSubject<any>(null);
	private _visible = true;
	private _visibilityChanges = new BehaviorSubject<boolean>(true);
	private _root: PropertyGroup;
	private _parent: PropertyGroup;
	private _path: string;

	constructor(
		schemaValidatorFactory: SchemaValidatorFactory,
		private validatorRegistry: ValidatorRegistry,
		public schema: any,

		parent: PropertyGroup,
		path: string
	) {
		this.schemaValidator = schemaValidatorFactory.createValidatorFn(this.schema);

		this._parent = parent;
		if (parent) {
			this._root = parent.root;
		} else if (this instanceof PropertyGroup) {
			this._root = <PropertyGroup><any>this;
		} else {
			throw new Error("")
		}
		this._path = path;
	}

	public get valueChanges() {
		return this._valueChanges;
	}

	public get errorsChanges() {
		return this._errorsChanges;
	}

	public get type(): string {
		return this.schema.type;
	}

	public get parent(): PropertyGroup {
		return this._parent;
	}

	public get root(): PropertyGroup {
		return this._root || <PropertyGroup><any>this;
	}

	public get path(): string {
		return this._path;
	}

	public get value() {
		return this._value;
	}

	public get visible() {
		return this._visible;
	}

	public get valid() {
		return this._errors === null;
	}

	public abstract setValue(value: any, onlySelf: boolean);

	abstract reset(value: any, onlySelf : boolean)

	protected updateValueAndValidity(onlySelf = false, emitEvent = true) {
		this.updateValue();

		if (emitEvent) {
			this.valueChanges.next(this.value);
		}

		this.runValidation();

		if (this.parent && !onlySelf) {
			this.parent.updateValueAndValidity(onlySelf, emitEvent);
		}

	}

	protected abstract updateValue();

	private runValidation() : any {
		let errors = this.schemaValidator(this._value) || [];
		let customValidator = this.validatorRegistry.get(this.path);
		if (customValidator) {
			let customErrors = customValidator(this.value, this, this.findRoot()) ;
			errors = this.mergeErrors(errors, customErrors);
		}
		if (errors.length === 0) {
			errors = null;
		}

		this._errors = errors;
		this.setErrors(this._errors);
	}

	private mergeErrors(errors, newErrors) {
		if (newErrors) {
			if (Array.isArray(newErrors)) {
				errors = errors.concat(...newErrors);
			} else {
				errors.push(newErrors);
			}
		}
		return errors;
	}

	private setErrors(errors) {
		this._errors = errors;
		this._errorsChanges.next(errors);
	}

	protected searchProperty(path: string): FormProperty {
		let prop: FormProperty = this;
{'fraction_non_alphanumeric': 0.11986466892218463, 'fraction_numerical': 0.00032221685194135655, 'mean_word_length': 4.45518453427065, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4213026', 'n_tokens_mistral': 2038, 'n_tokens_neox': 1850, 'n_words': 461}