/*
 * Copyright 2008 Novamente LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package relex.chunk;

import java.util.ArrayList;

import relex.ParsedSentence;
import relex.feature.FeatureForeach;
import relex.feature.FeatureNode;
import relex.feature.FeatureNodeCallback;
import relex.feature.RelationCallback;
import relex.tree.PhraseTree;

/**
 * Discover phrase chunks.
 * XXX This is so rudimentary that it might not be useful. XXX
 * XXX This might go away ...  XXX
 *
 * Copyright (C) 2008 Linas Vepstas <linas@linas.org>
 */

public class PhraseChunks
{
	static final int debug = 0;
	private ArrayList<Chunk> chunks;
	
	public PhraseChunks()
	{
		chunks = new ArrayList<Chunk>();
	}

	public void findBasicChunks(ParsedSentence parse)
	{
		PhraseTree pt = parse.getPhraseTree();
		BasicChunks pc = new BasicChunks(pt);
		pt.foreach(pc);
	}

	public void findObjectChunks(ParsedSentence parse)
	{
		ObjChunks obj = new ObjChunks();
		FeatureNode sent = parse.getLeft();
		FeatureForeach.foreach(sent, obj);
	}

	public ArrayList<Chunk> getChunks()
	{
		return chunks;
	}

	public void clear()
	{
		chunks.clear();
	}

	/* -------------------------------------------------------- */

	private void chunkPhrase(FeatureNode fn, Chunk chunk)
	{
		fn = fn.get("phr-head");
		while (fn != null)
		{
			FeatureNode wd = fn.get("phr-word");
			if (wd != null) chunk.addWord(wd);

			// Add subphrases to the word list
			FeatureNode subf = fn.get("phr-head");
			if (subf != null) 
			{
				chunkPhrase(fn, chunk);
			}
			fn = fn.get("phr-next");
		}
	}

	/* -------------------------------------------------------- */
	/* Use the phrase-tree approach to finding chunks */
	private class BasicChunks implements FeatureNodeCallback
	{
		private FeatureNode root;
		public BasicChunks (PhraseTree pt)
		{
			root = pt.getNode();
		}

		/**
		 * Called for each phrase in a parse.
		 * Add all parts of the phrase tree.
		 */
		public Boolean FNCallback(FeatureNode fn)
		{
			if (root == fn) return false;  // don't report the whole sentence 

			PhraseTree pt = new PhraseTree(fn);
			int breadth = pt.getBreadth();
			if (breadth < 2) return false; // don't report single words.

			int degree = pt.getDegree();
			if (degree <= 2) return false;  // don't report repeats!

			Chunk chunk = new Chunk();
			chunkPhrase(fn, chunk);
			chunks.add(chunk);
			return false;
		}
	}

	/* -------------------------------------------------------- */
	/**
	 * John Dillinger was a man who broke the law.
	 * _obj(break, law)
	 *  will generate th phrase "broke the law"
	 *
	 */
	private class ObjChunks implements RelationCallback
	{
		public Boolean UnaryRelationCB(FeatureNode from, String rel)
		{
			return false;
		}
		public Boolean BinaryHeadCB(FeatureNode from)
		{
			return false;
		}
		public Boolean BinaryRelationCB(String relation, FeatureNode from, FeatureNode to)
		{
			if (relation.equals("_subj")) return false;
			if (relation.equals("_prepSubj")) return false;

			FeatureNode fm = from.get("nameSource");

			if (0 < debug)
				System.out.println(relation + "(" + 
				                   from.get("name").getValue() + "," + 
				                   to.get("name").getValue() + ")");

			Chunk chunk = new Chunk();
			chunkPhrase(fm, chunk);
			chunks.add(chunk);

			return false;
		}
	}
}

@@ -675,45 +675,8 @@
 ce;%0A
-import relex.feature.FeatureForeach;%0A
 impo
@@ -705,16 +705,16 @@
 reNode;%0A
+
 import r
@@ -751,47 +751,8 @@
 ck;%0A
-import relex.feature.RelationCallback;%0A
 impo
@@ -1288,177 +1288,8 @@
 %09%7D%0A%0A
-%09public void findObjectChunks(ParsedSentence parse)%0A%09%7B%0A%09%09ObjChunks obj = new ObjChunks();%0A%09%09FeatureNode sent = parse.getLeft();%0A%09%09FeatureForeach.foreach(sent, obj);%0A%09%7D%0A%0A
 %09pub
@@ -2588,32 +2588,32 @@
 ase(fn, chunk);%0A
+
 %09%09%09chunks.add(ch
@@ -2645,931 +2645,7 @@
 %7D%0A%09%7D
-%0A%0A%09/* -------------------------------------------------------- */%0A%09/**%0A%09 * John Dillinger was a man who broke the law.%0A%09 * _obj(break, law)%0A%09 *  will generate th phrase %22broke the law%22%0A%09 *%0A%09 */%0A%09private class ObjChunks implements RelationCallback%0A%09%7B%0A%09%09public Boolean UnaryRelationCB(FeatureNode from, String rel)%0A%09%09%7B%0A%09%09%09return false;%0A%09%09%7D%0A%09%09public Boolean BinaryHeadCB(FeatureNode from)%0A%09%09%7B%0A%09%09%09return false;%0A%09%09%7D%0A%09%09public Boolean BinaryRelationCB(String relation, FeatureNode from, FeatureNode to)%0A%09%09%7B%0A%09%09%09if (relation.equals(%22_subj%22)) return false;%0A%09%09%09if (relation.equals(%22_prepSubj%22)) return false;%0A%0A%09%09%09FeatureNode fm = from.get(%22nameSource%22);%0A%0A%09%09%09if (0 %3C debug)%0A%09%09%09%09System.out.println(relation + %22(%22 + %0A%09%09%09%09                   from.get(%22name%22).getValue() + %22,%22 + %0A%09%09%09%09                   to.get(%22name%22).getValue() + %22)%22);%0A%0A%09%09%09Chunk chunk = new Chunk();%0A%09%09%09chunkPhrase(fm, chunk);%0A%09%09%09chunks.add(chunk);%0A%0A%09%09%09return false;%0A%09%09%7D%0A%09%7D
 %0A%7D%0A

trim out object crud, which we won't use.