/* * file: TaskModel.java * author: Scott Melville * Jon Iles * copyright: (c) Packwood Software 2002-2003 * date: 15/08/2002 */ /* * 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., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package net.sf.mpxj.mpx; import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import net.sf.mpxj.MPXJException; import net.sf.mpxj.ProjectFile; import net.sf.mpxj.Task; /** * This class represents the task table definition record in an MPX file. * This record defines which fields are present in a task record. * This record has two forms, one textual and one numeric. Both * variants are handled by this class. */ final class TaskModel { /** * Default constructor. * * @param file the parent file to which this record belongs. * @param locale target locale */ TaskModel(ProjectFile file, Locale locale) { m_parentFile = file; setLocale(locale); } /** * This method is used to update the locale specific data used by this class. * * @param locale target locale */ void setLocale(Locale locale) { m_taskNames = LocaleData.getStringArray(locale, LocaleData.TASK_NAMES); String name; m_taskNumbers.clear(); for (int loop = 0; loop < m_taskNames.length; loop++) { name = m_taskNames[loop]; if (name != null) { m_taskNumbers.put(name, Integer.valueOf(loop)); } } } /** * This method is used to retrieve a linked list of field identifiers * indicating the fields present in a task record. * * @return list of field names */ public int[] getModel() { m_fields[m_count] = -1; return (m_fields); } /** * This method populates the task model from data read from an MPX file. * * @param record data read from an MPX file * @param isText flag indicating whether the textual or numeric data is being supplied */ public void update(Record record, boolean isText) throws MPXJException { int length = record.getLength(); for (int i = 0; i < length; i++) { if (isText == true) { add(getTaskCode(record.getString(i))); } else { add(record.getInteger(i).intValue()); } } } /** * This method is called from the task class each time an attribute * is added, ensuring that all of the attributes present in each task * record are present in the resource model. * * @param field field identifier */ private void add(int field) { if (field < m_flags.length) { if (m_flags[field] == false) { m_flags[field] = true; m_fields[m_count] = field; ++m_count; } } } /** * This method is called to populate the arrays which are then * used to generate the text version of the model. */ private void populateModel() { if (m_count != 0) { m_count = 0; Arrays.fill(m_flags, false); } for (Task task : m_parentFile.getAllTasks()) { for (int loop = 0; loop < MPXTaskField.MAX_FIELDS; loop++) { if (task.getCachedValue(MPXTaskField.getMpxjField(loop)) != null) { if (m_flags[loop] == false) { m_flags[loop] = true; m_fields[m_count] = loop; ++m_count; } } } } // // Ensure the the model fields always appear in the same order // Arrays.sort(m_fields); System.arraycopy(m_fields, m_fields.length - m_count, m_fields, 0, m_count); } /** * This method generates a string in MPX format representing the * contents of this record. Both the textual and numeric record * types are written by this method. * * @return string containing the data for this record in MPX format. */ @Override public String toString() { populateModel(); int number; char delimiter = m_parentFile.getProjectProperties().getMpxDelimiter(); StringBuilder textual = new StringBuilder(); StringBuilder numeric = new StringBuilder(); textual.append(MPXConstants.TASK_MODEL_TEXT_RECORD_NUMBER); numeric.append(MPXConstants.TASK_MODEL_NUMERIC_RECORD_NUMBER); for (int loop = 0; loop < m_count; loop++) { number = m_fields[loop]; textual.append(delimiter); numeric.append(delimiter); textual.append(getTaskField(number)); numeric.append(number); } textual.append(MPXConstants.EOL); numeric.append(MPXConstants.EOL); textual.append(numeric.toString()); return (textual.toString()); } /** * Returns Task field name of supplied code no. * * @param key - the code no of required Task field * @return - field name */ private String getTaskField(int key) { String result = null; if ((key > 0) && (key < m_taskNames.length)) { result = m_taskNames[key]; } return (result); } /** * Returns code number of Task field supplied. * * @param field - name * @return - code no */ private int getTaskCode(String field) throws MPXJException { Integer result = m_taskNumbers.get(field.trim()); if (result == null) { throw new MPXJException(MPXJException.INVALID_TASK_FIELD_NAME + " " + field); } return (result.intValue()); } private ProjectFile m_parentFile; /** * Array of flags indicating whether each field has already been * added to the model. */ private boolean[] m_flags = new boolean[MPXTaskField.MAX_FIELDS]; /** * Array of field numbers in order of their appearance. */ private int[] m_fields = new int[MPXTaskField.MAX_FIELDS + 1]; /** * Count of the number of fields present. */ private int m_count; /** * Array of task column names, indexed by ID. */ private String[] m_taskNames; /** * Map used to store task field numbers. */ private HashMap<String, Integer> m_taskNumbers = new HashMap<String, Integer>(); }