/*
 * Copyright (C) 2007-2008  Reto Schuettel, Robin Stocker
 *
 * IFS Institute for Software, HSR Rapperswil, Switzerland
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

package ch.hsr.ifs.pystructure.typeinference.evaluators.references;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.python.pydev.parser.jython.ast.Attribute;
import org.python.pydev.parser.jython.ast.exprType;

import ch.hsr.ifs.pystructure.typeinference.contexts.ModuleContext;
import ch.hsr.ifs.pystructure.typeinference.evaluators.base.AbstractEvaluator;
import ch.hsr.ifs.pystructure.typeinference.goals.base.GoalState;
import ch.hsr.ifs.pystructure.typeinference.goals.base.IGoal;
import ch.hsr.ifs.pystructure.typeinference.goals.references.PossibleAttributeReferencesGoal;
import ch.hsr.ifs.pystructure.typeinference.goals.references.PossibleReferencesGoal;
import ch.hsr.ifs.pystructure.typeinference.goals.types.AbstractTypeGoal;
import ch.hsr.ifs.pystructure.typeinference.goals.types.ExpressionTypeGoal;
import ch.hsr.ifs.pystructure.typeinference.model.definitions.AttributeUse;
import ch.hsr.ifs.pystructure.typeinference.model.definitions.Module;
import ch.hsr.ifs.pystructure.typeinference.model.definitions.Use;
import ch.hsr.ifs.pystructure.typeinference.results.references.AttributeReference;
import ch.hsr.ifs.pystructure.typeinference.visitors.Workspace;

/**
 * Evaluator for finding uses of a name, which could be possible references to a
 * function or method.
 */
public class PossibleAttributeReferencesEvaluator extends AbstractEvaluator {

	private String name;
	private Map<IGoal, String> attributeNames;
	private Map<IGoal, exprType> attributeExpressions;
	
	private List<AttributeReference> references;

	public PossibleAttributeReferencesEvaluator(PossibleAttributeReferencesGoal goal) {
		super(goal);
		name = goal.getName();
		
		attributeNames = new HashMap<IGoal, String>();
		attributeExpressions = new HashMap<IGoal, exprType>();
		
		references = goal.references;
	}

	@Override
	public List<IGoal> init() {
		Workspace workspace = getGoal().getContext().getWorkspace();
		List<AttributeReference> possibleAttributeReferences = workspace.getPossibleAttributeReferences(name);
		if (possibleAttributeReferences != null) {
			references.addAll(possibleAttributeReferences);
		}
		return wrap(new PossibleReferencesGoal(getGoal().getContext(), name));
	}

	@Override
	public List<IGoal> subgoalDone(IGoal subgoal, GoalState subgoalState) {
		
		if (subgoal instanceof PossibleReferencesGoal) {
			PossibleReferencesGoal g = (PossibleReferencesGoal) subgoal;
			
			List<IGoal> subgoals = new LinkedList<IGoal>();

			for (Use use : g.references) {
				
				if (use instanceof AttributeUse) {
					AttributeUse attributeUse = (AttributeUse) use;
					
					ModuleContext parentContext = getGoal().getContext();
					ModuleContext context = new ModuleContext(parentContext, attributeUse.getModule());
					
					Attribute attribute = (Attribute) attributeUse.getExpression();
					IGoal goal = new ExpressionTypeGoal(context, attribute.value);
					
					attributeNames.put(goal, attributeUse.getName());
					attributeExpressions.put(goal, attribute);
					subgoals.add(goal);
				}
			}
			
			return subgoals;
			
		} else if (subgoal instanceof AbstractTypeGoal) {
			AbstractTypeGoal typeGoal = (AbstractTypeGoal) subgoal;
			String name = attributeNames.get(subgoal);
			exprType expression = attributeExpressions.get(subgoal);
			Module module = typeGoal.getContext().getModule();
			AttributeReference ref = new AttributeReference(name, typeGoal.resultType, expression, module);
			references.add(ref);
			
		} else {
			unexpectedSubgoal(subgoal);
		}
			
		return IGoal.NO_GOALS;
	}

}

@@ -1095,60 +1095,8 @@
 ute;
-%0Aimport org.python.pydev.parser.jython.ast.exprType;
 %0A%0Aim
@@ -1551,82 +1551,8 @@
 al;%0A
-import ch.hsr.ifs.pystructure.typeinference.goals.types.AbstractTypeGoal;%0A
 impo
@@ -2221,82 +2221,32 @@
 al, 
-String%3E attributeNames;%0A%09private Map%3CIGoal, exprType%3E attributeExpressions
+AttributeUse%3E useForGoal
 ;%0A%09%0A
@@ -2422,30 +2422,26 @@
 );%0A%09%09%0A%09%09
-attributeNames
+useForGoal
  = new H
@@ -2458,70 +2458,19 @@
 al, 
-String%3E();%0A%09%09attributeExpressions = new HashMap%3CIGoal, exprTyp
+AttributeUs
 e%3E()
@@ -3592,30 +3592,26 @@
 %09%09%0A%09%09%09%09%09
-attributeNames
+useForGoal
 .put(goa
@@ -3629,66 +3629,8 @@
 eUse
-.getName());%0A%09%09%09%09%09attributeExpressions.put(goal, attribute
 );%0A%09
@@ -3724,24 +3724,26 @@
 tanceof 
-Abstract
+Expression
 TypeGoal
@@ -3753,34 +3753,27 @@
 %0A%09%09%09
-AbstractTypeGoal t
+ExpressionT
 ypeGoal 
 = (A
@@ -3772,19 +3772,23 @@
 oal 
+g 
 = (
-Abstract
+Expression
 Type
@@ -3809,108 +3809,47 @@
 %0A%09%09%09
-String name = attributeNames.get(subgoal);%0A%09%09%09exprType expression = attributeExpressions.get(subgoal
+%0A%09%09%09AttributeUse use = useForGoal.get(g
 );%0A%09
@@ -3866,24 +3866,17 @@
 odule = 
-typeGoal
+g
 .getCont
@@ -3949,22 +3949,24 @@
 nce(
-name, typeGoal
+use.getName(), g
 .res
@@ -3974,17 +3974,24 @@
 ltType, 
-e
+use.getE
 xpressio
@@ -3991,16 +3991,18 @@
 pression
+()
 , module
@@ -4004,16 +4004,20 @@
 odule);%0A
+%09%09%09%0A
 %09%09%09refer

Use one map instead of two in PossibleAttributeReferencesEvaluator.