/*
 * Copyright (C) 2007 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 *
 * This file is part of Spejd.
 *
 * Spejd is free software: it may be distributed and/or modified under 
 * the terms of the GNU General Public License version 3 as published 
 * by the Free Software Foundation and appearing in the file doc/gpl.txt
 * included in the packaging of this file.
 *
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */ 
 
 
package ipipan.spejd.actions;

import ipipan.spejd.entities.Entity;
import ipipan.spejd.rules.Match;
import ipipan.spejd.util.Config;
import ipipan.spejd.util.Util;
import java.util.Set;
import java.util.regex.Pattern;

public class AgreeAction extends Action {
    int[] segs;
    int[] attr;
    boolean unify;

    AgreeAction(boolean unify, int attr[], int[] segs, Config conf) {
        super(conf);
        this.unify = unify;
        this.attr  = attr;
        this.segs  = segs;
    }

    public int[] required() {
	return segs;
    }

    /**
     * This is an exact copy of Entity's method - to get rid of "static"
     * Get common values of specified attributes of specified entities.
     */
    public Set<String> getCommonValues(Entity[] match, int[] attrIds) {
    	Set<String> values;
	values = match[0].getAttrValues(attrIds, conf.nullAgreement);
	for(int i = 1; i < match.length; i++)
	    values.retainAll(match[i].getAttrValues(attrIds,
						    conf.nullAgreement));
	return values;
    }

    /**
     * This is an exact copy of Entity's method - to get rid of "static"
     * Unify specified entities with respect to specified attributes.
     */
    public boolean unify(Entity[] match, int[] attrIds) {
    	Set values = getCommonValues(match, attrIds);
        if(values.size() == 0)
            return false;
        Util ut = new Util(conf);
        Pattern pattern = Pattern.compile(ut.join("[^<>]+|",values)+"[^<>]+");
        for(int i = 0; i < match.length; i++)
            match[i].delete(pattern, true);
        return true;
    }


    public boolean apply(Match matcher) {
	Entity[] match = matcher.get(segs);

	if(match.length == 0) return true;

	return unify ? unify(match, attr) :
	    (getCommonValues(match, attr).size() > 0);
    }

    public String toString() {
	return (unify ? "unify" : "agree") + 
	    " segs: " + intArgs(segs) + 
	    "attr: "  + intArgs(attr);
    }
}
