<commit_before>package org.javarosa.xform.schema;

import java.util.Enumeration;

import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.GroupDef;
import org.javarosa.core.model.IDataReference;
import org.javarosa.core.model.IFormElement;
import org.javarosa.core.model.QuestionDef;
import org.javarosa.core.model.condition.Condition;
import org.javarosa.core.model.condition.IConditionExpr;
import org.javarosa.core.model.instance.DataModelTree;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.services.locale.Localizer;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.model.xform.XPathReference;
import org.javarosa.xform.util.XFormAnswerDataSerializer;
import org.javarosa.xpath.XPathConditional;

public class FormOverview {
	public static String overview (FormDef f) {
		StringBuffer sb = new StringBuffer();
				
		println(sb, 0, "Form Name: " + f.getName());
		println(sb, 0, "Form Title: " + f.getTitle());
		println(sb);
		
		if (f.getLocalizer() != null) {
			Localizer l = f.getLocalizer();
			String[] langs = l.getAvailableLocales();
			
			println(sb, 0, "Available Languages: " + langs.length);
			for (int i = 0; i < langs.length; i++) {
				println(sb, 1, langs[i] + (langs[i].equals(l.getDefaultLocale()) ? " (default)" : ""));
			}
			
			f.getLocalizer().setToDefault();
		} else {
			println(sb, 0, "Available Languages: 1 (no multi-lingual content)");
		}
		println(sb);
		
		listQuestions(f, f, 0, sb);
		
		return sb.toString();
	}
	
	private static void listQuestions (FormDef f, IFormElement fe, int indent, StringBuffer sb) {
		if (fe instanceof QuestionDef) {
			listQuestion(f, (QuestionDef)fe, indent, sb);
		} else {
			if (fe instanceof GroupDef) {
				if (listGroup(f, (GroupDef)fe, indent, sb)) {
					indent += 1;
				}
			}
			
			for (int i = 0; i < fe.getChildren().size(); i++) {
				listQuestions(f, fe.getChild(i), indent, sb);
			}
		}
	}
	
	private static void listQuestion (FormDef f, QuestionDef q, int indent, StringBuffer sb) {
		TreeElement instanceNode = getInstanceNode(f.getDataModel(), q.getBind());
		
		String caption = q.getLongText();
		int type = instanceNode.dataType;
		
		if (q.getControlType() != Constants.CONTROL_TRIGGER) {
			println(sb, indent, "Question: \"" + caption + "\"");
			println(sb, indent + 1, "Type: " + printType(type));
		} else {
			println(sb, indent, "Info: \"" + caption + "\"");
		}
			
		if (q.getControlType() == Constants.CONTROL_SELECT_ONE || q.getControlType() == Constants.CONTROL_SELECT_MULTI) {
			printChoices(q, indent + 1, sb);
		}
		
		printProperty("relevant", f, instanceNode, indent + 1, sb);
		
		printProperty("required", f, instanceNode, indent + 1, sb);

		printProperty("readonly", f, instanceNode, indent + 1, sb);

		String defaultValue = printDefault(instanceNode);
		if (defaultValue != null) {
			println(sb, indent + 1, "Default: " + defaultValue);
		}
		
		if (instanceNode.constraint != null) {
			println(sb, indent + 1, "Constraint: " + printCondition(instanceNode.constraint.constraint));
		}
		
		println(sb);
	}
	
	private static void printChoices (QuestionDef q, int indent, StringBuffer sb) {
		println(sb, indent, "Choices: " + q.getSelectItems().size());
		for (Enumeration e = q.getSelectItems().keys(); e.hasMoreElements(); ) {
			println(sb, indent + 1, "\"" + (String)e.nextElement() + "\"");
		}
	}
	
	private static void printProperty (String property, FormDef f, TreeElement instanceNode, int indent, StringBuffer sb) {
		String line = printConditionalProperty(property, f, instanceNode);
		if (line != null) {
			println(sb, indent, line);
		}
	}
	
	private static String printConditionalProperty (String property, FormDef f, TreeElement instanceNode) {
		int action = -1;
		String conditionHeader = null;
		boolean absolute = false;
		boolean absoluteReportable = false;
		String absoluteHeader = null;
		
		if (property.equals("relevant")) {
			action = Condition.ACTION_SHOW;
			conditionHeader = "Relevant if";
			absolute = instanceNode.relevant;
			absoluteReportable = false;
			absoluteHeader = "Never relevant";
		} else if (property.equals("required")) {
			action = Condition.ACTION_REQUIRE;
			conditionHeader = "Conditionally Required";
			absolute = instanceNode.required;
			absoluteReportable = true;
			absoluteHeader = "Required";
		} else if (property.equals("readonly")) {
			action = Condition.ACTION_DISABLE;
			conditionHeader = "Conditionally Read-only";
			absolute = instanceNode.enabled;
			absoluteReportable = false;
			absoluteHeader = "Read-only";
		}
		
		IConditionExpr expr = null;
		for (int i = 0; i < f.conditions.size() && expr == null; i++) {
			Condition c = (Condition)f.conditions.elementAt(i);
			
			if (c.trueAction == action) {
				for (int j = 0; j < c.targets.size() && expr == null; j++) {
					TreeReference target = (TreeReference)c.targets.elementAt(j);
					
					if (instanceNode == getInstanceNode(f.getDataModel(), new XPathReference(target))) {
						expr = c.expr;
					}
				}
			}
		}
		
		String line = null;
		if (expr != null) {
			line = conditionHeader + ": " + printCondition(expr);
		} else if (absolute == absoluteReportable) {
			line = absoluteHeader;
		}
		
		return line;
	}
	
	private static String printDefault (TreeElement node) {
		String value = null;
		
		if (node.preloadHandler != null) {
			if (node.preloadHandler.equals("date")) {
				if (node.preloadParams.equals("today")) {
					value = "Today's Date";
				}
			} else if (node.preloadHandler.equals("property")) {
				if (node.preloadParams.equals("DeviceID")) {
					value = "Device ID";
				}
			} else if (node.preloadHandler.equals("timestamp")) {
				if (node.preloadParams.equals("start")) {
					value = "Timestamp when form opened";
				} else if (node.preloadParams.equals("end")) {
					value = "Timestamp when form completed";
				}
			} else if (node.preloadHandler.equals("context")) {
				if (node.preloadParams.equals("UserID")) {
					value = "User ID";
				} else if (node.preloadParams.equals("UserName")) {
					value = "<NAME>";
				}	
			} else if (node.preloadHandler.equals("patient")) {
				value = "Patient Record: " + node.preloadParams;
			}
			
			if (value == null) {
				value = "Preload Handler: " + node.preloadHandler;
				if (node.preloadParams != null) {
					value = value + "; params: " + node.preloadParams;
				}
			}
		} else {
			if (node.getValue() != null) {
				XFormAnswerDataSerializer xfads = new XFormAnswerDataSerializer();
				if (xfads.canSerialize(node.getValue())) {
					value = (String)xfads.serializeAnswerData(node.getValue(), node.dataType);
				} else {
					value = "unknown data";
				}
			}
		}<commit_msg>[r2553] Fixed a bunch of problems. Still reviewing conditions<commit_after>package org.javarosa.xform.schema;

import java.util.Enumeration;

import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.GroupDef;
import org.javarosa.core.model.IDataReference;
import org.javarosa.core.model.IFormElement;
import org.javarosa.core.model.QuestionDef;
import org.javarosa.core.model.condition.Condition;
import org.javarosa.core.model.condition.IConditionExpr;
import org.javarosa.core.model.instance.DataModelTree;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.services.locale.Localizer;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.model.xform.XPathReference;
import org.javarosa.xform.util.XFormAnswerDataSerializer;
import org.javarosa.xpath.XPathConditional;

public class FormOverview {
	public static String overview (FormDef f) {
		StringBuffer sb = new StringBuffer();
				
		println(sb, 0, "Form Name: " + f.getName());
		println(sb, 0, "Form Title: " + f.getTitle());
		println(sb);
		
		if (f.getLocalizer() != null) {
			Localizer l = f.getLocalizer();
			String[] langs = l.getAvailableLocales();
			
			println(sb, 0, "Available Languages: " + langs.length);
			for (int i = 0; i < langs.length; i++) {
				println(sb, 1, langs[i] + (langs[i].equals(l.getDefaultLocale()) ? " (default)" : ""));
			}
			
			f.getLocalizer().setToDefault();
		} else {
			println(sb, 0, "Available Languages: 1 (no multi-lingual content)");
		}
		println(sb);
		
		listQuestions(f, f, 0, sb);
		
		return sb.toString();
	}
	
	private static void listQuestions (FormDef f, IFormElement fe, int indent, StringBuffer sb) {
		if (fe instanceof QuestionDef) {
			listQuestion(f, (QuestionDef)fe, indent, sb);
		} else {
			if (fe instanceof GroupDef) {
				if (listGroup(f, (GroupDef)fe, indent, sb)) {
					indent += 1;
				}
			}
			
			for (int i = 0; i < fe.getChildren().size(); i++) {
				listQuestions(f, fe.getChild(i), indent, sb);
			}
		}
	}
	
	private static void listQuestion (FormDef f, QuestionDef q, int indent, StringBuffer sb) {
		TreeElement instanceNode = getInstanceNode(f.getDataModel(), q.getBind());
		
		String caption = q.getLongText();
		int type = instanceNode.dataType;
		
		if (q.getControlType() != Constants.CONTROL_TRIGGER) {
			println(sb, indent, "Question: \"" + caption + "\"");
			println(sb, indent + 1, "Type: " + printType(type));
		} else {
			println(sb, indent, "Info: \"" + caption + "\"");
		}
			
		if (q.getControlType() == Constants.CONTROL_SELECT_ONE || q.getControlType() == Constants.CONTROL_SELECT_MULTI) {
			printChoices(q, indent + 1, sb);
		}
		
		printProperty("relevant", f, instanceNode, indent + 1, sb);
		
		printProperty("required", f, instanceNode, indent + 1, sb);

		printProperty("readonly", f, instanceNode, indent + 1, sb);

		String defaultValue = printDefault(instanceNode);
		if (defaultValue != null) {
			println(sb, indent + 1, "Default: " + defaultValue);
		}
		
		if (instanceNode.getConstraint() != null) {
			println(sb, indent + 1, "Constraint: " + printCondition(instanceNode.getConstraint().constraint));
		}
		
		println(sb);
	}
	
	private static void printChoices (QuestionDef q, int indent, StringBuffer sb) {
		println(sb, indent, "Choices: " + q.getSelectItems().size());
		for (Enumeration e = q.getSelectItems().keys(); e.hasMoreElements(); ) {
			println(sb, indent + 1, "\"" + (String)e.nextElement() + "\"");
		}
	}
	
	private static void printProperty (String property, FormDef f, TreeElement instanceNode, int indent, StringBuffer sb) {
		String line = printConditionalProperty(property, f, instanceNode);
		if (line != null) {
			println(sb, indent, line);
		}
	}
	
	private static String printConditionalProperty (String property, FormDef f, TreeElement instanceNode) {
		int action = -1;
		String conditionHeader = null;
		boolean absolute = false;
		boolean absoluteReportable = false;
		String absoluteHeader = null;
		
		if (property.equals("relevant")) {
			action = Condition.ACTION_SHOW;
			conditionHeader = "Relevant if";
			absolute = instanceNode.relevant;
			absoluteReportable = false;
			absoluteHeader = "Never relevant";
		} else if (property.equals("required")) {
			action = Condition.ACTION_REQUIRE;
			conditionHeader = "Conditionally Required";
			absolute = instanceNode.required;
			absoluteReportable = true;
			absoluteHeader = "Required";
		} else if (property.equals("readonly")) {
			action = Condition.ACTION_DISABLE;
			conditionHeader = "Conditionally Read-only";
			absolute = instanceNode.isEnabled();
			absoluteReportable = false;
			absoluteHeader = "Read-only";
		}
		
		IConditionExpr expr = null;
		for (int i = 0; i < f.conditions.size() && expr == null; i++) {
			Condition c = (Condition)f.conditions.elementAt(i);
			
			if (c.trueAction == action) {
				for (int j = 0; j < c.targets.size() && expr == null; j++) {
					TreeReference target = (TreeReference)c.targets.elementAt(j);
					
					if (instanceNode == getInstanceNode(f.getDataModel(), new XPathReference(target))) {
						expr = c.expr;
					}
				}
			}
		}
		
		String line = null;
		if (expr != null) {
			line = conditionHeader + ": " + printCondition(expr);
		} else if (absolute == absoluteReportable) {
			line = absoluteHeader;
		}
		
		return line;
	}
	
	private static String printDefault (TreeElement node) {
		String value = null;
		
		if (node.getPreloadHandler() != null) {
			if (node.getPreloadHandler().equals("date")) {
				if (node.getPreloadParams().equals("today")) {
					value = "Today's Date";
				}
			} else if (node.getPreloadHandler().equals("property")) {
				if (node.getPreloadParams().equals("DeviceID")) {
					value = "Device ID";
				}
			} else if (node.getPreloadHandler().equals("timestamp")) {
				if (node.getPreloadParams().equals("start")) {
					value = "Timestamp when form opened";
				} else if (node.getPreloadParams().equals("end")) {
					value = "Timestamp when form completed";
				}
			} else if (node.getPreloadHandler().equals("context")) {
				if (node.getPreloadParams().equals("UserID")) {
					value = "User ID";
				} else if (node.getPreloadParams().equals("UserName")) {
					value = "<NAME>";
				}	
			} else if (node.getPreloadHandler().equals("patient")) {
				value = "Patient Record: " + node.getPreloadParams();
			}
			
			if (value == null) {
				value = "Preload Handler: " + node.getPreloadHandler();
				if (node.getPreloadParams() != null) {
					value = value + "; params: " + node.getPreloadParams();
				}
			}
		} else {
			if (node.getValue() != null) {
				XFormAnswerDataSerializer xfads = new XFormAnswerDataSerializer();
				if (xfads.canSerialize(node.getValue())) {
					value = (String)xfads.serializeAnswerData(node.getValue(), node.dataType);
				} else {
					value = "unknown data";
				}
			}
		}
{'fraction_non_alphanumeric': 0.1464, 'fraction_numerical': 0.0033454545454545456, 'mean_word_length': 3.774652777777778, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2897042', 'n_tokens_mistral': 5162, 'n_tokens_neox': 4341, 'n_words': 1002}