----------------------------------------------------------------------------- Rule Definition -----------------------------------------------------------------------------
340207
function create(context) {
    return {
        AssignmentExpression(node) {
            if (assignsToExportsProperty(node) && ancestor(isCommonJsWrapper, node)) {
                context.report(node, messages);
            }
        }
    };
}
1327453
function setRuleModule (roles, rule, rules, origRule) {
    // allow/deny is last element of rule
    var allow = rule.pop()
    // blanket rule for all modules
    if (rule.length === 0) {
        // create role access rule map
        if (!rules.allow) {
            rules.allow = {}
        }
        // set rule for each role
        _.each(roles, role => {
            rules.allow[role] = allow
        })
        // break
        return
    }

    // module name is first clause of rule
    var module = rule.shift()
    // create map of models
    if (!rules.module) {
        rules.module = {}
    }
    // create entry for module
    if (!rules.module[module]) {
        rules.module[module] = {}
    }

    // blanket rule for single module
    if (rule.length === 0) {
        // create role access rule map
        if (!rules.module[module].allow) {
            rules.module[module].allow = {}
        }
        // set rule for each role
        _.each(roles, role => {
            rules.module[module].allow[role] = allow
        })
    }
    // rule for method
    else if (rule.length === 1) {
        var method = rule.shift()
        // create map of methods
        if (!rules.module[module].method) {
            rules.module[module].method = {}
        }
        // create method entry
        if (!rules.module[module].method[method]) {
            rules.module[module].method[method] = {}
        }
        // create role access rule map
        if (!rules.module[module].method[method].allow) {
            rules.module[module].method[method].allow = {}
        }
        // set rule for each role
        _.each(roles, role => {
            rules.module[module].method[method].allow[role] = allow
        })
    }
    // invalid rule
    else {
        throw new Error('invalid rule '+origRule)
    }
}
635026
public function rules()
    {
        $rules = parent::rules();
        $rules = array_merge($rules, [
            ['fieldTwig', 'string'],
            ['fieldTwig', 'default', 'value' => ''],
            ['columnType', 'string'],
            ['columnType', 'default', 'value' => ''],
            ['decimals', 'number'],
            ['decimals', 'default', 'value' => 0],
            ['textareaRows', 'number'],
            ['textareaRows', 'default', 'value' => 5],
            ['parseBeforeSave', 'boolean'],
            ['parseBeforeSave', 'default', 'value' => false],
            ['parseOnMove', 'boolean'],
            ['parseOnMove', 'default', 'value' => false],
            ['displayType', 'string'],
            ['displayType', 'default', 'value' => 'hidden'],
            ['allowSelect', 'boolean'],
            ['allowSelect', 'default', 'value' => false],
        ]);

        return $rules;
    }
717024
public void addRules(Rules rules) {
        if (logger.isDebugEnabled()) {
            logger.debug("Adding rules -> " + rules);
        }
        addRules(DEFAULT_CONTEXT_ID, rules);
    }
967321
function Base (type, rule) {
  this._type = type || '';
  this._column = rule.getColumn();
  this._mapping = rule.getMapping();
  this._property = rule.getProperty();
}
678829
function hasParentRule(rule) {
  if (!rule.parent) {
    return false
  }

  if (rule.parent.type === 'rule') {
    return true
  }

  return hasParentRule(rule.parent)
}
720890
public function collectRule(Rule $rule): void
    {
        $this->data['rule'] = [
            'id' => $rule->getId(),
        ];

        foreach ($rule->getTargets() as $target) {
            $this->data['rule']['targets'][] = [
                'type' => $target->getTargetType()::getType(),
                'value' => $this->formatVar($target->getValue()),
            ];
        }

        foreach ($rule->getConditions() as $condition) {
            $this->data['rule']['conditions'][] = [
                'type' => $condition->getConditionType()::getType(),
                'value' => $this->formatVar($condition->getValue()),
            ];
        }
    }
310545
public synchronized void addRule(final RuleImpl rule) throws InvalidPatternException {
        final List<TerminalNode> terminals = this.ruleBuilder.addRule( rule,
                                                                       this.kBase );

        BaseNode[] nodes = terminals.toArray( new BaseNode[terminals.size()] );
        this.rules.put( rule.getFullyQualifiedName(), nodes );
        if (rule.isQuery()) {
            this.queries.put( rule.getName(), nodes );
        }
    }
900910
@Nonnull
    private Rule rule( FormattableContainer parent, String selector, Operation params, Expression guard ) {
        Rule rule = new Rule( reader, parent, selector, params, guard );
        parseRule( rule );
        return rule;
    }
67008
public void setRules(java.lang.String rules) {
        getStateHelper().put(PropertyKeys.rules, rules);
        handleAttribute("rules", rules);
    }
490939
function Rules (options) {
  this.options = options;
  this._keep = [];
  this._remove = [];

  this.blankRule = {
    replacement: options.blankReplacement
  };

  this.keepReplacement = options.keepReplacement;

  this.defaultRule = {
    replacement: options.defaultReplacement
  };

  this.array = [];
  for (var key in options.rules) this.array.push(options.rules[key]);
}
984147
public function setRule($rule)
	{
		if(null === $rule)
		{
			$rule = Dispatch::module() . '/' . Dispatch::control() . '/' . Dispatch::action();
		}
		$this->rule = $rule;
	}
459913
public final void ruleParserRule() throws RecognitionException {

        		int stackSize = keepStackSize();
        	
        try {
            // InternalXtext.g:241:2: ( ( ( rule__ParserRule__Group__0 ) ) )
            // InternalXtext.g:242:2: ( ( rule__ParserRule__Group__0 ) )
            {
            // InternalXtext.g:242:2: ( ( rule__ParserRule__Group__0 ) )
            // InternalXtext.g:243:3: ( rule__ParserRule__Group__0 )
            {
             before(grammarAccess.getParserRuleAccess().getGroup()); 
            // InternalXtext.g:244:3: ( rule__ParserRule__Group__0 )
            // InternalXtext.g:244:4: rule__ParserRule__Group__0
            {
            pushFollow(FollowSets000.FOLLOW_2);
            rule__ParserRule__Group__0();

            state._fsp--;


            }

             after(grammarAccess.getParserRuleAccess().getGroup()); 

            }


            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {

            	restoreStackSize(stackSize);

        }
        return ;
    }
1034183
function setRule (rule, isDefault) {
    // clear id for existing rules
    this.id = undefined
    // if this is default rule then add to list
    if (isDefault) {
        this.defaultRules.push(_.cloneDeep(rule))
    }
    // capture original rule as string for error logging
    var origRule = rule.join(',')
    // require array
    assert.ok(Array.isArray(rule), 'rule array required')
    // get roles array
    var roles = rule
    // get rule string from last element in array
    rule = roles.pop()
    // require rule to be a string
    assert.ok(typeof rule === 'string', 'invalid rule '+origRule)
    // require at least one role
    assert.ok(roles.length, 'one or more roles required '+origRule)
    // split rule on colon to separate into clauses
    var ruleClauses = rule.split(':')
    // first clause must identify type of resource
    var resourceType = ruleClauses.shift()
    // get index of last element in rule
    var lastIdx = ruleClauses.length - 1
    // final element in rule must be 1 or 0 to indicate allow or deny
    var allow = parseInt(ruleClauses[lastIdx])
    // validate
    assert.ok(allow === 0 || allow === 1, 'allow must be 0 or 1 '+origRule)
    // set value to boolean
    ruleClauses[lastIdx] = allow
    // deny rule only allowed on all role
    if (allow === 0) {
        assert.ok(roles.length === 1 && roles[0] === 'all', 'deny can only be set for all role '+origRule)
    }
    // require valid resource type
    assert.ok(resourceTypes[resourceType], 'invalid resource type '+origRule)
    // create entry from resource type if it does not exist
    if (!this.rules[resourceType]) {
        this.rules[resourceType] = {}
    }
    // call type specific method to set rule
    resourceTypes[resourceType](roles, ruleClauses, this.rules[resourceType], origRule)
}
72973
public void setRules(java.util.Collection<Rule> rules) {
        if (rules == null) {
            this.rules = null;
            return;
        }

        this.rules = new java.util.ArrayList<Rule>(rules);
    }
634044
public function rules($rules, $method = '*', array $option = [], array $pattern = [])
    {
        $this->group->addRules($rules, $method, $option, $pattern);
    }
619290
function processRules(rules) {


		if (rules !== undefined) {

			rCount = rules.length;

			//reduce common declarations amongst children into parent
			if (OPTIONS.new_reduce_common_into_parent) {


				var directParents = [];
				var hierachy = [];
				var hierachyKeys = [];
				var hierachyLen = 0;
				var selectedHierachyLevel = 0;
				var commonParentsIdx = -1;
				var commonParentsKeys = [];
				var commonParents = [];
				var commonParentsLen = 0;
				var commonParent = '';
				var commonParent2 = '';
				var commonParentTotal = 0;
				var commonParentDeclarations = [];
				var commonLineage = '';
				var newParentDeclarations = [];
				var processedCommonParentsChildren = [];
				var classLineage = '';
				var parentClassLineage = '';
				var lineageLabel = '';
				var tmpDeclarations = [];

				for (i = 0; i < rCount; ++i) {

					///rules
					//group classes - create hierarchy
					if (rules[i].selectors !== undefined) {
						for (j = 0; j < rules[i].selectors.length; j++) { //each comma delimited
							
							if (rules[i].selectors[j].indexOf('.') != -1) {

								classLineage = rules[i].selectors[j].split(' ');
								parentClassLineage = classLineage.slice(0); //clone
								parentClassLineage.pop();
								parentClassLineage = parentClassLineage.join(' ');

								if (parentClassLineage !== undefined && parentClassLineage != '') {

									if (directParents[parentClassLineage] !== undefined) {
										directParents[parentClassLineage].push({
											selector: rules[i].selectors[j],
											index: i
										});
									} else {
										directParents[parentClassLineage] = [{
											selector: rules[i].selectors[j],
											index: i
										}];	
									}
									
								}


								for (k = 0; k < classLineage.length; k++) { //depth of hierachy

									if (k > 0) {
										lineageLabel = '';

										for (l = k; l > 0; l--) {
											lineageLabel += classLineage[k-l] + ' ';	
										}
										lineageLabel += classLineage[k];	

										if (hierachy[lineageLabel] === undefined) {
											hierachy[lineageLabel] = 0;
										}

										hierachy[lineageLabel] += 1;

									} else {

										if (hierachy[classLineage[k]] === undefined) {
											hierachy[classLineage[k]] = 0;
										}

										hierachy[classLineage[k]] += 1;
									}
								} //end of for
							} //end of if
						} //end of for
					}
				}

				function sortHierachy(obj) {
					var keys = Object.keys(obj);
					keys.sort(function(a,b){return b.length-a.length})
					hierachy = [];
					for (i = 0; i < keys.length; i++) {

						hierachy[keys[i]] = obj[keys[i]];


						Object.keys(directParents).forEach(function(key, index, val) {
						  
						  if (this[key].length > 1) {
							  for (j = 0; j < this[key].length; j++) {

							  	if (keys[i] == this[key][j].selector) {

								  	if (OPTIONS.verbose) { console.log(success('Process - Rules - Group Common Parent Rule : ' + keys[i] ));}
								  	commonParentsKeys.push({
								  		selector: key,
								  		index: this[key][j].index,
								  		childSelector: keys[i]
								  	});
								  }
							  }
							}

						}, directParents);
					}
					return hierachy;
				}
				sortHierachy(hierachy);
				hierachyKeys = Object.keys(hierachy);
				hierachyLen = hierachyKeys.length;
				selectedHierachyLevel = 0;
				commonParentsLen = commonParentsKeys.length;

				// get declarations
				for (i = 0; i < commonParentsKeys.length; i++) {

					if (rules[commonParentsKeys[i].index].declarations !== undefined) {

						for (j = 0; j < rules[commonParentsKeys[i].index].declarations.length; j++) {

							if (commonParentDeclarations[rules[commonParentsKeys[i].index].declarations[j].property + '_' + rules[commonParentsKeys[i].index].declarations[j].value] !== undefined) {

								commonParentDeclarations[rules[commonParentsKeys[i].index].declarations[j].property + '_' + rules[commonParentsKeys[i].index].declarations[j].value].count += 1;

							} else {
								commonParentDeclarations[rules[commonParentsKeys[i].index].declarations[j].property + '_' + rules[commonParentsKeys[i].index].declarations[j].value] = {

									property: rules[commonParentsKeys[i].index].declarations[j].property,
									value: rules[commonParentsKeys[i].index].declarations[j].value,
									count: 1,
									selector: rules[commonParentsKeys[i].index].selectors,
									selectorIndex: commonParentsKeys[i].index,
									commonParent: commonParentsKeys[i].selector
								};
							}
						}

					}

				}

				Object.keys(commonParentDeclarations).forEach(function(val, index, key) {

					if (this[val].count == directParents[this[val].commonParent].length) {

						if (newParentDeclarations[this[val].commonParent] !== undefined) {
							newParentDeclarations[this[val].commonParent].declarations.push({
								type: 'declaration',
								property: this[val].property,
								value: this[val].value
							});
						} else {
							newParentDeclarations[this[val].commonParent] = {
								declarations: [{
									type: 'declaration',
									property: this[val].property,
									value: this[val].value
								}],
								selectorIndex: this[val].selectorIndex
							};
						}

						commonParents.push(this[val].commonParent);
					}

				}, commonParentDeclarations);


				commonParentsLen = commonParentsKeys.length;

				for (i = 0; i < commonParentsLen; i++) {

					Object.keys(newParentDeclarations).forEach(function(key, index) {

						if (commonParentsKeys[i] !== undefined && commonParentsKeys[i].selector == key) {

						  if (rules[commonParentsKeys[i].index] !== undefined && rules[commonParentsKeys[i].index].declarations !== undefined) {
						  	
						  	//clone declarations
						  	tmpDeclarations = rules[commonParentsKeys[i].index].declarations.slice(0); //clone
						  	dCount = tmpDeclarations.length;
							  
						  	for (j = 0; j < this[key].declarations.length; j++) { //each parent declaration

							  	//remove declarations
							  	for (k = 0; k < dCount; k++) { //each child declaration

							  		if (
							  			this[key].declarations[j] !== undefined
							  			&& this[key].declarations[j].type == 'declaration'
							  			&& this[key].declarations[j].property == tmpDeclarations[k].property
							  			&& this[key].declarations[j].value == tmpDeclarations[k].value
							  		) {
							  			tmpDeclarations.splice(k, 1); 
							  			k -= 1;
							  			dCount-=1;
							  		}
							  	} //end of k loop

							  } //end of j loop
							  
							  if (tmpDeclarations.length == 0) {

							  	//remove whole rule
							  	rules.splice(commonParentsKeys[i].index, 1);
							  	i-=1;
							  	commonParentsLen-=1;

							  } else {
							  	//update declarations
							  	rules[commonParentsKeys[i].index].declarations = tmpDeclarations;
							  }
								  	
						  }
						}
					  
					}, newParentDeclarations);
				} //end of i loop

				//Create Common Parents
				Object.keys(newParentDeclarations).forEach(function(key, index) {
				  
				  rules.splice( ((this[key].selectorIndex-1 < 0) ? this[key].selectorIndex : this[key].selectorIndex-1), 0, {
						type : 'rule',
						selectors: [key],
						declarations: this[key].declarations
					});

				}, newParentDeclarations);

				//some cleanup
				directParents = [];
				hierachy = [];
				hierachyKeys = [];
				commonParentsKeys = [];
				commonParents = [];
				commonParentDeclarations = [];
				newParentDeclarations = [];
				processedCommonParentsChildren = [];
				tmpDeclarations = [];
				
				//reset rules count
				rCount = rules.length;

			} //end of reduce common declarations amongst children into parent





			for (i = 0; i < rCount; ++i) {

				////comments
				//checking declarations for comments
				if (rules[i] !== undefined && rules[i].declarations !== undefined) {
					declarations = rules[i].declarations;
					dCount = declarations.length;

					for (j = 0; j < dCount; ++j) {

						//check for empty properties
						if (rules[i].declarations[j].value == '') {
							summary.empty_declarations.push({
								'selectors': rules[i].selectors,
								'property': rules[i].declarations[j]
							});
						}

						//remove comments in declarations - for turning off comments
						if (OPTIONS.trim_comments || OPTIONS.trim) {
							if (declarations[j] !== undefined && declarations[j].type == 'comment') {
								if (OPTIONS.verbose) { console.log(info('Process - Rules - Remove Comment')); }
								rules[i].declarations.splice(j, 1);
								j-=1;
								dCount-=1;
							}
						}
					}
				}

				//remove comments in root - for turning off comments
				if (OPTIONS.trim_comments || OPTIONS.trim) {
					if (rules[i] !== undefined && rules[i].type == 'comment') {
						if (OPTIONS.verbose) { console.log(info('Process - Rules - Remove Comment')); }
						rules.splice(i, 1);
						i-=1;
						rCount-=1;
					}
				}
				////end of comments


				////rules
				//remove duplicate root rules
				for (j = i+1; j < rCount; ++j) {
					// console.log(j, rCount)
					//root rules
					//rule selector
					if (rules[i] !== undefined 
						// && rules[i].type == 'rule'
						&& rules[i].selectors !== undefined 
						&& rules[j] !== undefined && rules[j].selectors !== undefined) {

						//duplicate rule found
						if (rules[i].selectors.toString() == rules[j].selectors.toString()) {

							//remove previous comment in root
							if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
								if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {

									rules.splice(i-1, 1);
									i-=1;
									j-=1;
									rCount-=1;
								}
							}

							if (OPTIONS.verbose) { console.log(success('Process - Rules - Group Duplicate Rule : ' + (rules[j].selectors ? rules[j].selectors.join(', ') : '')));}

							//copy + reduce
							summary.stats.summary.noDuplicateRules += 1;
							if ( j < i && (j-i) > 1 ) { //check comparison distance
								summary.duplicate_rules.push({
									'selectors': (rules[i].type == 'page') ? '@page' : rules[i].selectors,
									'position': rules[i].position
								});
								rules[j].declarations = rules[j].declarations.concat(rules[i].declarations);
								rules.splice(i, 1);
							} else {
								summary.duplicate_rules.push({
									'selectors': (rules[j].type == 'page') ? '@page' : rules[j].selectors,
									'position': rules[j].position
								});
								rules[i].declarations = rules[i].declarations.concat(rules[j].declarations);
								rules.splice(j, 1);
							}
							i-=1;
							j-=1;
							rCount-=1;				

						}
					} //end of rule selector

					//media selector - it could affect evaluation sequence
					if (rules[i] !== undefined && rules[i].type == 'media' 
						&& rules[i].media !== undefined 
						&& rules[j] !== undefined && rules[j].media !== undefined
						&& OPTIONS.bypass_media_rules != true
					) {

						//duplicate rule found
						if (rules[i].media.toString() == rules[j].media.toString()) {

							//remove previous comment in root
							if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
								if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {

									rules.splice(i-1, 1);
									i-=1;
									j-=1;
									rCount-=1;
								}
							}

							if (OPTIONS.verbose) { console.log(info('Process - Rules - @media - Group Duplicate Rule : ' + (rules[j].selectors ? rules[j].selectors.join(', ') : ''))); }

							//copy + reduce
							summary.stats.summary.noDuplicateRules += 1;
							if ( j < i && (j-i) > 1 ) { //check comparison distance
								summary.duplicate_rules.push({
									'selectors': '@media ' + rules[i].media,
									'position': rules[i].position
								});
								rules[j].rules = rules[j].rules.concat(rules[i].rules);
								rules.splice(i, 1);
							} else {
								summary.duplicate_rules.push({
									'selectors': '@media ' + rules[j].media,
									'position': rules[j].position
								});
								rules[i].rules = rules[i].rules.concat(rules[j].rules);
								rules.splice(j, 1);
							}
							i-=1;
							j-=1;
							rCount-=1;
						}
					} 
					//end of media selector

					//document selector
					if (rules[i] !== undefined && rules[i].type == 'document' 
						&& rules[i].document !== undefined 
						&& rules[j] !== undefined && rules[j].document !== undefined) {

						//duplicate rule found
						if (rules[i].document.toString() == rules[j].document.toString()) {

							//remove previous comment in root
							if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
								if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {

									rules.splice(i-1, 1);
									i-=1;
									j-=1;
									rCount-=1;
								}
							}

							if (OPTIONS.verbose) { console.log(success('Process - Rules - @document - Group Duplicate Rule : ' + (rules[j].selectors ? rules[j].selectors.join(', ') : ''))); }

							//copy + reduce
							summary.stats.summary.noDuplicateRules += 1;
							if ( j < i && (j-i) > 1 ) { //check comparison distance
								summary.duplicate_rules.push({
									'selectors': '@document ' + rules[i].document,
									'position': rules[i].position
								});
								rules[j].rules = rules[j].rules.concat(rules[i].rules);
								rules.splice(i, 1);
							} else {
								summary.duplicate_rules.push({
									'selectors': '@document ' + rules[j].document,
									'position': rules[j].position
								});
								rules[i].rules = rules[i].rules.concat(rules[j].rules);
								rules.splice(j, 1);
							}
							i-=1;
							j-=1;
							rCount-=1;
							
						}
					} //end of document selector

					//supports selector
					if (rules[i] !== undefined && rules[i].type == 'supports' 
						&& rules[i].supports !== undefined 
						&& rules[j] !== undefined && rules[j].supports !== undefined) {

						//duplicate rule found
						if (rules[i].supports.toString() == rules[j].supports.toString()) {

							//remove previous comment in root
							if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
								if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {

									rules.splice(i-1, 1);
									i-=1;
									j-=1;
									rCount-=1;
								}
							}

							
							if (OPTIONS.verbose) { console.log(success('Process - Rules - @supports - Group Duplicate Rule : ' + (rules[j].supports ? rules[j].supports : ''))); }

							//copy + reduce
							summary.stats.summary.noDuplicateRules += 1;
							if ( j < i && (j-i) > 1 ) { //check comparison distance
								summary.duplicate_rules.push({
									'selectors': '@supports ' + rules[i].supports,
									'position': rules[i].position
								});
								rules[j].rules = rules[j].rules.concat(rules[i].rules);
								rules.splice(i, 1);
							} else {
								summary.duplicate_rules.push({
									'selectors': '@supports ' + rules[j].supports,
									'position': rules[j].position
								});
								rules[i].rules = rules[i].rules.concat(rules[j].rules);
								rules.splice(j, 1);
							}
							i-=1;
							j-=1;
							rCount-=1;
							

						}
					} //end of supports selector



				} //end of j
				////end of rules


				////declarations
				//reduce root delcarations by property name and by duplicate values
				if (rules[i] !== undefined 
					&& (rules[i].type == 'rule' || (rules[i].type == 'page' && OPTIONS.bypass_page_rules == false))
				) {

					declarationsNameCounts = [];

					dCount = rules[i].declarations.length;

					//declarations duplicate check
					for (l = 0; l < dCount; ++l) {

						if (rules[i].declarations[l].type == 'declaration') {
							if (declarationsNameCounts[rules[i].declarations[l].property] !== undefined) {
								declarationsNameCounts[rules[i].declarations[l].property] += 1;
							} else {
								declarationsNameCounts[rules[i].declarations[l].property] = 1;
							}
						}
					} //end of declarations duplicate check


					//reduce according to values
					declarationsValueCounts = [];
					valKey = '';
					//detect duplicate values
					for (key in declarationsNameCounts) {

			      if (!reduceRulesListName.includes(key)) { //only properties not in list


							for (l = 0; l < dCount; ++l) {

								if (
									rules[i].declarations[l].type == 'declaration'
									&& rules[i].declarations[l].property == key
								) {
									hash = crypto.createHash('sha256');
									hash.update(rules[i].declarations[l].property + rules[i].declarations[l].value);
									
									valKey = hash.digest('hex');

									if (declarationsValueCounts[valKey] !== undefined) {
										declarationsValueCounts[valKey].id += ',' + l;
										declarationsValueCounts[valKey].count += 1;
									} else {
										declarationsValueCounts[valKey] = {
											id : l,
											count : 1
										}
									}
								}
							}
			      }
			    }

			    //remove duplicate declarations by duplicate values
			    declarationsValueCountsCount = Object.keys(declarationsValueCounts).length;

			    amountRemoved = 1;

					for (key in declarationsValueCounts) {
			      if (declarationsValueCounts.hasOwnProperty(key)) {


			      	if (declarationsValueCounts[key].count > 1) {
			      		duplicate_ids = declarationsValueCounts[key].id.split(',');

			      		amountRemoved = 1; //shift the ids by the amount removed
								for (l = 0; l < duplicate_ids.length-1; ++l) { // -1 to leave last behind

									//remove previous comment above declaration to be removed
									if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {

										if (rules[i].declarations[duplicate_ids[l]-1] !== undefined && rules[i].declarations[duplicate_ids[l]-1].type == 'comment') {

											rules[i].declarations.splice(duplicate_ids[l]-1, 1);
											dCount-=1;

											//adjust removal ids by amount already removed
											if (duplicate_ids[l] !== undefined) {
												duplicate_ids[l] -= amountRemoved; //shift the ids by the amount removed
											}
											amountRemoved += 1;
										}
									}

									if (OPTIONS.verbose) { console.log(success('Process - Declaration - Group Duplicate Declarations : ' + (rules[i].selectors ? rules[i].selectors.join(', ') : '') + ' - ' + (rules[i].declarations[l]!==undefined?rules[i].declarations[l].property:''))); }

									summary.duplicate_declarations.push(rules[i].declarations[duplicate_ids[l]]);
									summary.stats.summary.noDuplicateDeclarations += 1;
									rules[i].declarations.splice(duplicate_ids[l], 1);
									dCount-=1;

									//adjust removal ids by amount already removed
									if (duplicate_ids[l+1] !== undefined) {
										duplicate_ids[l+1] -= amountRemoved; //shift the ids by the amount removed

										//shift all the ids of the declarations afterwards
										for (key2 in declarationsValueCounts) {
											if (declarationsValueCounts.hasOwnProperty(key2) && (key2 != key)) {

												if (typeof declarationsValueCounts[key2].id == 'number') {
													duplicate_ids = [];
													duplicate_ids[0] = declarationsValueCounts[key2].id;
												} else {
													duplicate_ids = declarationsValueCounts[key2].id.split(',');	
												}
							      		
							      		for (l = 0; l < duplicate_ids.length; ++l) {
							      			
													if (duplicate_ids[l] !== undefined) {
								      			duplicate_ids[l] -= amountRemoved;
								      		}
							      		}
							      		declarationsValueCounts[key2].id = duplicate_ids.join();
											}
										}
										//end of shifting all ids

									}
									amountRemoved += 1;
								}

				      } //end of if
			      } //end of if
			    } //end of for in
					//end of reduce according to values

					for (k = 0; k < reduceRulesListNameCount; ++k) {

						//declarations reduction
						for (key in declarationsNameCounts) {
				      if (declarationsNameCounts.hasOwnProperty(key)) {

								if (declarationsNameCounts[key] > 1) {

									for (l = 0; l < dCount; ++l) {
										if (rules[i].declarations[l].type == 'declaration') {

											if (
												rules[i].declarations[l].property == key 
												&& declarationsNameCounts[key] > 1 //leave behind 1
											) {

												//reduce according to list
												if (rules[i].declarations[l].property == reduceRulesListName[k]) { 
													
													// console.log(declarationsNameCounts[key])
													// console.log(key)
													// console.log(rules[i].declarations[l].property)
													// console.log(reduceRulesListName[k])

													//remove previous comment above declaration to be removed
													if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
														if (rules[i].declarations[l-1] !== undefined && rules[i].declarations[l-1].type == 'comment') {

															rules[i].declarations.splice(l-1, 1);
															l-=1;
															dCount-=1;
														}
													}

													if (OPTIONS.verbose) { console.log(success('Process - Declaration - Group Duplicate Declarations : ' + (rules[i].selectors ? rules[i].selectors.join(', ') : '') + ' - ' + (rules[i].declarations[l]!==undefined?rules[i].declarations[l].property:''))); }

													// console.log(rules[i].declarations[l].value.indexOf('!important') !== -1)
													// console.log(rules[i].declarations[l].value)
													// console.log(rules[i].declarations[l+1].value)

													//prioritises !important declarations
													if (rules[i].declarations[l].value.indexOf('!important') !== -1) {
														
														summary.duplicate_declarations.push(rules[i].declarations[l+1]);
														summary.stats.summary.noDuplicateDeclarations += 1;
														rules[i].declarations.splice(l+1, 1);

													} else {

														summary.duplicate_declarations.push(rules[i].declarations[l]);
														summary.stats.summary.noDuplicateDeclarations += 1;
														rules[i].declarations.splice(l, 1);
													}

													l-=1;
													dCount-=1;
													declarationsNameCounts[key] -= 1;
												}
											}
										}
									}
								}
							}
						}
					} //end of reduce root declarations by property name

				} //end of rule check



				//reduce root declarations by selector
				selectorPropertiesList = [];
				declarationsCounts = [];
				for (k = 0; k < reduceRulesListSelectorCount; ++k) {

					if (rules[i] !== undefined 
						&& rules[i].type == 'rule'
					) {

						if (rules[i].selectors !== undefined && rules[i].selectors.toString() === reduceRulesListSelector[k]) {
						
							dCount = rules[i].declarations.length;

							//detect declarations duplicates
							for (l = 0; l < dCount; ++l) {
								if (rules[i].declarations[l].type == 'declaration'
								) {
									if (declarationsCounts[rules[i].declarations[l].property] !== undefined) {
										declarationsCounts[rules[i].declarations[l].property] += 1;
									} else {
										declarationsCounts[rules[i].declarations[l].property] = 1;
									}
								}
							} //end of declarations duplicate check

							// declarations reduction
							for (key in declarationsCounts) {
					      if (declarationsCounts.hasOwnProperty(key)) {

									if (declarationsCounts[key] > 1) {

										for (l = 0; l < dCount; ++l) {
											if (rules[i].declarations[l].type == 'declaration') {

												selectorPropertiesList = reduceRulesListSelectorPName[reduceRulesListSelector[k]];
												
												if (selectorPropertiesList !== undefined) { //specific in selector

													if (rules[i].declarations[l].property == key 
														&& (selectorPropertiesList.indexOf(rules[i].declarations[l].property) != -1)
														&& declarationsCounts[key] > 1) { //leave behind 1

														//remove previous comment above declaration to be removed
														if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
															if (rules[i].declarations[l-1] !== undefined && rules[i].declarations[l-1].type == 'comment') {

																rules[i].declarations.splice(l-1, 1);
																l-=1;
																dCount-=1;
															}
														}

														if (OPTIONS.verbose) { console.log(success('Process - Declaration - Group Duplicate Declarations : ' + (rules[i].selectors ? rules[i].selectors.join(', ') : '') + ' - ' + (rules[i].declarations[l]!==undefined?rules[i].declarations[l].property:''))); }
														summary.duplicate_declarations.push(rules[i].declarations[l]);
														summary.stats.summary.noDuplicateDeclarations += 1;
														rules[i].declarations.splice(l, 1);
														l-=1;
														dCount-=1;
														declarationsCounts[key] -= 1;
													}

												} else { //all in selector

													if (rules[i].declarations[l].property == key 
														&& declarationsCounts[key] > 1) { //leave behind 1

														//remove previous comment above declaration to be removed
														if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
															if (rules[i].declarations[l-1] !== undefined && rules[i].declarations[l-1].type == 'comment') {

																rules[i].declarations.splice(l-1, 1);
																l-=1;
																dCount-=1;
															}
														}

														if (OPTIONS.verbose) { console.log(success('Process - Declaration - Group Duplicate Declarations : ' + (rules[i].selectors ? rules[i].selectors.join(', ') : '') + ' - ' + (rules[i].declarations[l]!==undefined?rules[i].declarations[l].property:''))); }
														summary.duplicate_declarations.push(rules[i].declarations[l]);
														summary.stats.summary.noDuplicateDeclarations += 1;
														rules[i].declarations.splice(l, 1);
														l-=1;
														dCount-=1;
														declarationsCounts[key] -= 1;
													}
												}
											}
										}
									}

					      }
					    } //end of declarations reduction

						} //end of if
					} //end of if				
				} //end of reduce root declarations by selector

				////end of declarations




				////empty nodes
				//remove empty @sign keyframes
				if (rules[i] != undefined && rules[i].keyframes !== undefined && rules[i].keyframes.length == 0) {

					//remove previous comment in root
					if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
						if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {
							if (OPTIONS.verbose) { console.log(info('Process - @keyframes - Remove comment : ' + (rules[i].keyframes ? rules[i].keyframes.join(', ') : ''))); }
							rules.splice(i-1, 1);
							i-=1;
							rCount-=1;
						}
					}
					
					if (OPTIONS.verbose) { console.log(info('Process - @keyframes - Remove Empty Rule : ' + (rules[i].keyframes ? rules[i].keyframes.join(', ') : ''))); }

					rules.splice(i, 1);
					i-=1;
					rCount-=1;
				}

				//remove empty @sign media
				if (rules[i] !== undefined && rules[i].type == 'media' 
					&& rules[i].rules.length == 0) {

					//remove previous comment in root
					if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
						if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {
							if (OPTIONS.verbose) { console.log(info('Process - @media - Remove comment : ' + (rules[i].media ? rules[i].media : ''))); }
							rules.splice(i-1, 1);
							i-=1;
							rCount-=1;
						}
					}
					if (OPTIONS.verbose) { console.log(info('Process - @media - Remove Empty Rule : ' + (rules[i].media ? rules[i].media : ''))); }
					rules.splice(i, 1);
					i-=1;
					rCount-=1;
				}

				//remove empty @sign document
				if (rules[i] !== undefined && rules[i].type == 'document' 
					&& rules[i].rules.length == 0) {

					//remove previous comment in root
					if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
						if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {
							if (OPTIONS.verbose) { console.log(info('Process - @document - Remove comment : ' + (rules[i].document ? rules[i].document : ''))); }
							rules.splice(i-1, 1);
							i-=1;
							rCount-=1;
						}
					}

					if (OPTIONS.verbose) { console.log(info('Process - @document - Remove Empty Rule : ' + (rules[i].document ? rules[i].document : ''))); }
					rules.splice(i, 1);
					i-=1;
					rCount-=1;
				}

				//remove empty @sign supports
				if (rules[i] !== undefined && rules[i].type == 'supports' 
					&& rules[i].rules.length == 0) {

					//remove previous comment in root
					if (OPTIONS.trim_removed_rules_previous_comment || OPTIONS.trim) {
						if (rules[i-1] !== undefined && rules[i-1].type == 'comment') {
							if (OPTIONS.verbose) { console.log(info('Process - @supports - Remove comment : ' + (rules[i].supports ? rules[i].supports : ''))); }
							rules.splice(i-1, 1);
							i-=1;
							rCount-=1;
						}
					}

					if (OPTIONS.verbose) { console.log(info('Process - @supports - Remove Empty Rule : ' + (rules[i].supports ? rules[i].supports : ''))); }
					rules.splice(i, 1);
					i-=1;
					rCount-=1;
				}
				////end of empty nodes



			} //end of i

		} //end of undefined
	}