whole_func_string: function (opts, tree) {
  	var fileName;
  	this.tree = tree;
  	this.resolved = false;
  	this.dependants = [];
  	// filePath
  	this.filePath = opts.filePath || false;
  	if (opts.filePath && typeof opts.filePath !== 'string') {
  		throw new Error( 'Bad argument: filePath' );
  	}
  	// name without extension
  	if (this.filePath) {
  		fileName = path.basename( this.filePath, path.extname( this.filePath ));
  	// raw
  		this.raw = require( this.filePath );
  	} else {
  		this.raw = opts.raw;
  	}
  	// key
  	this.key = opts.key || fileName;
  	if (typeof this.key !== 'string') {
  		throw new Error( 'Bad argument: key' );
  	}
  	if (startsWithNumber( this.key )) {
  		throw new Error( 'Module name can\'t start with number: ' + this.key );
  	}
  	// localname
  	this.localname = opts.localname || opts.key;
  	// check if localname is a string and don't start with number'
  	if (opts.localname && (typeof opts.localname !== 'string' || startsWithNumber( opts.localname ))) {
  		throw new Error( 'Bad argument: localname' );
  	}
  	// processing
  	if (opts.processing) {
  		this.processing = opts.processing;
  	}
  
  	this.isPlugin = isPlugin( this.raw );
  	if (this.isPlugin) {
  		this.dependencies = getParamNames( this.raw.wiretree );
  		this.isAsync = this.dependencies.indexOf( 'wtDone' ) >= 0 ? true : false;
  	} else {
  		this.res = getProcessed( this.processing, this.raw );
  		this.resolved = true;
  		this.dependencies = [];
  		this.isAsync = false;
  	}
  	// check if group is a string and don't start with number'
  	if (opts.group && (typeof opts.group !== 'string' || startsWithNumber( opts.group ))) {
  		throw new Error( 'Bad argument: group' );
  	}
  
  	// set group
  	if (opts.group) {
  		if (opts.hidden) {
  			this.hidden = true;
  			this.key = this.key + uniid();
  		}
  		this.group = opts.group;
  		// create group if not exist
  		tree.groups[this.group] = tree.groups[this.group] || new Group( this.group, this.tree );
  		// add plugin to group
  		tree.groups[this.group].plugins[this.localname] = this;
  	}
  
  	tree.plugins[this.key] = this;
  }
func_code_string: function (opts, tree) {
  	var fileName;
  	this.tree = tree;
  	this.resolved = false;
  	this.dependants = [];
  	// filePath
  	this.filePath = opts.filePath || false;
  	if (opts.filePath && typeof opts.filePath !== 'string') {
  		throw new Error( 'Bad argument: filePath' );
  	}
  	// name without extension
  	if (this.filePath) {
  		fileName = path.basename( this.filePath, path.extname( this.filePath ));
  	// raw
  		this.raw = require( this.filePath );
  	} else {
  		this.raw = opts.raw;
  	}
  	// key
  	this.key = opts.key || fileName;
  	if (typeof this.key !== 'string') {
  		throw new Error( 'Bad argument: key' );
  	}
  	if (startsWithNumber( this.key )) {
  		throw new Error( 'Module name can\'t start with number: ' + this.key );
  	}
  	// localname
  	this.localname = opts.localname || opts.key;
  	// check if localname is a string and don't start with number'
  	if (opts.localname && (typeof opts.localname !== 'string' || startsWithNumber( opts.localname ))) {
  		throw new Error( 'Bad argument: localname' );
  	}
  	// processing
  	if (opts.processing) {
  		this.processing = opts.processing;
  	}
  
  	this.isPlugin = isPlugin( this.raw );
  	if (this.isPlugin) {
  		this.dependencies = getParamNames( this.raw.wiretree );
  		this.isAsync = this.dependencies.indexOf( 'wtDone' ) >= 0 ? true : false;
  	} else {
  		this.res = getProcessed( this.processing, this.raw );
  		this.resolved = true;
  		this.dependencies = [];
  		this.isAsync = false;
  	}
  	// check if group is a string and don't start with number'
  	if (opts.group && (typeof opts.group !== 'string' || startsWithNumber( opts.group ))) {
  		throw new Error( 'Bad argument: group' );
  	}
  
  	// set group
  	if (opts.group) {
  		if (opts.hidden) {
  			this.hidden = true;
  			this.key = this.key + uniid();
  		}
  		this.group = opts.group;
  		// create group if not exist
  		tree.groups[this.group] = tree.groups[this.group] || new Group( this.group, this.tree );
  		// add plugin to group
  		tree.groups[this.group].plugins[this.localname] = this;
  	}
  
  	tree.plugins[this.key] = this;
  }
func_documentation_string: /*!
  Plugin constructor
  @param {Object} opts plugin data
  @param {Object} tree parent tree