<commit_before>package com.eyeq.pivot4j.analytics.ui.navigator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.component.StateHolder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.primefaces.model.TreeNode;

import com.eyeq.pivot4j.analytics.repository.ReportRepository;
import com.eyeq.pivot4j.analytics.repository.RepositoryFile;

public class RepositoryNode extends NavigatorNode<RepositoryFile> implements
		StateHolder {

	private ReportRepository repository;

	private boolean transientState = false;

	private String viewId;

	public RepositoryNode() {
		ExternalContext externalContext = FacesContext.getCurrentInstance()
				.getExternalContext();
		Map<String, Object> applicationMap = externalContext
				.getApplicationMap();

		this.repository = (ReportRepository) applicationMap
				.get("reportRepository");
	}

	/**
	 * @param file
	 * @param repository
	 */
	public RepositoryNode(RepositoryFile file, ReportRepository repository) {
		super(file);

		if (repository == null) {
			throw new NullArgumentException("repository");
		}

		this.repository = repository;

		setSelectable(true);
	}

	/**
	 * @return the repository
	 */
	public ReportRepository getRepository() {
		return repository;
	}

	/**
	 * @see org.primefaces.model.TreeNode#getType()
	 */
	@Override
	public String getType() {
		String type;

		if (getObject().isRoot()) {
			type = "root";
		} else if (getObject().isDirectory()) {
			type = "directory";
		} else {
			type = "file";
		}

		return type;
	}

	/**
	 * @see org.primefaces.model.TreeNode#isLeaf()
	 */
	@Override
	public boolean isLeaf() {
		return !getObject().isDirectory() || getChildCount() == 0;
	}

	/**
	 * @return the viewId
	 */
	public String getViewId() {
		return viewId;
	}

	/**
	 * @param viewId
	 *            the viewId to set
	 */
	public void setViewId(String viewId) {
		this.viewId = viewId;

		getData().setSelected(viewId != null);
	}

	/**
	 * @see com.eyeq.pivot4j.analytics.ui.navigator.NavigatorNode#createData(java.lang.Object)
	 */
	@Override
	protected NodeData createData(RepositoryFile object) {
		return new NodeData(object.getPath(), object.getName());
	}

	/**
	 * @see com.eyeq.pivot4j.analytics.ui.navigator.NavigatorNode#createChildren()
	 */
	@Override
	protected List<TreeNode> createChildren() {
		List<TreeNode> children;

		try {
			List<RepositoryFile> files = repository.getFiles(getObject());

			children = new ArrayList<TreeNode>(files.size());

			for (RepositoryFile file : files) {
				RepositoryNode child = new RepositoryNode(file, repository);
				child.setParent(this);

				children.add(child);
			}
		} catch (IOException e) {
			throw new FacesException(e);
		}

		return children;
	}

	/**
	 * @param file
	 */
	public RepositoryNode selectNode(RepositoryFile file) {
		RepositoryNode node = findNode(file);

		if (node != null) {
			node.setSelected(true);

			TreeNode parent = node;

			while ((parent = parent.getParent()) != null) {
				parent.setExpanded(true);
			}
		}

		return node;
	}

	/**
	 * @param file
	 */
	public RepositoryNode findNode(RepositoryFile file) {
		if (file == null) {
			throw new NullArgumentException("file");
		}

		RepositoryNode selectedNode = null;

		List<RepositoryFile> ancestors;

		try {
			ancestors = file.getAncestors();
		} catch (IOException e) {
			throw new FacesException(e);
		}

		RepositoryFile thisFile = getObject();

		if (file.equals(thisFile)) {
			selectedNode = this;
		} else if (ancestors.contains(thisFile)) {
			for (TreeNode node : getChildren()) {
				RepositoryNode fileNode = (RepositoryNode) node;

				selectedNode = fileNode.findNode(file);

				if (selectedNode != null) {
					break;
				}
			}
		}

		return selectedNode;
	}

	/**
	 * @param viewId
	 */
	public RepositoryNode findNode(String viewId) {
		if (viewId == null) {
			throw new NullArgumentException("viewId");
		}

		RepositoryNode selectedNode = null;

		if (viewId.equals(this.viewId)) {
			selectedNode = this;
		} else if (isLoaded()) {
			for (TreeNode node : getChildren()) {
				RepositoryNode fileNode = (RepositoryNode) node;

				selectedNode = fileNode.findNode(viewId);

				if (selectedNode != null) {
					break;
				}
			}
		}

		return selectedNode;
	}

	/**
	 * @see javax.faces.component.StateHolder#isTransient()
	 */
	@Override
	public boolean isTransient() {
		return transientState;
	}

	/**
	 * @see javax.faces.component.StateHolder#setTransient(boolean)
	 */
	@Override
	public void setTransient(boolean newTransientValue) {
		this.transientState = newTransientValue;
	}

	/**
	 * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
	 */
	@Override
	public Object saveState(FacesContext context) {
		return new Object[] { isSelectable(), isSelected(), isExpanded(),
				viewId, getObject().getPath() };
	}

	/**
	 * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext,
	 *      java.lang.Object)
	 */
	@Override
	public void restoreState(FacesContext context, Object state) {
		Object[] states = (Object[]) state;

		setSelectable((Boolean) states[0]);
		setSelected((Boolean) states[1]);
		setExpanded((Boolean) states[2]);
		setViewId((String) states[3]);

		try {
			setObject(repository.getFile((String) states[4]));
		} catch (IOException e) {
			throw new FacesException(e);
		}
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */<commit_msg>Fix a NPE on tree node state restoring process.<commit_after>package com.eyeq.pivot4j.analytics.ui.navigator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.component.StateHolder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.primefaces.model.TreeNode;

import com.eyeq.pivot4j.analytics.repository.ReportRepository;
import com.eyeq.pivot4j.analytics.repository.RepositoryFile;

public class RepositoryNode extends NavigatorNode<RepositoryFile> implements
		StateHolder {

	private ReportRepository repository;

	private boolean transientState = false;

	private String viewId;

	public RepositoryNode() {
		ExternalContext externalContext = FacesContext.getCurrentInstance()
				.getExternalContext();
		Map<String, Object> applicationMap = externalContext
				.getApplicationMap();

		this.repository = (ReportRepository) applicationMap
				.get("reportRepository");
	}

	/**
	 * @param file
	 * @param repository
	 */
	public RepositoryNode(RepositoryFile file, ReportRepository repository) {
		super(file);

		if (repository == null) {
			throw new NullArgumentException("repository");
		}

		this.repository = repository;

		setSelectable(true);
	}

	/**
	 * @return the repository
	 */
	public ReportRepository getRepository() {
		return repository;
	}

	/**
	 * @see org.primefaces.model.TreeNode#getType()
	 */
	@Override
	public String getType() {
		String type;

		if (getObject().isRoot()) {
			type = "root";
		} else if (getObject().isDirectory()) {
			type = "directory";
		} else {
			type = "file";
		}

		return type;
	}

	/**
	 * @see org.primefaces.model.TreeNode#isLeaf()
	 */
	@Override
	public boolean isLeaf() {
		return !getObject().isDirectory() || getChildCount() == 0;
	}

	/**
	 * @return the viewId
	 */
	public String getViewId() {
		return viewId;
	}

	/**
	 * @param viewId
	 *            the viewId to set
	 */
	public void setViewId(String viewId) {
		this.viewId = viewId;

		getData().setSelected(viewId != null);
	}

	/**
	 * @see com.eyeq.pivot4j.analytics.ui.navigator.NavigatorNode#createData(java.lang.Object)
	 */
	@Override
	protected NodeData createData(RepositoryFile object) {
		return new NodeData(object.getPath(), object.getName());
	}

	/**
	 * @see com.eyeq.pivot4j.analytics.ui.navigator.NavigatorNode#createChildren()
	 */
	@Override
	protected List<TreeNode> createChildren() {
		List<TreeNode> children;

		try {
			List<RepositoryFile> files = repository.getFiles(getObject());

			children = new ArrayList<TreeNode>(files.size());

			for (RepositoryFile file : files) {
				RepositoryNode child = new RepositoryNode(file, repository);
				child.setParent(this);

				children.add(child);
			}
		} catch (IOException e) {
			throw new FacesException(e);
		}

		return children;
	}

	/**
	 * @param file
	 */
	public RepositoryNode selectNode(RepositoryFile file) {
		RepositoryNode node = findNode(file);

		if (node != null) {
			node.setSelected(true);

			TreeNode parent = node;

			while ((parent = parent.getParent()) != null) {
				parent.setExpanded(true);
			}
		}

		return node;
	}

	/**
	 * @param file
	 */
	public RepositoryNode findNode(RepositoryFile file) {
		if (file == null) {
			throw new NullArgumentException("file");
		}

		RepositoryNode selectedNode = null;

		List<RepositoryFile> ancestors;

		try {
			ancestors = file.getAncestors();
		} catch (IOException e) {
			throw new FacesException(e);
		}

		RepositoryFile thisFile = getObject();

		if (file.equals(thisFile)) {
			selectedNode = this;
		} else if (ancestors.contains(thisFile)) {
			for (TreeNode node : getChildren()) {
				RepositoryNode fileNode = (RepositoryNode) node;

				selectedNode = fileNode.findNode(file);

				if (selectedNode != null) {
					break;
				}
			}
		}

		return selectedNode;
	}

	/**
	 * @param viewId
	 */
	public RepositoryNode findNode(String viewId) {
		if (viewId == null) {
			throw new NullArgumentException("viewId");
		}

		RepositoryNode selectedNode = null;

		if (viewId.equals(this.viewId)) {
			selectedNode = this;
		} else if (isLoaded()) {
			for (TreeNode node : getChildren()) {
				RepositoryNode fileNode = (RepositoryNode) node;

				selectedNode = fileNode.findNode(viewId);

				if (selectedNode != null) {
					break;
				}
			}
		}

		return selectedNode;
	}

	/**
	 * @see javax.faces.component.StateHolder#isTransient()
	 */
	@Override
	public boolean isTransient() {
		return transientState;
	}

	/**
	 * @see javax.faces.component.StateHolder#setTransient(boolean)
	 */
	@Override
	public void setTransient(boolean newTransientValue) {
		this.transientState = newTransientValue;
	}

	/**
	 * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
	 */
	@Override
	public Object saveState(FacesContext context) {
		return new Object[] { isSelectable(), isSelected(), isExpanded(),
				viewId, getObject().getPath() };
	}

	/**
	 * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext,
	 *      java.lang.Object)
	 */
	@Override
	public void restoreState(FacesContext context, Object state) {
		Object[] states = (Object[]) state;

		try {
			setObject(repository.getFile((String) states[4]));
		} catch (IOException e) {
			throw new FacesException(e);
		}

		setSelectable((Boolean) states[0]);
		setSelected((Boolean) states[1]);
		setExpanded((Boolean) states[2]);
		setViewId((String) states[3]);
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
{'fraction_non_alphanumeric': 0.12971698113207547, 'fraction_numerical': 0.0019217330538085255, 'mean_word_length': 3.905312767780634, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, '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': '5940671', 'n_tokens_mistral': 4041, 'n_tokens_neox': 3531, 'n_words': 740}