Home Reference Source Repository

src/IsolatedObjectShadowImpl.js

import omit from "lodash.omit";
import isEqual from "lodash.isequal";
import isPlainObject from "lodash.isplainobject";

import IsolatedProperty from "./IsolatedProperty";
import ShadowImpl from "./ShadowImpl";
import reshadow from "./reshadow";


const _implsCacheKey = Symbol("implsCacheKey");
const _keysCacheKey = Symbol("keysCacheKey");
const _valuesCacheKey = Symbol("valuesCacheKey");


export default class IsolatedObjectShadowImpl extends ShadowImpl {
	/*
		Removes all subproperties.
	*/
	clear() {
		this.isolated().removeAllFor(this.property());
		this.update( state => ({ name: `clear()`, nextState: state }) );
	}

	/*
		Removes a subproperty from this state property.
	*/
	delete(k) {
		this.isolated().remove(k, this.property());
		this.update( state => ({ name: `delete(${k})`, nextState: state }) );
	}

	/*
		Gets a copy of the implementation objects.

		@return {object} key=name, value=property
	*/
	entries() {
		return this.isolated().entires(this.property());
	}

	extend(sources) {
		const keys = Object.keys(sources);
		var key;

		for (let i=0, len=keys.length; i<len; i++) {
			key = keys[i];

			this.set(key, sources[key])
		}
	}

	/*
		Gets the property implementation for a state property.
	*/
	get(k) {
		const isoProp = this.isolated().get(k, this.property());
		const isoShadow = isoProp && isoProp._();

		if (isoProp && isoProp.isActive()) {
			return isoProp._().data.__()
		} else {
			return undefined;
		}
	}

	/*
		Gets if this state property has a subproperty with a specified name.
	*/
	has(k) {
		return !!this.get(k);
	}

	isolated() {
		return this.store().isolated();
	}

	/*
		Gets the keys of all managed subproperties. Returns an array.
	*/
	keys() {
		const cache = this.cache();

		if (!cache[_keysCacheKey]) {
			const isoProps =  this.isolated().all(this.property());

			cache[_keysCacheKey] = isoProps.map( p => p.name() );
		}

		return cache[_keysCacheKey];
	}

	/*
		Sets a subproperty value. Replaces current state property if one has an identical name.
	*/
	set(k, v) {
		const managedType = this.property().stateType().getManagedType();
		const isoType = IsolatedProperty.type
				.initialState({ data: v })
				.managedType(managedType);

		this.isolated().set(k, isoType, this.property());
		this.update( state => ({ name: `set(${k})`, nextState: state }) );

		return this;
	}

	size() {
		return this.isolated().count(this.property());
	}

	/*
		Gets subproperty implementation objects. Returns an array.
	*/
	values() {
		const cache = this.cache();

		if (!cache[_valuesCacheKey]) {
			const isoProps =  this.isolated().all(this.property());

			cache[_valuesCacheKey] = isoProps.map( p => p._().data.__() );
		}

		return cache[_valuesCacheKey];
	}


	//------------------------------------------------------------------------------------------------------
	//	Overridden methods
	//------------------------------------------------------------------------------------------------------

	childCount() {
		return this.size();
	}

	children() {
		const cache = this.cache();

		if (!cache[_implsCacheKey]) {
			let isoProps =  this.isolated().all(this.property());

			cache[_implsCacheKey] = isoProps.map( p => p.__() );
		}

		return cache[_implsCacheKey];
	}

	defaults(state) {
		console.warn("defaults() not supported")
	}

	/*
		Maps all child properties onto this property using Object.defineProperty().
	*/
	defineChildProperties(prev, inCtor) {
		this.isolated().update(this.property());
	}


	hasChildren() {
		return !!this.size();
	}

	merge(state) {
		console.warn("merge() not supported")
	}
}