0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.cnd.makewizard;
0043:
0044: import java.awt.GridBagConstraints;
0045: import java.awt.GridBagLayout;
0046: import java.awt.GridLayout;
0047: import java.awt.Insets;
0048: import java.awt.event.ActionEvent;
0049: import java.awt.event.ActionListener;
0050: import java.io.File;
0051: import java.text.MessageFormat;
0052: import java.util.HashSet;
0053: import java.util.Iterator;
0054: import java.util.LinkedList;
0055: import java.util.ListIterator;
0056: import java.util.StringTokenizer;
0057: import java.util.regex.PatternSyntaxException;
0058: import javax.swing.DefaultListModel;
0059: import javax.swing.JButton;
0060: import javax.swing.JComponent;
0061: import javax.swing.JDialog;
0062: import javax.swing.JFileChooser;
0063: import javax.swing.JLabel;
0064: import javax.swing.JList;
0065: import javax.swing.JPanel;
0066: import javax.swing.JScrollPane;
0067: import javax.swing.JTextField;
0068: import javax.swing.event.DocumentEvent;
0069: import javax.swing.event.DocumentListener;
0070: import javax.swing.event.ListDataEvent;
0071: import javax.swing.event.ListDataListener;
0072: import javax.swing.event.ListSelectionEvent;
0073: import javax.swing.event.ListSelectionListener;
0074: import org.netbeans.modules.cnd.api.utils.IpeFileSystemView;
0075: import org.netbeans.modules.cnd.api.utils.IpeUtils;
0076: import org.netbeans.modules.cnd.api.utils.UnixRE;
0077: import org.openide.DialogDisplayer;
0078: import org.openide.NotifyDescriptor;
0079:
0080: /**
0081: * Create the Sources panel in the Makefile wizard.
0082: */
0083:
0084: public abstract class EnterItemsPanel extends MakefileWizardPanel {
0085:
0086: /** Serial version number */
0087: static final long serialVersionUID = 5260017369797781413L;
0088:
0089: // the fields in the sources panel...
0090: private JLabel entryLabel;
0091: private JTextField entryText;
0092: private JButton entryChooser;
0093:
0094: private JButton addBtn;
0095: private JButton changeBtn;
0096: private JButton removeBtn;
0097: private JButton upArrow;
0098: private JButton downArrow;
0099: private JList list;
0100:
0101: /** Store the file (possibly customized) file chooser */
0102: protected JFileChooser fc;
0103:
0104: /** Expand a directory to a list of files if set */
0105: private boolean expandDirs;
0106:
0107: /** Use Directory Chooser rather than File Chooser */
0108: private boolean dirChooser;
0109:
0110: /** Use MspFileFilter as file filter */
0111: private boolean mspFilter;
0112:
0113: /** Change the default button per change criteria */
0114: private boolean dynamicNext;
0115:
0116: /** Change the Last button if this is set */
0117: private boolean dynamicLast;
0118:
0119: /** Don't allow the Next or Last buttons to be enabled unless we have list items */
0120: private boolean itemsRequired;
0121:
0122: /** Add to beginning of list */
0123: private boolean addBeginning;
0124:
0125: /** Used to store source filters */
0126: private HashSet filters;
0127:
0128: /** Last chooser directory the user visited */
0129: private File lastChooserDir;
0130:
0131: /**
0132: * Show a dialog asking if a directory should be replaced with either its
0133: * leaf files or its leaf files and all of its descendant directories leaf
0134: * files
0135: */
0136: protected final static int EXPAND_DIRS = 0x1;
0137:
0138: /** Use a directory chooser rather than a regular file chooser */
0139: protected final static int DIR_CHOOSER = 0x2;
0140:
0141: /** Use the MspFileFilter class as the chooser's file filter */
0142: protected final static int MSP_FILTER = 0x4;
0143:
0144: /** Dynamically set the default button */
0145: protected final static int DYNAMIC_DEFAULT_BUTTONS = 0x8;
0146:
0147: /** Dynamically set the Last button */
0148: protected final static int DYNAMIC_LAST_BUTTON = 0x10;
0149:
0150: /** We require list items to go to the next (or last) panel */
0151: protected final static int ITEMS_REQUIRED = 0x20;
0152:
0153: /** Add to beginning of list */
0154: protected final static int ADD_BEGINNING = 0x40;
0155:
0156: /** The nextButton is set if we are dynamically setting the default */
0157: private JButton nextButton;
0158:
0159: /** Remember if Last is enabled */
0160: private static boolean lastEnabled;
0161:
0162: /**
0163: * Constructor for the Makefile sources panel. Remember, most of the panel
0164: * is inherited from WizardDescriptor.
0165: */
0166:
0167: public EnterItemsPanel(MakefileWizard wd) {
0168: super (wd);
0169:
0170: nextButton = null;
0171: lastChooserDir = null;
0172: lastEnabled = false;
0173: }
0174:
0175: /**
0176: * Create the panel. Since this class is used as a superclass for several
0177: * panels information is passed in to allow some customization at creation
0178: * time.
0179: *
0180: * @param label The label for the text field at the top of the panel
0181: * @param flags Set some optional flags to override default behavior
0182: */
0183: protected void create(String label, char mnemonic, int flags) {
0184: int gridy = 0;
0185:
0186: expandDirs = (flags & EXPAND_DIRS) == EXPAND_DIRS;
0187: dirChooser = (flags & DIR_CHOOSER) == DIR_CHOOSER;
0188: mspFilter = (flags & MSP_FILTER) == MSP_FILTER;
0189: dynamicNext = (flags & DYNAMIC_DEFAULT_BUTTONS) == DYNAMIC_DEFAULT_BUTTONS;
0190: dynamicLast = (flags & DYNAMIC_LAST_BUTTON) == DYNAMIC_LAST_BUTTON;
0191: itemsRequired = (flags & ITEMS_REQUIRED) == ITEMS_REQUIRED;
0192: addBeginning = (flags & ADD_BEGINNING) == ADD_BEGINNING;
0193:
0194: JPanel mainPanel = new JPanel();
0195: java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
0196:
0197: if (dynamicNext) {
0198: nextButton = MakefileWizard.getMakefileWizard()
0199: .getNextButton();
0200: }
0201:
0202: setLayout(new java.awt.GridBagLayout());
0203:
0204: mainPanel.setLayout(new java.awt.GridBagLayout());
0205:
0206: gridBagConstraints = new java.awt.GridBagConstraints();
0207: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0208: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
0209: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0210: mainPanel.add(createTextPanel(label, mnemonic),
0211: gridBagConstraints);
0212:
0213: gridBagConstraints = new java.awt.GridBagConstraints();
0214: gridBagConstraints.gridx = 0;
0215: gridBagConstraints.gridy = 1;
0216: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0217: gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
0218: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0219: mainPanel.add(createButtonRow1(), gridBagConstraints);
0220:
0221: // Create the scrolling list of sources and related buttons...
0222: JLabel listLabel = new JLabel(getListLabel());
0223: listLabel.setDisplayedMnemonic(getListMnemonic());
0224: gridBagConstraints = new java.awt.GridBagConstraints();
0225: gridBagConstraints.gridx = 0;
0226: gridBagConstraints.gridy = 2;
0227: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0228: gridBagConstraints.insets = new java.awt.Insets(11, 0, 0, 0);
0229: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0230: mainPanel.add(listLabel, gridBagConstraints);
0231:
0232: list = new JList(new DefaultListModel());
0233: listLabel.setLabelFor(list);
0234: JScrollPane sp = new JScrollPane(list);
0235: gridBagConstraints = new java.awt.GridBagConstraints();
0236: gridBagConstraints.gridx = 0;
0237: gridBagConstraints.gridy = 3;
0238: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0239: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
0240: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0241: gridBagConstraints.weightx = 1.0;
0242: gridBagConstraints.weighty = 1.0;
0243: mainPanel.add(sp, gridBagConstraints);
0244:
0245: gridBagConstraints = new java.awt.GridBagConstraints();
0246: gridBagConstraints.gridx = 0;
0247: gridBagConstraints.gridy = 4;
0248: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0249: gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
0250: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0251: mainPanel.add(createButtonRow2(), gridBagConstraints);
0252:
0253: gridBagConstraints = new java.awt.GridBagConstraints();
0254: gridBagConstraints.gridx = 0;
0255: gridBagConstraints.gridy = 0;
0256: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
0257: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0258: gridBagConstraints.weightx = 1.0;
0259: gridBagConstraints.weighty = 1.0;
0260: add(mainPanel, gridBagConstraints);
0261:
0262: /*
0263: setLayout(new GridBagLayout());
0264: GridBagConstraints grid = new GridBagConstraints();
0265: grid.anchor = GridBagConstraints.NORTHWEST;
0266: grid.gridx = 0;
0267:
0268: if (dynamicNext) {
0269: nextButton = MakefileWizard.getMakefileWizard().getNextButton();
0270: }
0271:
0272: JPanel textPanel = createTextPanel(label, mnemonic);
0273: grid.gridy = gridy++;
0274: grid.fill = GridBagConstraints.HORIZONTAL;
0275: grid.gridwidth = GridBagConstraints.REMAINDER;
0276: grid.weightx = 1.0;
0277: add(textPanel, grid);
0278:
0279: JPanel row1 = createButtonRow1();
0280: grid.gridy = gridy++;
0281: grid.fill = GridBagConstraints.NONE;
0282: grid.insets.top = 5;
0283: grid.weightx = 0.0;
0284: add(row1, grid);
0285:
0286: // Create the scrolling list of sources and related buttons...
0287: JLabel listLabel = new JLabel(getListLabel());
0288: listLabel.setDisplayedMnemonic(getListMnemonic());
0289: grid.gridy = gridy++;
0290: grid.insets.top = 11;
0291: add(listLabel, grid);
0292:
0293: list = new JList(new DefaultListModel());
0294: listLabel.setLabelFor(list);
0295: JScrollPane sp = new JScrollPane(list);
0296: grid.gridy = gridy++;
0297: grid.fill = GridBagConstraints.BOTH;
0298: grid.insets.top = 0;
0299: grid.weightx = 1.0;
0300: grid.weighty = 1.0;
0301: grid.gridheight = GridBagConstraints.RELATIVE;
0302: add(sp, grid);
0303:
0304: JPanel row2 = createButtonRow2();
0305: grid.gridy = gridy++;
0306: grid.fill = GridBagConstraints.NONE;
0307: grid.gridwidth = GridBagConstraints.REMAINDER;
0308: grid.gridheight = GridBagConstraints.REMAINDER;
0309: grid.insets.top = 5;
0310: grid.weighty = 0.0;
0311: add(row2, grid);
0312: */
0313:
0314: /*
0315: gridBagConstraints = new java.awt.GridBagConstraints();
0316: gridBagConstraints.gridx = 0;
0317: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
0318: gridBagConstraints.insets = new java.awt.Insets(11, 0, 0, 0);
0319: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
0320: addComponent(createSysLibPanel(), gridBagConstraints);
0321: */
0322:
0323: setupListeners();
0324: }
0325:
0326: void addComponent(JComponent component, GridBagConstraints gridx) {
0327: add(component, gridx);
0328: }
0329:
0330: // private JPanel createSysLibPanel() {
0331: // JPanel sysLibPanel = new JPanel();
0332: // sysLibPanel.setLayout(new java.awt.GridBagLayout());
0333: //
0334: // JLabel sysLibLabel = new JLabel();
0335: // sysLibLabel.setText("Syslibs:");
0336: // sysLibPanel.add(sysLibLabel, new java.awt.GridBagConstraints());
0337: //
0338: // JTextField sysLibTextField = new JTextField();
0339: // sysLibLabel.setLabelFor(sysLibTextField);
0340: // sysLibTextField.setEditable(false);
0341: // sysLibTextField.setText("jTextField1");
0342: // sysLibTextField.setFocusable(false);
0343: // java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
0344: // gridBagConstraints = new java.awt.GridBagConstraints();
0345: // gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
0346: // sysLibPanel.add(sysLibTextField, gridBagConstraints);
0347: //
0348: // return sysLibPanel;
0349: // }
0350:
0351: /** Override for custom label */
0352: protected String getListLabel() {
0353: return getString("LBL_ListLabel"); // NOI18N
0354: }
0355:
0356: /** Override for custom mnemonic */
0357: protected char getListMnemonic() {
0358: return getString("MNEM_ListLabel").charAt(0); // NOI18N
0359: }
0360:
0361: /** Create the text panel and file chooser in its own panel */
0362: private JPanel createTextPanel(String wholeLabel, char mnemonic) {
0363: int gridy = 0;
0364: String label;
0365:
0366: GridBagConstraints grid = new GridBagConstraints();
0367: JPanel panel = new JPanel(new GridBagLayout());
0368:
0369: // In some cases the label is multiline. Since a JLabel is single line
0370: // we need to break up the label and create multiple JLabels.
0371: StringTokenizer tok = new StringTokenizer(wholeLabel, "\n"); // NOI18N
0372: label = tok.nextToken();
0373:
0374: // Create the textfield, its label and buttons.
0375: entryLabel = new JLabel(label);
0376: entryLabel.setDisplayedMnemonic(mnemonic);
0377: grid.anchor = GridBagConstraints.WEST;
0378: grid.gridx = 0;
0379: grid.gridy = gridy++;
0380: grid.gridwidth = GridBagConstraints.REMAINDER;
0381: panel.add(entryLabel, grid);
0382:
0383: while (tok.hasMoreTokens()) {
0384: label = tok.nextToken();
0385: grid.gridy = gridy++;
0386: panel.add(new JLabel(label), grid);
0387: }
0388:
0389: entryText = new JTextField();
0390: entryLabel.setLabelFor(entryText);
0391: grid.fill = GridBagConstraints.HORIZONTAL;
0392: grid.gridy = gridy++;
0393: grid.gridwidth = GridBagConstraints.RELATIVE;
0394: grid.weightx = 1.0;
0395: panel.add(entryText, grid);
0396:
0397: entryChooser = new JButton(getString("BTN_Chooser")); // NOI18N
0398: entryChooser.setMnemonic(getString("MNEM_Chooser").charAt(0)); // NOI18N
0399: grid.fill = GridBagConstraints.NONE;
0400: grid.gridx = GridBagConstraints.RELATIVE;
0401: grid.gridwidth = GridBagConstraints.REMAINDER;
0402: grid.insets = new Insets(0, 5, 0, 0);
0403: grid.weightx = 0.0;
0404: panel.add(entryChooser, grid);
0405: createChooser(entryChooser);
0406:
0407: return panel;
0408: }
0409:
0410: /** Create the first row of buttons */
0411: private JPanel createButtonRow1() {
0412: JPanel row = new JPanel(new GridLayout(1, 2, 6, 0));
0413:
0414: addBtn = new JButton(getString("BTN_Add")); // NOI18N
0415: addBtn.setMnemonic(getString("MNEM_Add").charAt(0)); // NOI18N
0416: addBtn.setEnabled(false);
0417: row.add(addBtn);
0418:
0419: changeBtn = new JButton(getString("BTN_Change")); // NOI18N
0420: changeBtn.setMnemonic(getString("MNEM_Change").charAt(0)); // NOI18N
0421: changeBtn.setEnabled(false);
0422: row.add(changeBtn);
0423:
0424: return row;
0425: }
0426:
0427: /** Create the 2nd row of buttons */
0428: private JPanel createButtonRow2() {
0429: JPanel row = new JPanel(new GridLayout(1, 3, 6, 0));
0430:
0431: removeBtn = new JButton(getString("BTN_Remove")); // NOI18N
0432: removeBtn.setMnemonic(getString("MNEM_Remove").charAt(0)); // NOI18N
0433: removeBtn.setEnabled(false);
0434: row.add(removeBtn);
0435:
0436: upArrow = new JButton(getString("BTN_Up")); // NOI18N
0437: upArrow.setMnemonic(getString("MNEM_Up").charAt(0)); // NOI18N
0438: upArrow.setEnabled(false);
0439: row.add(upArrow);
0440:
0441: downArrow = new JButton(getString("BTN_Down")); // NOI18N
0442: downArrow.setMnemonic(getString("MNEM_Down").charAt(0)); // NOI18N
0443: downArrow.setEnabled(false);
0444: row.add(downArrow);
0445:
0446: return row;
0447: }
0448:
0449: /** Return a pointer to the JList */
0450: public JList getList() {
0451: return list;
0452: }
0453:
0454: /** Return an array of all items collected in the list */
0455: public String[] getListItems() {
0456: Object[] o = ((DefaultListModel) list.getModel()).toArray();
0457: String[] s = new String[o.length];
0458:
0459: for (int i = 0; i < o.length; i++) {
0460: s[i] = o[i].toString().trim();
0461: }
0462:
0463: return s;
0464: }
0465:
0466: /**
0467: * Expand the text string to an array of (ListItem) objects.
0468: *
0469: * Note: The currentDirectory may not exist or may not be a directory.
0470: * We need to handle this gracefully. If it doesn't exist its not an error
0471: * but we can't do any RE expansion or relative path lookup.
0472: *
0473: * @param text The complete string entered into the text field
0474: * @return An array of ListItem[] objects, one for each file name
0475: */
0476: private Object[] expandFileList(String text) {
0477: StringTokenizer st = new StringTokenizer(text);
0478: LinkedList list = new LinkedList();
0479: TokType type = new TokType();
0480: boolean neFileAdded = false;
0481: int tcount = 0;
0482:
0483: while (st.hasMoreTokens()) {
0484: String tok = validateInput(st.nextToken());
0485:
0486: if (tok != null) { // tok can be null, see validateInput javadoc
0487: if (tok.startsWith("$(")) { // NOI18N
0488: // Treat all chars up to matching ')' as one token
0489: int plevel = 1;
0490: int pos = 2;
0491: while (plevel > 0) {
0492: for (int i = pos; i < tok.length(); i++) {
0493: if (tok.charAt(i) == '(')
0494: plevel++;
0495: if (tok.charAt(i) == ')')
0496: plevel--;
0497: if (plevel <= 0)
0498: break;
0499: }
0500: if (plevel > 0) {
0501: if (st.hasMoreTokens()) {
0502: pos = tok.length() + 1;
0503: tok = tok + " " + st.nextToken(); // NOI18N
0504: } else {
0505: break;
0506: }
0507: }
0508: }
0509: }
0510:
0511: LinkedList tmp = expandToken(tok, type);
0512: tcount++;
0513:
0514: if (tmp.size() == 0) {
0515: if (!type.isRE()) { // add nonexistant file
0516: list.add(new ListItem(tok, false));
0517: neFileAdded = true;
0518: }
0519: } else {
0520: ListIterator iter = tmp.listIterator();
0521: while (iter.hasNext()) {
0522: ListItem item = (ListItem) iter.next();
0523: File file = new File(item.getName());
0524:
0525: if (expandDirs && file.isDirectory()) {
0526: LinkedList l = processDirectory(tok, file);
0527: if (l != null) {
0528: list.addAll(l);
0529: } else {
0530: tcount--; // it was cancelled
0531: }
0532: } else {
0533: list.add(new ListItem(file
0534: .getAbsolutePath(), file.exists()));
0535: }
0536: }
0537: }
0538: }
0539: }
0540:
0541: //
0542: // The criterial for displaying an alert is an arbitrary decision from
0543: // WorkShop's ProjectWizard.
0544: //
0545: if (checkErrorConditions(tcount, list, neFileAdded)) {
0546: ErrorInfo einfo = getErrorInfo();
0547: NotifyDescriptor nd = new NotifyDescriptor(einfo.getMsg(),
0548: einfo.getTitle(), NotifyDescriptor.DEFAULT_OPTION,
0549: NotifyDescriptor.WARNING_MESSAGE,
0550: new Object[] { NotifyDescriptor.OK_OPTION },
0551: NotifyDescriptor.OK_OPTION);
0552: DialogDisplayer.getDefault().notify(nd);
0553: }
0554:
0555: return list.toArray(new ListItem[list.size()]);
0556: }
0557:
0558: /**
0559: * By default its an error if only one token was found and it didn't match any file.
0560: *
0561: * @param tcount The number of tokens
0562: * @param list The list of token matches
0563: * @param nefiles True if non existant files were specified or matched
0564: */
0565: protected boolean checkErrorConditions(int tcount, LinkedList list,
0566: boolean nefiles) {
0567: return tcount == 1 && (list.size() == 0 || nefiles);
0568: }
0569:
0570: /** Derived classes supply alert title and message */
0571: protected abstract ErrorInfo getErrorInfo();
0572:
0573: /**
0574: * Expand a UnixRE into a linked list of files.
0575: *
0576: * @param token The regular expression to be expanded
0577: * @param type Tell if the token is a regular expression
0578: * @return A linked list of type ItemList with an entry for each
0579: * item to display.
0580: */
0581: private LinkedList expandToken(String token, TokType type) {
0582: LinkedList files = new LinkedList();
0583: REParser rep = new REParser(token);
0584: String comp = rep.getFirstComponent();
0585: String re = rep.getRegularExpression();
0586: String rem = rep.getRemainder();
0587:
0588: if (re == null) {
0589: File f = new File(comp);
0590: type.setRE(false);
0591: if (f.exists()) {
0592: files
0593: .add(new ListItem(f.getAbsolutePath(), f
0594: .exists()));
0595: }
0596: } else {
0597: type.setRE(true);
0598: LinkedList list = processDir(comp, re);
0599: TokType dontcare = new TokType();
0600: if (list != null) {
0601: if (rem == null) {
0602: files.addAll(list);
0603: } else {
0604: ListIterator iter = list.listIterator();
0605:
0606: while (iter.hasNext()) {
0607: ListItem item = (ListItem) iter.next();
0608: StringBuffer buf = new StringBuffer(256);
0609:
0610: buf.append(item.getName());
0611: buf.append(File.separator);
0612: buf.append(rem);
0613: files.addAll(expandToken(buf.toString(),
0614: dontcare));
0615: }
0616: }
0617: }
0618: }
0619:
0620: return files;
0621: }
0622:
0623: /**
0624: * Given a directory and UnixRE pattern return a LinkedList of all matching
0625: * files and directories.
0626: *
0627: * @param dir The directory to match the UnixRE against
0628: * @return The LinkedList containing all matches
0629: */
0630: private LinkedList processDir(String dir, String pattern) {
0631: LinkedList list = new LinkedList();
0632: File[] files = getFileArray(new File(dir));
0633: UnixRE re;
0634:
0635: if (files == null) {
0636: return null;
0637: } else {
0638: try {
0639: re = new UnixRE(pattern);
0640: } catch (PatternSyntaxException e) {
0641: if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0642: e.printStackTrace();
0643: }
0644: return null;
0645: }
0646:
0647: for (int i = 0; i < files.length; i++) {
0648: String name = files[i].toString();
0649: if (re.match(name)) {
0650: File file = new File(name);
0651: list.add(new ListItem(file.getAbsolutePath(), file
0652: .exists()));
0653: }
0654: }
0655: }
0656:
0657: return list;
0658: }
0659:
0660: /**
0661: * Break the text field down into 3 fields. The first part is the name of
0662: * the longest directory component with no UnixRE chars, the 2nd part is
0663: * the UnixRE, and the 3rd part is the remainder. If there are no UnixRE
0664: * chars in the whole string then the firstComonent is the full file name.
0665: * In all cases, the breaks are at '/' characters.
0666: */
0667: private class REParser {
0668:
0669: /** Every directory and file component before the first RE pattern */
0670: private String firstComponent;
0671:
0672: /** The (optional) regular expression */
0673: private String regularExpression;
0674:
0675: /** Anything left after the regular expression */
0676: private String remainder;
0677:
0678: /**
0679: * Parse the given text for quick lookup later.
0680: *
0681: * @param text The input from the JTextField
0682: */
0683: public REParser(String text) {
0684: int pos1 = 0, pos2;
0685:
0686: if (text.charAt(0) != File.separatorChar) {
0687: text = getMakefileData().getBaseDirectory(
0688: MakefileData.EXPAND)
0689: + File.separator + text;
0690: }
0691: for (int i = 0; i < text.length(); i++) {
0692: char c = text.charAt(i);
0693: if (c == '/') {
0694: pos1 = i; // store for later use
0695: }
0696: if (c == '*' || c == '?' || c == '[') {
0697: // pos points to the last '/'
0698: firstComponent = new String(text.substring(0, pos1));
0699:
0700: // set pos to the '/' delimiting the RE
0701: pos2 = text.indexOf('/', i);
0702: if (pos2 == -1) {
0703: regularExpression = new String(text
0704: .substring(pos1 + 1));
0705: remainder = null;
0706: } else {
0707: regularExpression = new String(text.substring(
0708: pos1 + 1, pos2));
0709: remainder = new String(text.substring(pos2 + 1));
0710: }
0711: return;
0712: }
0713: }
0714:
0715: // didn't find any regular expression characters
0716: firstComponent = new String(text);
0717: regularExpression = null;
0718: remainder = null;
0719: }
0720:
0721: /** Getter for firstComponent */
0722: public String getFirstComponent() {
0723: return firstComponent;
0724: }
0725:
0726: /** Getter for regularExpression */
0727: public String getRegularExpression() {
0728: return regularExpression;
0729: }
0730:
0731: /** Getter for remainder */
0732: public String getRemainder() {
0733: return remainder;
0734: }
0735: }
0736:
0737: /**
0738: * This should be File.listFiles() except that method ignores "." and
0739: * "..". This method adds those missing directories.
0740: */
0741: private File[] getFileArray(File dir) {
0742: File[] files = dir.listFiles();
0743:
0744: if (files == null) {
0745: return null;
0746: }
0747:
0748: File[] augmented = new File[files.length + 2];
0749: augmented[0] = new File("."); // NOI18N
0750: augmented[1] = new File(".."); // NOI18N
0751: for (int i = 0; i < files.length; i++) {
0752: augmented[i + 2] = files[i];
0753: }
0754:
0755: return augmented;
0756: }
0757:
0758: /**
0759: * Ask the user if just this directory should be checked or if a recursive
0760: * directory traversal should be done. Call a method to add the files based
0761: * on what the user specifies.
0762: *
0763: * @param name The name of the directory being added/processed
0764: * @param file The File representing the named directory
0765: * @return A linked list containing a ListItem for each selected file
0766: *
0767: * Note: If no files are chosen an empty LinkedList is returned.
0768: */
0769: private LinkedList processDirectory(String name, File file) {
0770:
0771: // Ask the user what to do
0772: String msg = MessageFormat.format(
0773: getString("MSG_CREATE_SOURCE_DIRECTORY"), // NOI18N
0774: new Object[] { name });
0775: JButton subdirs = new JButton(getString("BTN_Subdirs")); // NOI18N
0776: subdirs.setMnemonic(getString("MNEM_Subdirs").charAt(0)); // NOI18N
0777: JButton dirs = new JButton(getString("BTN_Dirs")); // NOI18N
0778: dirs.setMnemonic(getString("MNEM_Dirs").charAt(0)); // NOI18N
0779: JButton cancel = new JButton(getString("BTN_Cancel")); // NOI18N
0780: String TITLE = getString("LBL_QUESTION_WINDOW"); // NOI18N
0781:
0782: NotifyDescriptor nd = new NotifyDescriptor(msg, TITLE,
0783: NotifyDescriptor.DEFAULT_OPTION,
0784: NotifyDescriptor.QUESTION_MESSAGE, new JButton[] {
0785: subdirs, dirs, cancel }, subdirs);
0786:
0787: // Post the QuestionWindow
0788: Object ret = DialogDisplayer.getDefault().notify(nd);
0789:
0790: // Process the user's answer
0791: if (ret instanceof JButton) {
0792: if (ret.equals(subdirs)) {
0793: return addDirectoryFiles(name, file, true);
0794: } else if (ret.equals(dirs)) {
0795: return addDirectoryFiles(name, file, false);
0796: }
0797: }
0798:
0799: return null; // return null list for cancel
0800: }
0801:
0802: /**
0803: * Add the files in the given directory. Recursively do subdirectories if
0804: * the recurse flag is set.
0805: *
0806: * @param parent The relative pathname of the parent directory
0807: * @param dir The File representing the parent directory
0808: * @param recurse Tells if we should recursively call ourselves for
0809: * subdirectories
0810: * @return A linked list containing a ListItem for each file added
0811: */
0812: private LinkedList addDirectoryFiles(String parent, File dir,
0813: boolean recurse) {
0814: LinkedList list = new LinkedList();
0815:
0816: // Add each file in the directory
0817: File[] files = dir.listFiles(new SrcsFileFilter());
0818: for (int i = 0; i < files.length; i++) {
0819: list.add(new ListItem(parent + File.separator
0820: + files[i].getName(), true));
0821: }
0822:
0823: if (recurse) {
0824: // Recursively call this method for each subdirectory
0825: File[] dirs = dir.listFiles(new DirFilter());
0826: for (int i = 0; i < dirs.length; i++) {
0827: list.addAll(addDirectoryFiles(parent + File.separator
0828: + dirs[i].getName(), dirs[i], true));
0829: }
0830: }
0831:
0832: return list;
0833: }
0834:
0835: /**
0836: * Add all items to the item list which have been specified in objects.
0837: */
0838: protected void addMultipleFiles(Object[] objects) {
0839:
0840: if (objects != null) { // no files in a directory
0841: DefaultListModel model = (DefaultListModel) list.getModel();
0842: String cwd = getMakefileData().getBaseDirectory(
0843: MakefileData.EXPAND);
0844:
0845: for (int i = 0; i < objects.length; i++) {
0846: String path = IpeUtils.getRelativePath(cwd,
0847: ((ListItem) objects[i]).getName());
0848: if (!model.contains(path)) { // expensive! but necessary
0849: if (addBeginning)
0850: model.add(0, path);
0851: else
0852: model.addElement(path);
0853: }
0854: }
0855: }
0856: }
0857:
0858: /**
0859: * Add all items to the item list which have been specified in files.
0860: */
0861: protected void addMultipleFiles(File[] files) {
0862:
0863: if (files != null) {
0864: DefaultListModel model = (DefaultListModel) list.getModel();
0865: String cwd = getMakefileData().getBaseDirectory(
0866: MakefileData.EXPAND);
0867:
0868: for (int i = 0; i < files.length; i++) {
0869: String path = IpeUtils.getRelativePath(cwd, files[i]
0870: .getPath());
0871: if (!model.contains(path)) { // expensive! but necessary
0872: if (addBeginning)
0873: model.add(0, path);
0874: else
0875: model.addElement(path);
0876: }
0877: }
0878: }
0879: }
0880:
0881: /**
0882: * The default implementation returns the input unchanged. Classes derived
0883: * from EnterItemsPanel may override the default and add/remove text or
0884: * even return a null to indicate the whole token was unwanted.
0885: */
0886: protected String validateInput(String token) {
0887: return token;
0888: }
0889:
0890: /**
0891: * Create a FileChoose for the text field.
0892: */
0893: protected void createChooser(JButton chooser) {
0894:
0895: chooser.addActionListener(new ActionListener() {
0896: public void actionPerformed(ActionEvent evt) {
0897:
0898: if (fc == null) {
0899: fc = new JFileChooser();
0900: fc.setApproveButtonText(getString("BTN_Approve")); // NOI18N
0901: fc.setMultiSelectionEnabled(true);
0902: fc.setFileSystemView(new IpeFileSystemView(fc
0903: .getFileSystemView()));
0904: if (mspFilter) {
0905: fc.setFileFilter(new MspFileFilter());
0906: }
0907: if (dirChooser) {
0908: fc
0909: .setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
0910: fc
0911: .setDialogTitle(getString("TITLE_DirChooser")); // NOI18N
0912: } else {
0913: fc
0914: .setDialogTitle(getString("DLG_FILE_CHOOSER_TITLE")); // NOI18N
0915: }
0916: }
0917:
0918: // See if the user has already typed a directory. If so use it.
0919: File f = null;
0920: String cur = IpeUtils.expandPath(getText());
0921: if (cur.length() > 0) {
0922: f = new File(cur);
0923: }
0924:
0925: if (f != null && f.isDirectory()) {
0926: fc.setCurrentDirectory(f);
0927: } else if (lastChooserDir != null) {
0928: fc.setCurrentDirectory(lastChooserDir);
0929: } else {
0930: fc.setCurrentDirectory(new File(getMakefileData()
0931: .getBaseDirectory(MakefileData.EXPAND)));
0932: }
0933: int returnVal = fc.showDialog(EnterItemsPanel.this ,
0934: null);
0935:
0936: if (returnVal == JFileChooser.APPROVE_OPTION) {
0937: addMultipleFiles(fc.getSelectedFiles());
0938: lastChooserDir = fc.getCurrentDirectory();
0939: entryText.setText(null);
0940: addBtn.setEnabled(false);
0941: }
0942: }
0943: });
0944: }
0945:
0946: public JTextField getEntryText() {
0947: return entryText;
0948: }
0949:
0950: private String getText() {
0951: return IpeUtils.expandPath(entryText.getText());
0952: }
0953:
0954: /**
0955: * The validation method. This panel is valid iff a writable directory is
0956: * specified.
0957: */
0958: public boolean isPanelValid() {
0959:
0960: if (itemsRequired && list.getModel().getSize() == 0) {
0961: return false;
0962: } else {
0963: return true;
0964: }
0965: }
0966:
0967: public void addNotify() {
0968:
0969: super .addNotify();
0970:
0971: // disable up/down/remove buttons (4880337)
0972: removeBtn.setEnabled(false);
0973: upArrow.setEnabled(false);
0974: downArrow.setEnabled(false);
0975:
0976: if (itemsRequired && list.getModel().getSize() == 0) {
0977: nextButton.setEnabled(false);
0978: }
0979:
0980: if (dynamicNext && entryText.getDocument().getLength() > 0) {
0981: addBtn.setEnabled(true);
0982: //getRootPane().setDefaultButton(addBtn);
0983: IpeUtils.setDefaultButton(getRootPane(), addBtn);
0984: }
0985: entryText.selectAll();
0986: IpeUtils.requestFocus(entryText);
0987: }
0988:
0989: public void removeNotify() {
0990: super .removeNotify();
0991:
0992: if (dynamicNext || itemsRequired) {
0993: nextButton.setEnabled(true);
0994: getRootPane().setDefaultButton(nextButton);
0995: }
0996:
0997: if (fc != null && fc.isShowing()) {
0998: Object o = fc.getTopLevelAncestor();
0999: if (o != null && o instanceof JDialog) {
1000: ((JDialog) o).dispose();
1001: }
1002: }
1003: }
1004:
1005: /**
1006: * Setup listeners for entryText and list. This needs to be done after all
1007: * components are created so its not done in the create* methods.
1008: */
1009: private void setupListeners() {
1010: final DefaultListModel model = (DefaultListModel) list
1011: .getModel();
1012:
1013: entryText.getDocument().addDocumentListener(
1014: new DocumentListener() {
1015: public void changedUpdate(DocumentEvent e) {
1016: if (e.getDocument().getLength() >= 1) {
1017: addBtn.setEnabled(true);
1018: if (dynamicNext) {
1019: getRootPane().setDefaultButton(addBtn);
1020: }
1021: }
1022: }
1023:
1024: public void insertUpdate(DocumentEvent e) {
1025: if (e.getDocument().getLength() >= 1) {
1026: addBtn.setEnabled(true);
1027: if (dynamicNext
1028: && list.getModel().getSize() == 0) {
1029: getRootPane().setDefaultButton(addBtn);
1030: }
1031:
1032: int min = list.getMinSelectionIndex();
1033: int max = list.getMaxSelectionIndex();
1034: if (min >= 0 && max >= 0 && min == max) {
1035: // Single line selections:
1036: changeBtn.setEnabled(true);
1037: }
1038: }
1039: }
1040:
1041: public void removeUpdate(DocumentEvent e) {
1042: if (e.getDocument().getLength() == 0) {
1043: addBtn.setEnabled(false);
1044: changeBtn.setEnabled(false);
1045: if (dynamicNext) {
1046: getRootPane().setDefaultButton(
1047: nextButton);
1048: }
1049: }
1050: }
1051: });
1052:
1053: addBtn.addActionListener(new ActionListener() {
1054: public void actionPerformed(ActionEvent e) {
1055: addMultipleFiles(expandFileList(getText()));
1056: list.clearSelection();
1057: entryText.setText(null);
1058: addBtn.setEnabled(false);
1059: changeBtn.setEnabled(false);
1060: if ((dynamicNext && !itemsRequired)
1061: || (itemsRequired && model.getSize() > 0)) {
1062: nextButton.setEnabled(true);
1063: getRootPane().setDefaultButton(nextButton);
1064: }
1065: }
1066: });
1067:
1068: changeBtn.addActionListener(new ActionListener() {
1069: public void actionPerformed(ActionEvent e) {
1070: model.set(list.getMinSelectionIndex(), getText());
1071: }
1072: });
1073:
1074: removeBtn.addActionListener(new ActionListener() {
1075: public void actionPerformed(ActionEvent e) {
1076: //int min = list.getMinSelectionIndex();
1077: //int max = list.getMaxSelectionIndex();
1078: //model.removeRange(min, max);
1079:
1080: int min = list.getMinSelectionIndex();
1081: int[] removeList = list.getSelectedIndices();
1082: for (int i = removeList.length; i > 0; i--) {
1083: model.remove(removeList[i - 1]);
1084: }
1085:
1086: int selectedIndex = (min >= list.getModel().getSize()) ? min - 1
1087: : min;
1088: if (selectedIndex >= 0) {
1089: list.ensureIndexIsVisible(selectedIndex);
1090: list.setSelectedIndex(selectedIndex);
1091: removeBtn.setEnabled(true);
1092: changeBtn.setEnabled(true);
1093: upArrow.setEnabled(selectedIndex > 0);
1094: downArrow.setEnabled(selectedIndex < (list
1095: .getModel().getSize() - 1));
1096: } else {
1097: removeBtn.setEnabled(false);
1098: changeBtn.setEnabled(false);
1099: upArrow.setEnabled(false);
1100: downArrow.setEnabled(false);
1101: }
1102: }
1103: });
1104:
1105: list.addListSelectionListener(new ListSelectionListener() {
1106: public void valueChanged(ListSelectionEvent e) {
1107: // Ignore any calls while value is being adjusted (ie, dragged)
1108: if (!e.getValueIsAdjusting()) {
1109: int min = list.getMinSelectionIndex();
1110: int max = list.getMaxSelectionIndex();
1111:
1112: if (min >= 0 && max >= 0) {
1113: if (min == max) {
1114: // Single line selections:
1115:
1116: // Set selected value in the text field and enable
1117: // the change button.
1118: entryText
1119: .setText(model.get(min).toString());
1120: addBtn.setEnabled(true);
1121: changeBtn.setEnabled(true);
1122:
1123: // Enable the up and down arrows unless selection
1124: // is 0th or last entry.
1125: upArrow.setEnabled(min != 0);
1126: downArrow.setEnabled(min != (model
1127: .getSize() - 1));
1128: } else {
1129: entryText.setText(null);
1130: changeBtn.setEnabled(false);
1131: upArrow.setEnabled(false);
1132: downArrow.setEnabled(false);
1133: }
1134: }
1135:
1136: // We can delete any selection
1137: removeBtn.setEnabled(true);
1138: }
1139: }
1140: });
1141:
1142: model.addListDataListener(new ListDataListener() {
1143: public void contentsChanged(ListDataEvent e) {
1144: if (model.getSize() > 0) {
1145: if (dynamicLast && !lastEnabled
1146: && getMakefileData().isComplete(true)) {
1147: lastEnabled = true;
1148: //MakefileWizard.getMakefileWizard().setFinishEnabled(true);
1149: }
1150: } else {
1151: if (dynamicLast && lastEnabled) {
1152: lastEnabled = false;
1153: //MakefileWizard.getMakefileWizard().setFinishEnabled(false);
1154: }
1155: }
1156: }
1157:
1158: public void intervalRemoved(ListDataEvent e) {
1159: if (model.getSize() == 0) {
1160: if (dynamicNext && itemsRequired
1161: && list.getModel().getSize() == 0) {
1162: getRootPane().setDefaultButton(addBtn);
1163: nextButton.setEnabled(false);
1164: }
1165: if (dynamicLast && lastEnabled) {
1166: lastEnabled = false;
1167: //MakefileWizard.getMakefileWizard().setFinishEnabled(false);
1168: }
1169: }
1170: }
1171:
1172: public void intervalAdded(ListDataEvent e) {
1173: if (dynamicNext && itemsRequired) {
1174: nextButton.setEnabled(true);
1175: getRootPane().setDefaultButton(nextButton);
1176: }
1177: if (dynamicLast && !lastEnabled
1178: && getMakefileData().isComplete(true)) {
1179: lastEnabled = true;
1180: //MakefileWizard.getMakefileWizard().setFinishEnabled(true);
1181: }
1182: }
1183: });
1184:
1185: // There is an assumption that the button is disabled if it cannot be
1186: // decreased.
1187: upArrow.addActionListener(new ActionListener() {
1188: public void actionPerformed(ActionEvent e) {
1189: int idx = list.getSelectedIndex();
1190:
1191: Object o = model.remove(idx);
1192: model.add(idx - 1, o);
1193: list.setSelectedIndex(idx - 1);
1194: if (idx == 1) {
1195: upArrow.setEnabled(false);
1196: }
1197: }
1198: });
1199:
1200: // There is an assumption that the button is disabled if it cannot be
1201: // increased.
1202: downArrow.addActionListener(new ActionListener() {
1203: public void actionPerformed(ActionEvent e) {
1204: int idx = list.getSelectedIndex();
1205:
1206: Object o = model.remove(idx);
1207: model.add(idx + 1, o);
1208: list.setSelectedIndex(idx + 1);
1209: if (idx == (model.getSize() - 1)) {
1210: downArrow.setEnabled(false);
1211: }
1212: }
1213: });
1214: }
1215:
1216: /**
1217: * Filter to display directories and source files in the FileChooser.
1218: */
1219: private class MspFileFilter extends
1220: javax.swing.filechooser.FileFilter {
1221:
1222: /** Store the filter string since its used in several places */
1223: private String filterString;
1224:
1225: /** Constructor for MspFileFilter */
1226: public MspFileFilter() {
1227: filterString = getString("DFLT_SourceFilter"); // NOI18N
1228: }
1229:
1230: /**
1231: * Match the given file against the default source file regular
1232: * expression.
1233: *
1234: * @param file The source file to check
1235: * @return true if its a source file or directory
1236: */
1237: public boolean accept(File file) {
1238:
1239: if (file.isDirectory()) {
1240: return true;
1241: }
1242:
1243: if (filters == null) {
1244: StringTokenizer st = new StringTokenizer(filterString);
1245: filters = new HashSet(15);
1246:
1247: synchronized (filters) {
1248: try {
1249: while (st.hasMoreTokens()) {
1250: filters.add(new UnixRE(st.nextToken()));
1251: }
1252: } catch (PatternSyntaxException ex) {
1253: ex.printStackTrace();
1254: return false;
1255: }
1256: }
1257: }
1258:
1259: synchronized (filters) {
1260: Iterator iter = filters.iterator();
1261: while (iter.hasNext()) {
1262: UnixRE re = (UnixRE) iter.next();
1263:
1264: if (re.match(file.getName())) {
1265: return true;
1266: }
1267: }
1268: }
1269:
1270: return false;
1271: }
1272:
1273: public String getDescription() {
1274: return filterString;
1275: }
1276: }
1277:
1278: /**
1279: * Filter to eliminate directories and non-source files. Uses the default
1280: * sources filter to match only source files.
1281: */
1282: private class SrcsFileFilter implements java.io.FileFilter {
1283:
1284: /** Store the filter string since its used in several places */
1285: private String filterString;
1286:
1287: /** Constructor for SrcsFileFilter */
1288: public SrcsFileFilter() {
1289: filterString = getString("DFLT_SourceFilter"); // NOI18N
1290: }
1291:
1292: /**
1293: * Match the given file against the default source file regular
1294: * expression. Verify its not a directory first.
1295: *
1296: * @param file The source file to check
1297: * @return true if its a source file otherwise false
1298: */
1299: public boolean accept(File file) {
1300:
1301: if (file.isDirectory()) {
1302: return false;
1303: }
1304:
1305: if (filters == null) {
1306: StringTokenizer st = new StringTokenizer(filterString);
1307: filters = new HashSet(15);
1308:
1309: synchronized (filters) {
1310: try {
1311: while (st.hasMoreTokens()) {
1312: filters.add(new UnixRE(st.nextToken()));
1313: }
1314: } catch (PatternSyntaxException ex) {
1315: ex.printStackTrace();
1316: return false;
1317: }
1318: }
1319: }
1320:
1321: synchronized (filters) {
1322: Iterator iter = filters.iterator();
1323: while (iter.hasNext()) {
1324: UnixRE re = (UnixRE) iter.next();
1325:
1326: if (re.match(file.getName())) {
1327: return true;
1328: }
1329: }
1330: }
1331:
1332: return false;
1333: }
1334: }
1335:
1336: /**
1337: * Filter to eliminate all files except directories.
1338: */
1339: private class DirFilter implements java.io.FileFilter {
1340: public boolean accept(File file) {
1341: return file.isDirectory();
1342: }
1343: }
1344:
1345: /**
1346: * Store an item for each token in the original text and each file or
1347: * directory found during the search.
1348: */
1349: protected class ListItem {
1350:
1351: /** a name from the text field */
1352: private String name;
1353:
1354: /** does the file already exist? */
1355: private boolean exists;
1356:
1357: /** Create item for the list */
1358: public ListItem(String name, boolean exists) {
1359:
1360: this .name = name;
1361: this .exists = exists;
1362: }
1363:
1364: public String getName() {
1365: return name;
1366: }
1367:
1368: public void setName(String name) {
1369: this .name = name;
1370: }
1371:
1372: public boolean isExists() {
1373: return exists;
1374: }
1375: }
1376:
1377: /** Is the token a regular expression token? */
1378: private final class TokType {
1379:
1380: private boolean re;
1381:
1382: void setRE(boolean re) {
1383: this .re = re;
1384: }
1385:
1386: boolean isRE() {
1387: return re;
1388: }
1389: }
1390:
1391: protected final class ErrorInfo {
1392:
1393: private String title;
1394: private String msg;
1395:
1396: protected ErrorInfo() {
1397: this (null, null);
1398: }
1399:
1400: protected ErrorInfo(String title, String msg) {
1401: this .title = title;
1402: this .msg = msg;
1403: }
1404:
1405: String getTitle() {
1406: return title;
1407: }
1408:
1409: void setTitle(String title) {
1410: this .title = title;
1411: }
1412:
1413: String getMsg() {
1414: return msg;
1415: }
1416:
1417: void setMsg(String msg) {
1418: this.msg = msg;
1419: }
1420: }
1421: }
|