	protected void prepare(Environment env)
	{
		throwsDefinitions.add(env.analysisException);
		IClassDefinition c = classDefinition;
		StringBuilder sb = new StringBuilder();
		sb.append("\t/**\n");
		sb.append("\t* Called by the {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName()
				+ "} node from {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName() + "#apply("
				+ env.getTaggedDef(env.TAG_IAnalysis).getName().getName()
				+ ")}.\n");
		sb.append("\t* @param node the calling {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName()
				+ "} node\n");
		sb.append("\t*/");
		this.javaDoc = sb.toString();
		String thisNodeMethodName = NameUtil.getClassName(AnalysisUtil.getCaseClass(env, c).getName().getName());
		this.name = "case" + thisNodeMethodName;
		this.setupArguments(env);
		this.requiredImports.add("java.util.ArrayList");
		this.requiredImports.add("java.util.List");
		this.requiredImports.add(env.analysisException.getName().getCanonicalName());
		StringBuffer bodySb = new StringBuffer();
		if (!(c instanceof ExternalJavaClassDefinition && ((ExternalJavaClassDefinition) c).extendsNode))
		{
			bodySb.append("\t\t_visitedNodes.add(node);\n");
		}
		if (addReturnToBody)
		{
			bodySb.append("\t\tA retVal = createNewReturnValue("
					+ getAdditionalBodyCallArguments() + ");\n");
		}
		bodySb.append("\t\t"
				+ wrapForMerge("in" + thisNodeMethodName + "("
						+ getAdditionalBodyCallArguments()) + ");\n\n");
		List<Field> allFields = new Vector<Field>();
		allFields.addAll(c.getInheritedFields());
		allFields.addAll(c.getFields());
		for (Field f : allFields)
		{
			boolean externalNode = false;
			if (f.isTokenField)
			{
				if (f.isTypeExternalNode())
				{
					externalNode = true;
				} else
				{
					continue;
				}
			}
			Method getMethod = new GetMethod(c, f);
			getMethod.getJavaSourceCode(env);
			String getMethodName = getMethod.name;
			String getter = "node." + getMethodName + "()";
			requiredImports.addAll(getMethod.getRequiredImports(env));
			if (!f.isList)
			{
				bodySb.append("\t\tif("
						+ getter
						+ " != null "
						+ (!externalNode ? "&& !_" + visitedNodesField.name
								+ ".contains(" + getter + ")" : "") + ") \n");
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\t"
						+ wrapForMerge(getter + ".apply(" + getCallArguments())
						+ ");\n");
				bodySb.append("\t\t}\n");
			} else if (f.isList && !f.isDoubleList)
			{
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\tList<" + f.getInnerTypeForList(env)
						+ "> copy = new ArrayList<"
						+ f.getInnerTypeForList(env) + ">(" + getter + ");\n");
				bodySb.append("\t\t\tfor( " + f.getInnerTypeForList(env)
						+ " e : copy) \n");
				bodySb.append("\t\t\t{\n");
				if (!externalNode)
				{
					bodySb.append("\t\t\t\tif(!_" + visitedNodesField.name
							+ ".contains(e))\n");
					bodySb.append("\t\t\t\t{\n");
					bodySb.append("\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
					bodySb.append("\t\t\t\t}\n");
				} else
				{
					bodySb.append("\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
				}
				bodySb.append("\t\t\t}\n");
				bodySb.append("\t\t}\n");
			} else if (f.isDoubleList)
			{
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\tList<List<" + f.getInnerTypeForList(env)
						+ ">> copy = new ArrayList<List<"
						+ f.getInnerTypeForList(env) + ">>(" + getter + ");\n");
				bodySb.append("\t\t\tfor( List<" + f.getInnerTypeForList(env)
						+ "> list : copy) {\n");
				bodySb.append("\t\t\t\tfor( " + f.getInnerTypeForList(env)
						+ " e : list) \n");
				bodySb.append("\t\t\t{\n");
				if (!externalNode)
				{
					bodySb.append("\t\t\t\t\tif(!_" + visitedNodesField.name
							+ ".contains(e))\n");
					bodySb.append("\t\t\t\t\t{\n");
					bodySb.append("\t\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
					bodySb.append("\t\t\t\t\t}\n");
				} else
				{
					bodySb.append("\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
				}
				bodySb.append("\t\t\t\t}\n");
				bodySb.append("\t\t\t}\n");
				bodySb.append("\t\t}\n");
			}
		}
		bodySb.append("\n\t\t"
				+ wrapForMerge("out" + thisNodeMethodName + "("
						+ getAdditionalBodyCallArguments()) + ");\n");
		if (addReturnToBody)
		{
			bodySb.append("\t\treturn retVal;");
		}
		this.body = bodySb.toString();
	}

	protected void prepare(Environment env)
	{
		throwsDefinitions.add(env.analysisException);
		IClassDefinition c = classDefinition;
		StringBuilder sb = new StringBuilder();
		sb.append("\t/**\n");
		sb.append("\t* Called by the {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName()
				+ "} node from {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName() + "#apply("
				+ env.getTaggedDef(env.TAG_IAnalysis).getName().getName()
				+ ")}.\n");
		sb.append("\t* @param node the calling {@link "
				+ AnalysisUtil.getClass(env, c).getName().getName()
				+ "} node\n");
		sb.append("\t*/");
		this.javaDoc = sb.toString();
		String thisNodeMethodName = NameUtil.getClassName(AnalysisUtil.getCaseClass(env, c).getName().getName());
		this.name = "case" + thisNodeMethodName;
		this.setupArguments(env);
		this.requiredImports.add("java.util.ArrayList");
		this.requiredImports.add("java.util.List");
		this.requiredImports.add(env.analysisException.getName().getCanonicalName());
		StringBuffer bodySb = new StringBuffer();
		if (!(c instanceof ExternalJavaClassDefinition) ||(c instanceof ExternalJavaClassDefinition && ((ExternalJavaClassDefinition) c).extendsNode))
		{
			bodySb.append("\t\t_visitedNodes.add(node);\n");
		}
		if (addReturnToBody)
		{
			bodySb.append("\t\tA retVal = createNewReturnValue("
					+ getAdditionalBodyCallArguments() + ");\n");
		}
		bodySb.append("\t\t"
				+ wrapForMerge("in" + thisNodeMethodName + "("
						+ getAdditionalBodyCallArguments()) + ");\n\n");
		List<Field> allFields = new Vector<Field>();
		allFields.addAll(c.getInheritedFields());
		allFields.addAll(c.getFields());
		for (Field f : allFields)
		{
			boolean externalNode = false;
			if (f.isTokenField)
			{
				if (f.isTypeExternalNode())
				{
					externalNode = true;
				} else
				{
					continue;
				}
			}
			Method getMethod = new GetMethod(c, f);
			getMethod.getJavaSourceCode(env);
			String getMethodName = getMethod.name;
			String getter = "node." + getMethodName + "()";
			requiredImports.addAll(getMethod.getRequiredImports(env));
			if (!f.isList)
			{
				bodySb.append("\t\tif("
						+ getter
						+ " != null "
						+ (!externalNode ? "&& !_" + visitedNodesField.name
								+ ".contains(" + getter + ")" : "") + ") \n");
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\t"
						+ wrapForMerge(getter + ".apply(" + getCallArguments())
						+ ");\n");
				bodySb.append("\t\t}\n");
			} else if (f.isList && !f.isDoubleList)
			{
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\tList<" + f.getInnerTypeForList(env)
						+ "> copy = new ArrayList<"
						+ f.getInnerTypeForList(env) + ">(" + getter + ");\n");
				bodySb.append("\t\t\tfor( " + f.getInnerTypeForList(env)
						+ " e : copy) \n");
				bodySb.append("\t\t\t{\n");
				if (!externalNode)
				{
					bodySb.append("\t\t\t\tif(!_" + visitedNodesField.name
							+ ".contains(e))\n");
					bodySb.append("\t\t\t\t{\n");
					bodySb.append("\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
					bodySb.append("\t\t\t\t}\n");
				} else
				{
					bodySb.append("\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
				}
				bodySb.append("\t\t\t}\n");
				bodySb.append("\t\t}\n");
			} else if (f.isDoubleList)
			{
				bodySb.append("\t\t{\n");
				bodySb.append("\t\t\tList<List<" + f.getInnerTypeForList(env)
						+ ">> copy = new ArrayList<List<"
						+ f.getInnerTypeForList(env) + ">>(" + getter + ");\n");
				bodySb.append("\t\t\tfor( List<" + f.getInnerTypeForList(env)
						+ "> list : copy) {\n");
				bodySb.append("\t\t\t\tfor( " + f.getInnerTypeForList(env)
						+ " e : list) \n");
				bodySb.append("\t\t\t{\n");
				if (!externalNode)
				{
					bodySb.append("\t\t\t\t\tif(!_" + visitedNodesField.name
							+ ".contains(e))\n");
					bodySb.append("\t\t\t\t\t{\n");
					bodySb.append("\t\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
					bodySb.append("\t\t\t\t\t}\n");
				} else
				{
					bodySb.append("\t\t\t\t\t"
							+ wrapForMerge("e.apply(" + getCallArguments())
							+ ");\n");
				}
				bodySb.append("\t\t\t\t}\n");
				bodySb.append("\t\t\t}\n");
				bodySb.append("\t\t}\n");
			}
		}
		bodySb.append("\n\t\t"
				+ wrapForMerge("out" + thisNodeMethodName + "("
						+ getAdditionalBodyCallArguments()) + ");\n");
		if (addReturnToBody)
		{
			bodySb.append("\t\treturn retVal;");
		}
		this.body = bodySb.toString();
	}
