1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution,
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: OptsParser.java,v 1.1.1.1 2004/05/09 16:57:57 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.util.args;
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.CharArrayWriter;
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException;
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.InputStream;
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.InputStreamReader;
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.PrintWriter;
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.Reader;
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.ArrayList;
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.HashMap;
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.HashSet;
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Iterator;
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.List;
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Map;
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Set;
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IConstants;
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.ResourceLoader;
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2002
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class OptsParser implements IOptsParser
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: #-comments
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: prefixing for error messages
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: support var subst (main class name, etc)
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: support short/full usage
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: support marking opts as for displayable in full usage only
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public synchronized void usage (final PrintWriter out, final int level, final int width)
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: use width
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: cache?
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String prefix = OPT_PREFIXES [CANONICAL_OPT_PREFIX];
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (Iterator i = m_metadata.getOptDefs (); i.hasNext (); )
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final OptDef optdef = (OptDef) i.next ();
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((level < 2) && optdef.isDetailedOnly ()) // skip detailed usage only options
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                continue;
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final StringBuffer line = new StringBuffer ("  ");
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String canonicalName = optdef.getCanonicalName ();
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final boolean isPattern = optdef.isPattern ();
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            line.append (prefix);
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            line.append (canonicalName);
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (isPattern) line.append ('*');
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] names = optdef.getNames ();
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int n = 0; n < names.length; ++ n)
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String name = names [n];
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (! name.equals (canonicalName))
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    line.append (", ");
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    line.append (prefix);
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    line.append (name);
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (isPattern) line.append ('*');
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String vmnemonic = optdef.getValueMnemonic ();
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (vmnemonic != null)
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                line.append (' ');
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                line.append (vmnemonic);
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int padding = 16 - line.length ();
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (padding < 2)
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // end the current line
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                out.println (line);
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                line.setLength (0);
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int p = 0; p < 16; ++ p) line.append (' ');
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int p = 0; p < padding; ++ p) line.append (' ');
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (optdef.isRequired ()) line.append ("{required} ");
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            line.append (optdef.getDescription ());
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            out.println (line);
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (level < DETAILED_USAGE)
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final OptDef usageOptDef = m_metadata.getUsageOptDef ();
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((usageOptDef != null) && (usageOptDef.getNames () != null) && (usageOptDef.getNames ().length > 1))
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                out.println ();
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                out.println ("  {use '" + usageOptDef.getNames () [1] + "' option to see detailed usage help}");
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public synchronized IOpts parse (final String [] args)
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (args == null) throw new IllegalArgumentException ("null input: args");
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final Opts opts = new Opts ();
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] nv = new String [2]; // out buffer for getOptNameAndValue()
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] pp = new String [1]; // out buffer for getOptDef()
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // running state/current vars:
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int state = STATE_OPT;
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            OptDef optdef = null;
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            Opt opt = null;
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            String value = null;
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int valueCount = 0;
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int a;
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      scan: for (a = 0; a < args.length; )
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String av = args [a];
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (av == null) throw new IllegalArgumentException ("null input: args[" + a + "]");
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                //System.out.println ("[state: " + state + "] av = " + av);
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                switch (state)
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    case STATE_OPT:
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (isOpt (av, valueCount, optdef))
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // 'av' looks like an option: get its name and see if it
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // is in the metadata
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            valueCount = 0;
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            getOptNameAndValue (av, nv); // this can leave nv[1] as null
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // [assertion: nv [0] != null]
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            final String optName = nv [0]; // is not necessarily canonical
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            optdef = m_metadata.getOptDef (optName, pp); // pp [0] is always set by this
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            if (optdef == null)
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                // unknown option:
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                // TODO: coded messages?
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                opts.addError (formatMessage ("unknown option \'" + optName + "\'"));
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                state = STATE_ERROR;
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            else
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                // merge if necessary:
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                final String canonicalName = getOptCanonicalName (optName, optdef);
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                final String patternPrefix = pp [0];
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                opt = opts.getOpt (canonicalName);
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                if (optdef.isMergeable ())
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                {
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    if (opt == null)
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    {
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        opt = new Opt (optName, canonicalName, patternPrefix);
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        opts.addOpt (opt, optdef, optName);
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    }
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                }
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                else
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                {
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    if (opt == null)
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    {
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        opt = new Opt (optName, canonicalName, patternPrefix);
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        opts.addOpt (opt, optdef, optName);
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    }
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    else
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    {
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        opts.addError (formatMessage ("option \'" + optName + "\' cannot be specified more than once"));
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        state = STATE_ERROR;
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    }
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                }
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                value = nv [1];
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                if (value == null) ++ a;
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                state = STATE_OPT_VALUE;
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        else
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // not in STATE_OPT_VALUE and 'av' does not look
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // like an option: the rest of args are free
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            state = STATE_FREE_ARGS;
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    break;
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    case STATE_OPT_VALUE:
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // [assertion: opt != null and optdef != null]
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (value != null)
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // value specified explicitly using the <name>separator<value> syntax:
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // [don't shift a]
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            valueCount = 1;
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            final int [] cardinality = optdef.getValueCardinality ();
231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            if (cardinality [1] < 1)
233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                opts.addError (formatMessage ("option \'" + opt.getName () + "\' does not accept values: \'" + value + "\'"));
235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                state = STATE_ERROR;
237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            else
239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                ++ a;
241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                opt.addValue (value);
242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        else
245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            value = args [a];
247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            final int [] cardinality = optdef.getValueCardinality ();
249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            if (isOpt (value, valueCount, optdef))
251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                if (valueCount < cardinality [0])
253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                {
254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    opts.addError (formatMessage ("option \'" + opt.getName () + "\' does not accept fewer than " + cardinality [0] + " value(s)"));
255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    state = STATE_ERROR;
257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                }
258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                else
259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    state = STATE_OPT;
260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            else
262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            {
263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                if (valueCount < cardinality [1])
264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                {
265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    ++ valueCount;
266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    ++ a;
267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    opt.addValue (value);
268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                }
269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                else
270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                {
271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                    // this check is redundant:
272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                    if (valueCount < cardinality [0])
273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                    {
274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                        opts.addError (formatMessage ("option \'" + opt.getName () + "\' does not accept fewer than " + cardinality [0] + " value(s)"));
275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                        state = STATE_ERROR;
277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                    }
278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                                    else
279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                        state = STATE_FREE_ARGS;
280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                }
281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            }
282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        value = null;
285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    break;
287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    case STATE_FREE_ARGS:
290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (isOpt (args [a], valueCount, optdef))
292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            state = STATE_OPT;
294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        else
296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            opts.setFreeArgs (args, a);
298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            break scan;
299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    break;
302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    case STATE_ERROR:
305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        break scan; // TODO: could use the current value of 'a' for a better error message
307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                } // end of switch
310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (a == args.length)
313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (opt != null) // validate the last option's min cardinality
315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final int [] cardinality = optdef.getValueCardinality ();
317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (valueCount < cardinality [0])
319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        opts.addError (formatMessage ("option \'" + opt.getName () + "\' does not accept fewer than " + cardinality [0] + " value(s)"));
321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else
324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    opts.setFreeArgs (args, a);
326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        } // end of 'args' parsing
330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final IOpt [] specified = opts.getOpts ();
333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (specified != null)
334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // validation: all required parameters must be specified
336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Set /* String(canonical name) */ required = new HashSet ();
338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            required.addAll (m_metadata.getRequiredOpts ());
339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int s = 0; s < specified.length; ++ s)
341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                required.remove (specified [s].getCanonicalName ());
343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (! required.isEmpty ())
346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (Iterator i = required.iterator (); i.hasNext (); )
348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    opts.addError (formatMessage ("missing required option \'" + (String) i.next () + "\'"));
350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int s = 0; s < specified.length; ++ s)
354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final IOpt opt = specified [s];
356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final OptDef optdef = m_metadata.getOptDef (opt.getCanonicalName (), null);
357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                // validation: value cardinality constraints
359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                final int [] cardinality = optdef.getValueCardinality ();
361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                if (opt.getValueCount () < cardinality [0])
362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    opts.addError (formatMessage ("option \'" + opt.getName () + "\' must have at least " + cardinality [0] +  " value(s)"));
363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                else if (opt.getValueCount () > cardinality [1])
364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    opts.addError (formatMessage ("option \'" + opt.getName () + "\' must not have more than " + cardinality [1] +  " value(s)"));
365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // validation: "requires" constraints
367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String [] requires = optdef.getRequiresSet (); // not canonicalized
369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (requires != null)
370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    for (int r = 0; r < requires.length; ++ r)
372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (opts.getOpt (requires [r]) == null)
374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            opts.addError (formatMessage ("option \'" + opt.getName () + "\' requires option \'" + requires [r] +  "\'"));
375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // validation: "not with" constraints
379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String [] excludes = optdef.getExcludesSet (); // not canonicalized
381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (excludes != null)
382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    for (int x = 0; x < excludes.length; ++ x)
384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        final Opt xopt = opts.getOpt (excludes [x]);
386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (xopt != null)
387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            opts.addError (formatMessage ("option \'" + opt.getName () + "\' cannot be used with option \'" + xopt.getName () +  "\'"));
388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // side effect: determine if usage is requested
392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (optdef.isUsage ())
394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    opts.setUsageRequested (opt.getName ().equals (opt.getCanonicalName ()) ? SHORT_USAGE : DETAILED_USAGE);
396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return opts;
401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static String getOptCanonicalName (final String n, final OptDef optdef)
404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (optdef.isPattern ())
406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String canonicalPattern = optdef.getCanonicalName ();
408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] patterns = optdef.getNames ();
409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int p = 0; p < patterns.length; ++ p)
411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String pattern = patterns [p];
413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (n.startsWith (pattern))
415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    return canonicalPattern.concat (n.substring (pattern.length ()));
417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // this should never happen:
421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new IllegalStateException ("failed to detect pattern prefix for [" + n + "]");
422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return optdef.getCanonicalName ();
426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * ['optdef' can be null if no current opt def context has been established]
431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * pre: av != null
433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * input not validated
434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static boolean isOpt (final String av, final int valueCount, final OptDef optdef)
436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (optdef != null)
438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // if the current optdef calls for more values, consume the next token
440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // as an op value greedily, without looking at its prefix:
441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int [] cardinality = optdef.getValueCardinality ();
443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (valueCount < cardinality [1]) return false;
445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // else check av's prefix:
448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int p = 0; p < OPT_PREFIXES.length; ++ p)
450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (av.startsWith (OPT_PREFIXES [p]))
452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return (av.length () > OPT_PREFIXES [p].length ());
453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return false;
456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * pre: av != null and isOpt(av)=true
460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * input not validated
461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static void getOptNameAndValue (final String av, final String [] nv)
463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        nv [0] = null;
465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        nv [1] = null;
466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int p = 0; p < OPT_PREFIXES.length; ++ p)
468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((av.startsWith (OPT_PREFIXES [p])) && (av.length () > OPT_PREFIXES [p].length ()))
470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String name = av.substring (OPT_PREFIXES [p].length ()); // with a possible value after a separator
472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                char separator = 0;
474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                int sindex = Integer.MAX_VALUE;
475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int s = 0; s < OPT_VALUE_SEPARATORS.length; ++ s)
477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final int index = name.indexOf (OPT_VALUE_SEPARATORS [s]);
479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ((index > 0) && (index < sindex))
480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        separator = OPT_VALUE_SEPARATORS [s];
482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        sindex = index;
483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (separator != 0)
487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    nv [0] = name.substring (0, sindex);
489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    nv [1] = name.substring (sindex + 1);
490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else
492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    nv [0] = name;
494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return;
497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    static final class Opt implements IOptsParser.IOpt
507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String getName ()
509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_name;
511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String getCanonicalName ()
514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_canonicalName;
516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public int getValueCount ()
519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_values == null) return 0;
521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_values.size ();
523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String getFirstValue ()
526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_values == null) return null;
528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return (String) m_values.get (0);
530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String [] getValues ()
533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_values == null) return IConstants.EMPTY_STRING_ARRAY;
535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] result = new String [m_values.size ()];
537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_values.toArray (result);
538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return result;
540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String getPatternPrefix ()
543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_patternPrefix;
545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String toString ()
548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final StringBuffer s = new StringBuffer (m_name);
550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (! m_canonicalName.equals (m_name)) s.append (" [" + m_canonicalName + "]");
551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_values != null)
553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                s.append (": ");
555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                s.append (m_values);
556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return s.toString ();
559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Opt (final String name, final String canonicalName, final String patternPrefix)
562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_name = name;
564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_canonicalName = canonicalName;
565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_patternPrefix = patternPrefix;
566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void addValue (final String value)
569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (value == null) throw new IllegalArgumentException ("null input: value");
571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_values == null) m_values = new ArrayList ();
573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_values.add (value);
574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final String m_name, m_canonicalName, m_patternPrefix;
578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private ArrayList m_values;
579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    static final class Opts implements IOptsParser.IOpts
584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public int usageRequestLevel ()
586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_usageRequestLevel;
588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public void error (final PrintWriter out, final int width)
591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // TODO: use width
593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (hasErrors ())
594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (Iterator i = m_errors.iterator (); i.hasNext (); )
596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    out.println (i.next ());
598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String [] getFreeArgs ()
603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (hasErrors ())
605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new IllegalStateException (errorsToString ());
606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_freeArgs;
608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public IOpt [] getOpts ()
611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (hasErrors ()) return null;
613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_opts.isEmpty ())
615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return EMPTY_OPT_ARRAY;
616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final IOpt [] result = new IOpt [m_opts.size ()];
619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_opts.toArray (result);
620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return result;
622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public IOpt [] getOpts (final String pattern)
626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (hasErrors ()) return null;
628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final List /* Opt */ patternOpts = (List) m_patternMap.get (pattern);
630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((patternOpts == null) || patternOpts.isEmpty ())
632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return EMPTY_OPT_ARRAY;
633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final IOpt [] result = new IOpt [patternOpts.size ()];
636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                patternOpts.toArray (result);
637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return result;
639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public boolean hasArg (final String name)
644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (hasErrors ())
646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new IllegalStateException (errorsToString ());
647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_nameMap.containsKey (name);
649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Opts ()
652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_opts = new ArrayList ();
654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_nameMap = new HashMap ();
655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_patternMap = new HashMap ();
656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void addOpt (final Opt opt, final OptDef optdef, final String occuranceName)
659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (opt == null) throw new IllegalArgumentException ("null input: opt");
661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (optdef == null) throw new IllegalArgumentException ("null input: optdef");
662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (occuranceName == null) throw new IllegalArgumentException ("null input: occuranceName");
663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // [name collisions detected elsewhere]
665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_opts.add (opt);
667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] names = optdef.getNames ();
669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final boolean isPattern = (opt.getPatternPrefix () != null);
670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (isPattern)
672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final String unprefixedName = occuranceName.substring (opt.getPatternPrefix ().length ());
674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int n = 0; n < names.length; ++ n)
676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    m_nameMap.put (names [n].concat (unprefixedName), opt);
678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final String canonicalPattern = optdef.getCanonicalName ();
682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    List patternList = (List) m_patternMap.get (canonicalPattern);
684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (patternList == null)
685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        patternList = new ArrayList ();
687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        for (int n = 0; n < names.length; ++ n)
688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            m_patternMap.put (names [n], patternList);
690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    patternList.add (opt);
694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int n = 0; n < names.length; ++ n)
699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    m_nameMap.put (names [n], opt);
701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Opt getOpt (final String occuranceName)
706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (occuranceName == null) throw new IllegalArgumentException ("null input: occuranceName");
708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return (Opt) m_nameMap.get (occuranceName);
710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setFreeArgs (final String [] args, final int start)
713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (args == null) throw new IllegalArgumentException ("null input: args");
715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((start < 0) || (start > args.length)) throw new IllegalArgumentException ("invalid start index: " + start);
716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_freeArgs = new String [args.length - start];
718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            System.arraycopy (args, start, m_freeArgs, 0, m_freeArgs.length);
719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setUsageRequested (final int level)
722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_usageRequestLevel = level;
724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void addError (final String msg)
727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (msg != null)
729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (m_errors == null) m_errors = new ArrayList ();
731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_errors.add (msg);
733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean hasErrors ()
737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return (m_errors != null) && ! m_errors.isEmpty ();
739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String errorsToString ()
742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (! hasErrors ()) return "<no errors>";
744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final CharArrayWriter caw = new CharArrayWriter ();
746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final PrintWriter pw = new PrintWriter (caw);
747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            error (pw, DEFAULT_ERROR_WIDTH);
749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            pw.flush ();
750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return caw.toString ();
752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final List /* Opt */ m_opts;
756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final Map /* String(name/pattern-prefixed name)->Opt */ m_nameMap;
757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final Map /* String(pattern prefix)->List<Opt> */ m_patternMap;
758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private String [] m_freeArgs;
759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private List /* String */ m_errors;
760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private int m_usageRequestLevel;
761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private static final int DEFAULT_ERROR_WIDTH = 80;
763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private static final IOpt [] EMPTY_OPT_ARRAY = new IOpt [0];
764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    static final class OptDef // TODO: merge with Opt?
769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        OptDef (final boolean usage)
771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_usage = usage;
773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean isUsage ()
776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_usage;
778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String getCanonicalName ()
781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_names [0];
783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String [] getNames ()
786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_names;
788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean isRequired ()
791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_required;
793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String getValueMnemonic ()
796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_valueMnemonic;
798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean isMergeable ()
801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_mergeable;
803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean isDetailedOnly ()
806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_detailedOnly;
808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        boolean isPattern ()
811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_pattern;
813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
814f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
815f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        int [] getValueCardinality ()
816f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
817f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_valueCardinality;
818f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
819f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
820f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String [] getRequiresSet ()
821f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
822f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_requiresSet;
823f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
824f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
825f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String [] getExcludesSet ()
826f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
827f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_excludesSet;
828f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
829f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
830f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String getDescription ()
831f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
832f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_description;
833f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
834f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
835f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setNames (final String [] names)
836f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
837f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (names == null) throw new IllegalArgumentException ("null input: names");
838f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
839f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_names = names;
840f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
841f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
842f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setRequired (final boolean required)
843f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
844f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_required = required;
845f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
846f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
847f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setValueMnemonic (final String mnemonic)
848f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
849f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (mnemonic == null) throw new IllegalArgumentException ("null input: mnemonic");
850f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
851f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_valueMnemonic = mnemonic;
852f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
853f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
854f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setMergeable (final boolean mergeable)
855f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
856f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_mergeable = mergeable;
857f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
858f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
859f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setDetailedOnly (final boolean detailedOnly)
860f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
861f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_detailedOnly = detailedOnly;
862f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
863f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
864f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setPattern (final boolean pattern)
865f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
866f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_pattern = pattern;
867f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
868f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
869f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setValueCardinality (final int [] cardinality)
870f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
871f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((cardinality == null) || (cardinality.length != 2)) throw new IllegalArgumentException ("null or invalid input: cardinality");
872f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
873f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_valueCardinality = cardinality;
874f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
875f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
876f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setRequiresSet (final String [] names)
877f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
878f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (names == null) throw new IllegalArgumentException ("null input: names");
879f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
880f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_requiresSet = names.length > 0 ? names : null;
881f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
882f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
883f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setExcludesSet (final String [] names)
884f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
885f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (names == null) throw new IllegalArgumentException ("null input: names");
886f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
887f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_excludesSet = names.length > 0 ? names : null;
888f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
889f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
890f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void setDescription (final String description)
891f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
892f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (description == null) throw new IllegalArgumentException ("null input: description");
893f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
894f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_description = description;
895f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
896f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
897f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
898f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int [] C_ZERO = new int [] {0, 0};
899f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int [] C_ONE = new int [] {1, 1};
900f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int [] C_ZERO_OR_ONE = new int [] {0, 1};
901f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int [] C_ZERO_OR_MORE = new int [] {0, Integer.MAX_VALUE};
902f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int [] C_ONE_OR_MORE = new int [] {1, Integer.MAX_VALUE};
903f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
904f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
905f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final boolean m_usage;
906f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private String [] m_names;
907f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private boolean m_required;
908f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private String m_valueMnemonic;
909f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private boolean m_mergeable;
910f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private boolean m_detailedOnly;
911f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private boolean m_pattern;
912f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private int [] m_valueCardinality;
913f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private String [] m_requiresSet, m_excludesSet;
914f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private String m_description;
915f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
916f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
917f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
918f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
919f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    static final class OptDefMetadata
920f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
921f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        OptDefMetadata ()
922f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
923f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_optdefs = new ArrayList ();
924f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_optdefMap = new HashMap ();
925f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_requiredOpts = new HashSet ();
926f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_patternOptDefMap = new HashMap ();
927f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
928f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
929f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        OptDef getOptDef (final String name, final String [] prefixout)
930f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
931f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (name == null) throw new IllegalArgumentException ("null input: name");
932f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
933f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (prefixout != null) prefixout [0] = null;
934f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
935f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // first, see if this is a regular option:
936f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            OptDef result = (OptDef) m_optdefMap.get (name);
937f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
938f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // next, see if this is a prefixed option:
939f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (result == null)
940f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
941f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (Iterator ps = m_patternOptDefMap.entrySet ().iterator ();
942f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     ps.hasNext (); )
943f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
944f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final Map.Entry entry = (Map.Entry) ps.next ();
945f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final String pattern = (String) entry.getKey ();
946f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
947f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (name.startsWith (pattern))
948f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
949f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (prefixout != null) prefixout [0] = pattern;
950f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        result = (OptDef) entry.getValue ();
951f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        break;
952f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
953f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
954f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
955f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
956f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return result;
957f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
958f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
959f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Iterator /* OptDef */ getOptDefs ()
960f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
961f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_optdefs.iterator ();
962f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
963f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
964f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        OptDef getPatternOptDefs (final String pattern) // returns null if no such pattern is defined
965f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
966f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (pattern == null) throw new IllegalArgumentException ("null input: pattern");
967f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
968f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return (OptDef) m_patternOptDefMap.get (pattern);
969f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
970f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
971f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Set /* String(canonical name) */ getRequiredOpts ()
972f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
973f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_requiredOpts;
974f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
975f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
976f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        OptDef getUsageOptDef ()
977f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
978f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_usageOptDef;
979f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
980f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
981f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void addOptDef (final OptDef optdef)
982f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
983f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (optdef == null) throw new IllegalArgumentException ("null input: optdef");
984f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
985f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Map map = optdef.isPattern () ? m_patternOptDefMap : m_optdefMap;
986f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] names = optdef.getNames ();
987f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
988f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int n = 0; n < names.length; ++ n)
989f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
990f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (map.containsKey (names [n]))
991f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new IllegalArgumentException ("duplicate option name [" + names [n] + "]");
992f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
993f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                map.put (names [n], optdef);
994f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
995f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
996f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_optdefs.add (optdef);
997f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
998f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (optdef.isRequired ())
999f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_requiredOpts.add (optdef.getCanonicalName ());
1000f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1001f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (optdef.isUsage ())
1002f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
1003f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (m_usageOptDef != null)
1004f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new IllegalArgumentException ("usage optdef set already");
1005f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1006f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_usageOptDef = optdef;
1007f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
1008f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1009f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1010f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1011f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final List /* OptDef */ m_optdefs; // keeps the addition order
1012f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final Map /* String(name)->OptDef */ m_optdefMap;
1013f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final Set /* String(canonical name) */ m_requiredOpts;
1014f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final Map /* String(pattern name)->OptDef */ m_patternOptDefMap;
1015f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private OptDef m_usageOptDef;
1016f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1017f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
1018f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1019f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1020f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    static final class MetadataParser
1021f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1022f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        /*
1023f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * metadata := ( optdef )* <EOF>
1024f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *
1025f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * optdef := optnamelist ":" optmetadata ";"
1026f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * optnamelist := namelist
1027f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * optmetadata :=
1028f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      ("optional" | "required" )
1029f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," "mergeable" ]
1030f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," "detailedonly" ]
1031f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," "pattern" ]
1032f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      "," "values" ":" cardinality
1033f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," name ]
1034f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," "requires" "{" namelist "}" ]
1035f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      [ "," "notwith" "{" namelist "}" ]
1036f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         *      "," text
1037f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * cardinality := "0" | "1" | "?"
1038f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * namelist := name ( "," name )*
1039f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * name := <single quoted string>
1040f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         * text := <double quoted string>
1041f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         */
1042f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         OptDef [] parse (final Reader in)
1043f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1044f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (in == null) throw new IllegalArgumentException ("null input: in");
1045f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             m_in = in;
1046f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1047f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             nextChar ();
1048f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             nextToken ();
1049f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1050f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             while (m_token != Token.EOF)
1051f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1052f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 if (m_opts == null) m_opts = new ArrayList ();
1053f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 m_opts.add (optdef ());
1054f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1055f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1056f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final OptDef [] result;
1057f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1058f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if ((m_opts == null) || (m_opts.size () == 0))
1059f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                result = EMPTY_OPTDEF_ARRAY;
1060f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             else
1061f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1062f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 result = new OptDef [m_opts.size ()];
1063f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 m_opts.toArray (result);
1064f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1065f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1066f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             m_in = null;
1067f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             m_opts = null;
1068f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1069f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return result;
1070f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1071f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1072f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         OptDef optdef ()
1073f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1074f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final OptDef optdef = new OptDef (false);
1075f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1076f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             optdef.setNames (optnamelist ());
1077f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.COLON_ID);
1078f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             optmetadata (optdef);
1079f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.SEMICOLON_ID);
1080f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1081f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return optdef;
1082f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1083f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1084f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         String [] optnamelist ()
1085f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1086f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return namelist ();
1087f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1088f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1089f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         void optmetadata (final OptDef optdef)
1090f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1091f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             switch (m_token.getID ())
1092f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1093f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case Token.REQUIRED_ID:
1094f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1095f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     accept ();
1096f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     optdef.setRequired (true);
1097f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1098f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1099f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case Token.OPTIONAL_ID:
1101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     accept ();
1103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     optdef.setRequired (false);
1104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 default:
1108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new IllegalArgumentException ("parse error: invalid token " + m_token + ", expected " + Token.REQUIRED + " or " + Token.OPTIONAL);
1109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             } // end of switch
1111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.COMMA_ID);
1113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.MERGEABLE_ID)
1115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setMergeable (true);
1118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.DETAILEDONLY_ID)
1123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setDetailedOnly (true);
1126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.PATTERN_ID)
1131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setPattern (true);
1134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.VALUES_ID);
1139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.COLON_ID);
1140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             optdef.setValueCardinality (cardinality ());
1141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             accept (Token.COMMA_ID);
1143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.STRING_ID)
1144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setValueMnemonic (m_token.getValue ());
1146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.REQUIRES_ID)
1152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.LBRACKET_ID);
1156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setRequiresSet (namelist ());
1157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.RBRACKET_ID);
1158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == Token.EXCLUDES_ID)
1163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.LBRACKET_ID);
1167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 optdef.setExcludesSet (namelist ());
1168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.RBRACKET_ID);
1169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept (Token.COMMA_ID);
1171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             optdef.setDescription (accept (Token.TEXT_ID).getValue ());
1174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         int [] cardinality ()
1177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final Token result = accept (Token.CARD_ID);
1179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if ("0".equals (result.getValue ()))
1181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return OptDef.C_ZERO;
1182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             else if ("1".equals (result.getValue ()))
1183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return OptDef.C_ONE;
1184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             else // ?
1185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return OptDef.C_ZERO_OR_ONE;
1186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         String [] namelist ()
1189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final List _result = new ArrayList ();
1191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             _result.add (accept (Token.STRING_ID).getValue ());
1193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             while (m_token.getID () == Token.COMMA_ID)
1194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 accept ();
1196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 _result.add (accept (Token.STRING_ID).getValue ());
1197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final String [] result = new String [_result.size ()];
1200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             _result.toArray (result);
1201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return result;
1203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         Token accept ()
1207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final Token current = m_token;
1209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             nextToken ();
1210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return current;
1212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         Token accept (final int tokenID)
1215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             final Token current = m_token;
1217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_token.getID () == tokenID)
1219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                nextToken ();
1220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             else
1221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new IllegalArgumentException ("parse error: invalid token [" + m_token + "], expected type [" + tokenID + "]");
1222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             return current;
1224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         // "scanner":
1227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         void nextToken ()
1229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             consumeWS ();
1231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             switch (m_currentChar)
1233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case -1: m_token = Token.EOF; break;
1235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case ':':
1237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = Token.COLON;
1240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case ';':
1244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = Token.SEMICOLON;
1247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case ',':
1251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = Token.COMMA;
1254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '{':
1258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = Token.LBRACKET;
1261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '}':
1265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = Token.RBRACKET;
1268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '0':
1272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = new Token (Token.CARD_ID, "0");
1275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '1':
1279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = new Token (Token.CARD_ID, "1");
1282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '?':
1286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = new Token (Token.CARD_ID, "?");
1289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '\'':
1293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     final StringBuffer value = new StringBuffer ();
1295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     while (m_currentChar != '\'')
1298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     {
1299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         value.append ((char) m_currentChar);
1300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         nextChar ();
1301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     }
1302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = new Token (Token.STRING_ID, value.toString ());
1305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 case '\"':
1309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     final StringBuffer value = new StringBuffer ();
1311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     while (m_currentChar != '\"')
1314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     {
1315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         value.append ((char) m_currentChar);
1316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         nextChar ();
1317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     }
1318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     nextChar ();
1319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = new Token (Token.TEXT_ID, value.toString ());
1321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 break;
1323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 default:
1325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     final StringBuffer value = new StringBuffer ();
1327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     while (Character.isLetter ((char) m_currentChar))
1329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     {
1330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         value.append ((char) m_currentChar);
1331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                         nextChar ();
1332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     }
1333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     final Token token = (Token) KEYWORDS.get (value.toString ());
1335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     if (token == null)
1336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("parse error: unrecognized keyword [" + value  + "]");
1337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                     m_token = token;
1339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             } // end of switch
1342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private void consumeWS ()
1346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             if (m_currentChar == -1)
1348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return;
1349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             else
1350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 while (Character.isWhitespace ((char) m_currentChar))
1352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 {
1353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    nextChar ();
1354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 }
1355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             // TODO: #-comments
1358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private void nextChar ()
1361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             try
1363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_currentChar = m_in.read ();
1365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             catch (IOException ioe)
1367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             {
1368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 throw new RuntimeException ("I/O error while parsing: " + ioe);
1369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             }
1370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private Reader m_in;
1374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private List m_opts;
1375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private Token m_token;
1377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private int m_currentChar;
1378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private static final Map KEYWORDS;
1380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         private static final OptDef [] EMPTY_OPTDEF_ARRAY = new OptDef [0];
1382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         static
1384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         {
1385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS = new HashMap (17);
1386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.OPTIONAL.getValue (), Token.OPTIONAL);
1388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.REQUIRED.getValue (), Token.REQUIRED);
1389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.VALUES.getValue (), Token.VALUES);
1390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.REQUIRES.getValue (), Token.REQUIRES);
1391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.EXCLUDES.getValue (), Token.EXCLUDES);
1392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.MERGEABLE.getValue (), Token.MERGEABLE);
1393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.DETAILEDONLY.getValue (), Token.DETAILEDONLY);
1394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project             KEYWORDS.put (Token.PATTERN.getValue (), Token.PATTERN);
1395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project         }
1396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
1398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    OptsParser (final String metadataResourceName, final ClassLoader loader, final String [] usageOpts)
1401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        this (metadataResourceName, loader, null, usageOpts);
1403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
1404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    OptsParser (final String metadataResourceName, final ClassLoader loader, final String msgPrefix, final String [] usageOpts)
1406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (metadataResourceName == null) throw new IllegalArgumentException ("null input: metadataResourceName");
1408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_msgPrefix = msgPrefix;
1410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        InputStream in = null;
1412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
1413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            in = ResourceLoader.getResourceAsStream (metadataResourceName, loader);
1415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (in == null)
1416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new IllegalArgumentException ("resource [" + metadataResourceName + "] could not be loaded via [" + loader + "]");
1417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // TODO: encoding
1419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Reader rin = new InputStreamReader (in);
1420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_metadata = parseOptDefMetadata (rin, usageOpts);
1422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        finally
1424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (in != null) try { in.close (); } catch (IOException ignore) {}
1426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
1428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
1430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class Token
1433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Token (final int ID, final String value)
1435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (value == null) throw new IllegalArgumentException ("null input: value");
1437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_ID = ID;
1439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_value = value;
1440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        int getID ()
1443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_ID;
1445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        String getValue ()
1448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_value;
1450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public String toString ()
1453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_ID + ": [" + m_value + "]";
1455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int EOF_ID = 0;
1459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int STRING_ID = 1;
1460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int COLON_ID = 2;
1461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int SEMICOLON_ID = 3;
1462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int COMMA_ID = 4;
1463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int LBRACKET_ID = 5;
1464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int RBRACKET_ID = 6;
1465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int OPTIONAL_ID = 7;
1466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int REQUIRED_ID = 8;
1467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int CARD_ID = 9;
1468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int VALUES_ID = 10;
1469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int TEXT_ID = 11;
1470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int REQUIRES_ID = 12;
1471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int EXCLUDES_ID = 13;
1472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int MERGEABLE_ID = 14;
1473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int DETAILEDONLY_ID = 15;
1474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final int PATTERN_ID = 16;
1475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token EOF = new Token (EOF_ID, "<EOF>");
1477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token COLON = new Token (COLON_ID, ":");
1478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token SEMICOLON = new Token (SEMICOLON_ID, ";");
1479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token COMMA = new Token (COMMA_ID, ",");
1480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token LBRACKET = new Token (LBRACKET_ID, "{");
1481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token RBRACKET = new Token (RBRACKET_ID, "}");
1482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token OPTIONAL = new Token (OPTIONAL_ID, "optional");
1483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token REQUIRED = new Token (REQUIRED_ID, "required");
1484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token VALUES = new Token (VALUES_ID, "values");
1485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token REQUIRES = new Token (REQUIRES_ID, "requires");
1486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token EXCLUDES = new Token (EXCLUDES_ID, "excludes");
1487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token MERGEABLE = new Token (MERGEABLE_ID, "mergeable");
1488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token DETAILEDONLY = new Token (DETAILEDONLY_ID, "detailedonly");
1489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        static final Token PATTERN = new Token (PATTERN_ID, "pattern");
1490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final int m_ID;
1492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final String m_value;
1493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
1495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static OptDefMetadata parseOptDefMetadata (final Reader in, final String [] usageOpts)
1498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final MetadataParser parser = new MetadataParser ();
1500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final OptDef [] optdefs = parser.parse (in);
1501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // validate:
1503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        for (int o = 0; o < optdefs.length; ++ o)
1505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        {
1506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            final OptDef optdef = optdefs [o];
1507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            final int [] cardinality = optdef.getValueCardinality ();
1508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
1509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            if (optdef.isMergeable ())
1510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            {
1511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                if ((cardinality [1] != 0) && (cardinality [1] != Integer.MAX_VALUE))
1512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] is mergeable and can only specify {0, +inf} for max value cardinality: " + cardinality [1]);
1513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            }
1514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        }
1515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final OptDefMetadata result = new OptDefMetadata ();
1517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int o = 0; o < optdefs.length; ++ o)
1518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            result.addOptDef (optdefs [o]);
1520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // add usage opts:
1523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (usageOpts != null)
1524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final OptDef usage = new OptDef (true);
1526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setNames (usageOpts);
1528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setDescription ("display usage information");
1529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setValueCardinality (OptDef.C_ZERO);
1530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setRequired (false);
1531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setDetailedOnly (false);
1532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            usage.setMergeable (false);
1533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            result.addOptDef (usage);
1535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: fix this to be pattern-savvy
1538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int o = 0; o < optdefs.length; ++ o)
1540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final OptDef optdef = optdefs [o];
1542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] requires = optdef.getRequiresSet ();
1544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (requires != null)
1545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
1546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int r = 0; r < requires.length; ++ r)
1547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
1548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final OptDef ropt = result.getOptDef (requires [r], null);
1549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (ropt == null)
1550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] specifies an unknown option [" + requires [r] + "] in its \'requires\' set");
1551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (ropt == optdef)
1553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] specifies itself in its \'requires\' set");
1554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
1555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
1556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] excludes = optdef.getExcludesSet ();
1558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (excludes != null)
1559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
1560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int x = 0; x < excludes.length; ++ x)
1561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
1562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final OptDef xopt = result.getOptDef (excludes [x], null);
1563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (xopt == null)
1564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] specifies an unknown option [" + excludes [x] + "] in its \'excludes\' set");
1565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (xopt.isRequired ())
1567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] specifies a required option [" + excludes [x] + "] in its \'excludes\' set");
1568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (xopt == optdef)
1570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new IllegalArgumentException ("option [" + optdef.getCanonicalName () + "] specifies itself in its \'excludes\' set");
1571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
1572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
1573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return result;
1576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
1577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private String formatMessage (final String msg)
1579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
1580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_msgPrefix == null) return msg;
1581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
1582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
1583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_msgPrefix.concat (msg);
1584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
1585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
1586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final String m_msgPrefix;
1589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final OptDefMetadata m_metadata;
1590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int CANONICAL_OPT_PREFIX = 1; // indexes into OPT_PREFIXES
1592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final String [] OPT_PREFIXES = new String [] {"--", "-"}; // HACK: these must appear in decreasing length order
1593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final char [] OPT_VALUE_SEPARATORS = new char [] {':', '='};
1594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int STATE_OPT = 0, STATE_OPT_VALUE = 1, STATE_FREE_ARGS = 2, STATE_ERROR = 3;
1596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
1597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
1598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------