1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.interview;
  28 
  29 import java.io.File;
  30 import java.util.Map;
  31 
  32 /**
  33  * A {@link Question question} to which the response is a filename.
  34  */
  35 public abstract class FileQuestion extends Question
  36 {
  37     /**
  38      * Create a question with a nominated tag.
  39      * @param interview The interview containing this question.
  40      * @param tag A unique tag to identify this specific question.
  41      */
  42     protected FileQuestion(Interview interview, String tag) {
  43         super(interview, tag);
  44 
  45         if (interview.getInterviewSemantics() > Interview.SEMANTIC_PRE_32)
  46             clear();
  47 
  48         setDefaultValue(value);
  49     }
  50 
  51     /**
  52      * Get the suggested responses to this question, or null if none.
  53      * @return The suggestions.
  54      *
  55      * @see #setSuggestions
  56      */
  57     public File[] getSuggestions() {
  58         return suggestions;
  59     }
  60 
  61     /**
  62      * Set the set of suggested responses.
  63      * @param newSuggestions The values to be set, or null if none
  64      * @throws IllegalArgumentException if any of the values in the array
  65      * are null
  66      * @see #getSuggestions
  67      */
  68     public void setSuggestions(File[] newSuggestions) {
  69         if (newSuggestions != null) {
  70             for (File newSuggestion : newSuggestions) {
  71                 if (newSuggestion == null)
  72                     throw new IllegalArgumentException();
  73             }
  74         }
  75 
  76         suggestions = newSuggestions;
  77     }
  78 
  79     /**
  80      * Get the default response for this question.
  81      * @return the default response for this question.
  82      *
  83      * @see #setDefaultValue
  84      */
  85     public File getDefaultValue() {
  86         return defaultValue;
  87     }
  88 
  89     /**
  90      * Set the default response for this question,
  91      * used by the clear method.
  92      * @param v the default response for this question.
  93      *
  94      * @see #getDefaultValue
  95      */
  96     public void setDefaultValue(File v) {
  97         defaultValue = v;
  98     }
  99 
 100     /**
 101      * Get the current (default or latest) response to this question.
 102      * @return The current value.
 103      * @see #setValue
 104      */
 105     public File getValue() {
 106         return value;
 107     }
 108 
 109     /**
 110      * Verify this question is on the current path, and if it is,
 111      * return the current value.
 112      * @return the current value of this question
 113      * @throws Interview.NotOnPathFault if this question is not on the
 114      * current path
 115      * @see #getValue
 116      */
 117     public File getValueOnPath()
 118         throws Interview.NotOnPathFault
 119     {
 120         interview.verifyPathContains(this);
 121         return getValue();
 122     }
 123 
 124     public String getStringValue() {
 125         return (value == null ? null : value.getPath());
 126     }
 127 
 128     /**
 129      * Set the response to this question to the value represented by
 130      * a string-valued argument.
 131      * @see #getValue
 132      */
 133     public void setValue(String path) {
 134         setValue(path == null ? null : new File(path));
 135     }
 136 
 137     /**
 138      * Set the current value.
 139      * @param newValue The value to be set.
 140      * @see #getValue
 141      */
 142     public void setValue(File newValue) {
 143         File oldValue = value;
 144         value = newValue;
 145         if (!equal(value, oldValue)) {
 146             interview.updatePath(this);
 147             interview.setEdited(true);
 148         }
 149     }
 150 
 151     public boolean isValueValid() {
 152         if (value == null) {
 153             return true;
 154         }
 155         if (baseRelativeOnly && baseDir != null
 156             && !value.getPath().startsWith(baseDir.getPath())) {
 157             return false;
 158         }
 159 
 160         if (filters != null) {
 161             for (FileFilter f : filters) {
 162                 if (!f.accept(value)) {
 163                     return false;
 164                 }
 165             }
 166         }
 167         return true;
 168     }
 169 
 170     public boolean isValueAlwaysValid() {
 171         return false;
 172     }
 173 
 174     /**
 175      * Get the filters used to select valid files for a response
 176      * to this question.
 177      * @return An array of filters
 178      * @see #setFilter
 179      * @see #setFilters
 180      */
 181     public FileFilter[] getFilters() {
 182         return filters;
 183     }
 184 
 185     /**
 186      * Set a filter used to select valid files for a response
 187      * to this question.
 188      * @param filter a filter used to select valid files for a response
 189      * to this question
 190      * @see #getFilters
 191      * @see #setFilters
 192      */
 193     public void setFilter(FileFilter filter) {
 194         filters = new FileFilter[] { filter };
 195     }
 196 
 197     /**
 198      * Set the filters used to select valid files for a response
 199      * to this question.
 200      * @param filters An array of filters used to select valid files for a response
 201      * to this question
 202      * @see #getFilters
 203      * @see #setFilter
 204      */
 205     public void setFilters(FileFilter[] filters) {
 206         this.filters = filters;
 207     }
 208 
 209     /**
 210      * Get the default directory for files for a response to this question.
 211      * @return the default directory in which files should be found/placed
 212      * @see #setBaseDirectory
 213      * @see #isBaseRelativeOnly
 214      */
 215     public File getBaseDirectory() {
 216         return baseDir;
 217     }
 218 
 219     /**
 220      * Set the default directory for files for a response to this question.
 221      * @param dir the default directory in which files should be found/placed
 222      * @see #getBaseDirectory
 223      */
 224     public void setBaseDirectory(File dir) {
 225         baseDir = dir;
 226     }
 227 
 228     /**
 229      * Determine whether all valid responses to this question should be
 230      * relative to the base directory (i.e. in or under it.)  False by
 231      * default.
 232      * @return true if all valid responses to this question should be
 233      * relative to the base directory
 234      * @see #setBaseRelativeOnly
 235      */
 236     public boolean isBaseRelativeOnly() {
 237         return baseRelativeOnly;
 238     }
 239 
 240     /**
 241      * Specify whether all valid responses to this question should be
 242      * relative to the base directory (in or under it).
 243      * @param b this parameter should be true if all valid responses
 244      * to this question should be relative to the base directory
 245      * @see #setBaseRelativeOnly
 246      */
 247     public void setBaseRelativeOnly(boolean b) {
 248         baseRelativeOnly = b;
 249     }
 250 
 251     /**
 252      * Clear any response to this question, resetting the value
 253      * back to its initial state.
 254      */
 255     public void clear() {
 256         setValue(defaultValue);
 257     }
 258 
 259     /**
 260      * Load the value for this question from a dictionary, using
 261      * the tag as the key.
 262      * @param data The map from which to load the value for this question.
 263      */
 264     protected void load(Map<String, String> data) {
 265         Object o = data.get(tag);
 266         if (o instanceof File)
 267             setValue((File)o);
 268         else if (o instanceof String)
 269             setValue(new File((String)o));
 270     }
 271 
 272     /**
 273      * Save the value for this question in a dictionary, using
 274      * the tag as the key.
 275      * @param data The map in which to save the value for this question.
 276      */
 277     protected void save(Map<String, String> data) {
 278         if (value != null)
 279             data.put(tag, value.toString());
 280     }
 281 
 282 
 283     /**
 284      * Determine if two filenames are equal.
 285      * @param f1 the first filename to be compared
 286      * @param f2 the other filename to be compared
 287      * @return true if both filenames are null, or if both
 288      * identify the same filename
 289      */
 290     protected static boolean equal(File f1, File f2) {
 291         return (f1 == null ? f2 == null : f1.equals(f2));
 292     }
 293 
 294     /**
 295      * The current (default or latest) response to this question.
 296      */
 297     protected File value;
 298 
 299     /**
 300      * Suggested values for this question.
 301      */
 302     protected File[] suggestions;
 303 
 304     /**
 305      * The default response for this question.
 306      */
 307     private File defaultValue;
 308 
 309     private File baseDir;
 310 
 311     private boolean baseRelativeOnly;
 312 
 313     private FileFilter[] filters;
 314 }