<commit_before>/*
 * Copyright 2007 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
 *
 * 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 org.kuali.rice.kns.uif.layout;

import java.util.ArrayList;
import java.util.List;

import org.kuali.rice.kns.uif.UifConstants;
import org.kuali.rice.kns.uif.container.CollectionGroup;
import org.kuali.rice.kns.uif.container.Container;
import org.kuali.rice.kns.uif.container.View;
import org.kuali.rice.kns.uif.core.Component;
import org.kuali.rice.kns.uif.field.ActionField;
import org.kuali.rice.kns.uif.field.AttributeField;
import org.kuali.rice.kns.uif.field.Field;
import org.kuali.rice.kns.uif.field.GroupField;
import org.kuali.rice.kns.uif.field.LabelField;
import org.kuali.rice.kns.uif.field.MessageField;
import org.kuali.rice.kns.uif.util.ComponentFactory;
import org.kuali.rice.kns.uif.util.ComponentUtils;
import org.kuali.rice.kns.uif.widget.TableTools;

/**
 * Layout manager that works with <code>CollectionGroup</code> components and
 * renders the collection as a Table
 * 
 * <p>
 * Based on the fields defined, the <code>TableLayoutManager</code> will
 * dynamically create instances of the fields for each collection row. In
 * addition, the manager can create standard fields like the action and sequence
 * fields for each row. The manager supports options inherited from the
 * <code>GridLayoutManager</code> such as rowSpan, colSpan, and cell width
 * settings.
 * </p>
 * 
 * @author <NAME> (<EMAIL>)
 */
public class TableLayoutManager extends GridLayoutManager implements CollectionLayoutManager {
	private static final long serialVersionUID = 3622267585541524208L;

	private boolean useShortLabels;
	private boolean repeatHeader;
	private LabelField headerFieldPrototype;

	private boolean renderSequenceField;
	private String conditionalRenderSequenceField;
	private boolean generateAutoSequence;
	private Field sequenceFieldPrototype;

	private GroupField actionFieldPrototype;

	private GroupField subCollectionGroupFieldPrototype;

	// internal counter for the data columns (not including sequence, action)
	private int numberOfDataColumns;

	private List<LabelField> headerFields;
	private List<Field> dataFields;

	private TableTools tableTools;
	private boolean headerAdded = false;

	public TableLayoutManager() {
		useShortLabels = true;
		repeatHeader = false;
		renderSequenceField = true;
		generateAutoSequence = false;

		headerFields = new ArrayList<LabelField>();
		dataFields = new ArrayList<Field>();
	}
	
	/**
	 * The following actions are performed:
	 * 
	 * <ul>
	 * <li>Sets sequence field prototype if auto sequence is true</li>
	 * <li>Initializes the prototypes</li>
	 * </ul>
	 * 
	 * @see org.kuali.rice.kns.uif.layout.BoxLayoutManager#performInitialization(org.kuali.rice.kns.uif.container.View,
	 *      org.kuali.rice.kns.uif.container.Container)
	 */
	@Override
	public void performInitialization(View view, Container container) {
		super.performInitialization(view, container);
		
        if (generateAutoSequence && !(sequenceFieldPrototype instanceof MessageField)) {
            sequenceFieldPrototype = ComponentFactory.getMessageField();
        }

		view.getViewHelperService().performComponentInitialization(view, headerFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, sequenceFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, actionFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, subCollectionGroupFieldPrototype);
	}

	/**
	 * Sets up the final column count for rendering based on whether the
	 * sequence and action fields have been generated
	 * 
	 * @see org.kuali.rice.kns.uif.layout.LayoutManagerBase#performFinalize(org.kuali.rice.kns.uif.container.View,
	 *      java.lang.Object, org.kuali.rice.kns.uif.container.Container)
	 */
	@Override
	public void performFinalize(View view, Object model, Container container) {
		super.performFinalize(view, model, container);

		CollectionGroup collectionGroup = (CollectionGroup) container;

		int totalColumns = getNumberOfDataColumns();
		if (renderSequenceField) {
			totalColumns++;
		}

		if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
			totalColumns++;
		}

		setNumberOfColumns(totalColumns);

	}

	/**
	 * Assembles the field instances for the collection line. The given sequence
	 * field prototype is copied for the line sequence field. Likewise a copy of
	 * the actionFieldPrototype is made and the given actions are set as the
	 * items for the action field. Finally the generated items are assembled
	 * together into the dataFields list with the given lineFields.
	 * 
	 * @see org.kuali.rice.kns.uif.layout.CollectionLayoutManager#buildLine(org.kuali.rice.kns.uif.container.View,
	 *      java.lang.Object, org.kuali.rice.kns.uif.container.CollectionGroup,
	 *      java.util.List, java.util.List, java.lang.String, java.util.List,
	 *      java.lang.String, java.lang.Object, int)
	 */
	public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
			List<GroupField> subCollectionFields, String bindingPath, List<ActionField> actions, String idSuffix,
			Object currentLine, int lineIndex) {
		boolean isAddLine = lineIndex == -1;
		
        // if add line or first line set number of data columns
        if (isAddLine || (!collectionGroup.isRenderAddLine() && (lineIndex == 0))) {
            if (isSuppressLineWrapping()) {
                setNumberOfDataColumns(lineFields.size());
            } else {
                setNumberOfDataColumns(getNumberOfColumns());
            }
        }

		// if add line build table header first
		// TODO: implement repeat header
		if (!headerAdded) {
			headerFields = new ArrayList<LabelField>();
			dataFields = new ArrayList<Field>();

			buildTableHeaderRows(collectionGroup, lineFields);
			ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.LINE, currentLine);
			ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.INDEX, new Integer(
					lineIndex));
			headerAdded = true;
		}

		// set label field rendered to true on line fields
		for (Field field : lineFields) {
			field.setLabelFieldRendered(true);
<commit_msg>fix for 'division by 0' error due to the number of columns not getting set<commit_after>/*
 * Copyright 2007 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
 *
 * 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 org.kuali.rice.kns.uif.layout;

import java.util.ArrayList;
import java.util.List;

import org.kuali.rice.kns.uif.UifConstants;
import org.kuali.rice.kns.uif.container.CollectionGroup;
import org.kuali.rice.kns.uif.container.Container;
import org.kuali.rice.kns.uif.container.View;
import org.kuali.rice.kns.uif.core.Component;
import org.kuali.rice.kns.uif.field.ActionField;
import org.kuali.rice.kns.uif.field.AttributeField;
import org.kuali.rice.kns.uif.field.Field;
import org.kuali.rice.kns.uif.field.GroupField;
import org.kuali.rice.kns.uif.field.LabelField;
import org.kuali.rice.kns.uif.field.MessageField;
import org.kuali.rice.kns.uif.util.ComponentFactory;
import org.kuali.rice.kns.uif.util.ComponentUtils;
import org.kuali.rice.kns.uif.widget.TableTools;

/**
 * Layout manager that works with <code>CollectionGroup</code> components and
 * renders the collection as a Table
 * 
 * <p>
 * Based on the fields defined, the <code>TableLayoutManager</code> will
 * dynamically create instances of the fields for each collection row. In
 * addition, the manager can create standard fields like the action and sequence
 * fields for each row. The manager supports options inherited from the
 * <code>GridLayoutManager</code> such as rowSpan, colSpan, and cell width
 * settings.
 * </p>
 * 
 * @author <NAME> (<EMAIL>)
 */
public class TableLayoutManager extends GridLayoutManager implements CollectionLayoutManager {
	private static final long serialVersionUID = 3622267585541524208L;

	private boolean useShortLabels;
	private boolean repeatHeader;
	private LabelField headerFieldPrototype;

	private boolean renderSequenceField;
	private String conditionalRenderSequenceField;
	private boolean generateAutoSequence;
	private Field sequenceFieldPrototype;

	private GroupField actionFieldPrototype;

	private GroupField subCollectionGroupFieldPrototype;

	// internal counter for the data columns (not including sequence, action)
	private int numberOfDataColumns;

	private List<LabelField> headerFields;
	private List<Field> dataFields;

	private TableTools tableTools;
	private boolean headerAdded = false;

	public TableLayoutManager() {
		useShortLabels = true;
		repeatHeader = false;
		renderSequenceField = true;
		generateAutoSequence = false;

		headerFields = new ArrayList<LabelField>();
		dataFields = new ArrayList<Field>();
	}
	
	/**
	 * The following actions are performed:
	 * 
	 * <ul>
	 * <li>Sets sequence field prototype if auto sequence is true</li>
	 * <li>Initializes the prototypes</li>
	 * </ul>
	 * 
	 * @see org.kuali.rice.kns.uif.layout.BoxLayoutManager#performInitialization(org.kuali.rice.kns.uif.container.View,
	 *      org.kuali.rice.kns.uif.container.Container)
	 */
	@Override
	public void performInitialization(View view, Container container) {
		super.performInitialization(view, container);
		
        if (generateAutoSequence && !(sequenceFieldPrototype instanceof MessageField)) {
            sequenceFieldPrototype = ComponentFactory.getMessageField();
        }

		view.getViewHelperService().performComponentInitialization(view, headerFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, sequenceFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, actionFieldPrototype);
		view.getViewHelperService().performComponentInitialization(view, subCollectionGroupFieldPrototype);
	}

	/**
	 * Sets up the final column count for rendering based on whether the
	 * sequence and action fields have been generated
	 * 
	 * @see org.kuali.rice.kns.uif.layout.LayoutManagerBase#performFinalize(org.kuali.rice.kns.uif.container.View,
	 *      java.lang.Object, org.kuali.rice.kns.uif.container.Container)
	 */
	@Override
	public void performFinalize(View view, Object model, Container container) {
		super.performFinalize(view, model, container);

		CollectionGroup collectionGroup = (CollectionGroup) container;

		int totalColumns = getNumberOfDataColumns();
		if (renderSequenceField) {
			totalColumns++;
		}

		if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
			totalColumns++;
		}

		setNumberOfColumns(totalColumns);

	}

	/**
	 * Assembles the field instances for the collection line. The given sequence
	 * field prototype is copied for the line sequence field. Likewise a copy of
	 * the actionFieldPrototype is made and the given actions are set as the
	 * items for the action field. Finally the generated items are assembled
	 * together into the dataFields list with the given lineFields.
	 * 
	 * @see org.kuali.rice.kns.uif.layout.CollectionLayoutManager#buildLine(org.kuali.rice.kns.uif.container.View,
	 *      java.lang.Object, org.kuali.rice.kns.uif.container.CollectionGroup,
	 *      java.util.List, java.util.List, java.lang.String, java.util.List,
	 *      java.lang.String, java.lang.Object, int)
	 */
	public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
			List<GroupField> subCollectionFields, String bindingPath, List<ActionField> actions, String idSuffix,
			Object currentLine, int lineIndex) {
		boolean isAddLine = lineIndex == -1;
		
        // if add line or first line set number of data columns
        if (isAddLine || ((!collectionGroup.isRenderAddLine() || collectionGroup.isReadOnly()) && (lineIndex == 0))) {
            if (isSuppressLineWrapping()) {
                setNumberOfDataColumns(lineFields.size());
            } else {
                setNumberOfDataColumns(getNumberOfColumns());
            }
        }

		// if add line build table header first
		// TODO: implement repeat header
		if (!headerAdded) {
			headerFields = new ArrayList<LabelField>();
			dataFields = new ArrayList<Field>();

			buildTableHeaderRows(collectionGroup, lineFields);
			ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.LINE, currentLine);
			ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.INDEX, new Integer(
					lineIndex));
			headerAdded = true;
		}

		// set label field rendered to true on line fields
		for (Field field : lineFields) {
			field.setLabelFieldRendered(true);

{'fraction_non_alphanumeric': 0.09279707495429616, 'fraction_numerical': 0.00416819012797075, 'mean_word_length': 4.444267515923567, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5940653', 'n_tokens_mistral': 4065, 'n_tokens_neox': 3817, 'n_words': 1067}