com.codename1.util.StringUtil Java Examples

The following examples show how to use com.codename1.util.StringUtil. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AI.java    From codenameone-demos with GNU General Public License v2.0 6 votes vote down vote up
private String getResponseToQuestion(String question) {
    if(has(question, BAD_WORDS)) {
        return CANT_ABIDE_SUCH_LANGUAGE;
    }
    
    if(question.startsWith("please")) {
        return "You don't have to be so polite";
    }
    
    if(question.startsWith("say ")) {
        return question.substring(4);
    }
    
    if(question.length() < 6) {
        return TOO_LITTLE_DATA_PLEASE_TELL_ME_MORE;
    }
    
    List<String> tokens = StringUtil.tokenize(question, " .,;\"':-?!-_");
    return WHY_ARE_YOU_CONCERNED + tokens.get(tokens.size() - 1);
}
 
Example #2
Source File: ParseBatch.java    From parse4cn1 with Apache License 2.0 6 votes vote down vote up
/**
 * Adds multiple objects to the batch to be {@link #execute() executed}.
 *
 * @param objects The objects to be added to the batch.
 * @param opType The type of operation to be performed on ALL
 * {@code objects}.
 * @return {@code this} to enable chaining.
 * @throws ParseException if any of the objects does not meet the
 * constraints for {@code opType}, for example, an objectId is required for
 * {@link EBatchOpType#UPDATE} and {@link EBatchOpType#DELETE} but should
 * not exist for {@link EBatchOpType#CREATE}. because it already has an
 * objectId.
 */
public ParseBatch addObjects(final Collection<? extends ParseObject> objects,
        final EBatchOpType opType) throws ParseException {

    final String urlPath =  StringUtil.replaceAll(Util.getURLPath(Parse.getApiEndpoint()), "/", "");
    final String pathPrefix = "/" + (!Parse.isEmpty(urlPath) ? urlPath + "/" : "");

    final String method = opTypeToHttpMethod(opType);
    
    for (ParseObject object : objects) {
        validate(object, opType);
        final JSONObject objData = new JSONObject();
        try {
            objData.put("method", method);
            objData.put("path", pathPrefix + getObjectPath(object, opType));
            objData.put("body", object.getParseData());
        } catch (JSONException ex) {
            throw new ParseException(ParseException.INVALID_JSON, 
                    ParseException.ERR_PREPARING_REQUEST, ex);
        }
        data.put(objData);
        parseObjects.add(object);
    }
    return this;
}
 
Example #3
Source File: URITests.java    From CodenameOne with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean runTest() throws Exception {
    FileSystemStorage fs = FileSystemStorage.getInstance();
    String home = fs.getAppHomePath();
    if (!home.endsWith(fs.getFileSystemSeparator()+"")) {
        home += fs.getFileSystemSeparator();
    }
    String homePath = home.substring(6);
    homePath = StringUtil.replaceAll(homePath, "\\", "/");
    while(homePath.startsWith("/")) {
        homePath = homePath.substring(1);
    }
    homePath = "/" + homePath;
    com.codename1.io.URL url = new com.codename1.io.File("hello world.txt").toURL();
    
    //https://en.wikipedia.org/wiki/File_URI_scheme
    assertTrue(url.toString().startsWith("file:/"), "URL should start with file:///");
    assertEqual("file:"+homePath+"hello%20world.txt", url.toString(), "URL failed to encode space in file name");
    
    
    URI uri = new com.codename1.io.File("hello world.txt").toURI();
    assertEqual("file:"+homePath+"hello%20world.txt", uri.toString(), "URI failed to encode space in file name");
    assertEqual(homePath+"hello world.txt", uri.getPath(), "Incorrect URI path");
    return true;

}
 
Example #4
Source File: FacebookRESTService.java    From CodenameOne with GNU General Public License v2.0 6 votes vote down vote up
protected void setQuery(String query) {
    if (query.indexOf("?") > 0) {
        String search = query.substring(query.indexOf("?")+1);
        query = query.substring(0, query.indexOf("?"));
        java.util.List<String> parts = StringUtil.tokenize(search, "&");
        for (String part : parts) {
            java.util.List<String> kv = StringUtil.tokenize(part, "=");
            addArgumentNoEncoding(kv.get(0), kv.size()>1 ?kv.get(1):"");
        }
    }
    String url = GRAPH_URL + query;
    if(FaceBookAccess.getApiVersion().length() > 0){
        url = GRAPH_URL + FaceBookAccess.getApiVersion() + "/" + query;
    }
    setUrl(url);
}
 
Example #5
Source File: JavascriptContext.java    From CodenameOne with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Sets a Javascript value given a compatible Java object value asynchronously.
 * @param key A Javascript expression whose result is being assigned the value.
 * @param value The object or value that is being assigned to the Javascript variable
 * on the left.
 * @see #set(java.lang.String, java.lang.Object) 
 */
public void setAsync(String key, Object value) {
    String lhs = key;
    String rhs = "undefined";
  
    if ( String.class.isInstance(value)){
        String escaped = StringUtil.replaceAll((String)value, "\\", "\\\\");
        escaped = StringUtil.replaceAll(escaped, "'", "\\'");
        rhs = "'"+escaped+"'";
    } else if ( value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double ){
        rhs =value.toString();
    } else if ( JSObject.class.isInstance(value)){
        rhs = ((JSObject)value).toJSPointer();
    } else if (value instanceof Boolean){
        rhs = ((Boolean)value).booleanValue()?"true":"false";
    } else {
        rhs = "null";
    }
    
    exec(lhs+"="+rhs, true);
}
 
Example #6
Source File: UnitTests.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean runTest() throws Exception {
    String testStr = "1,2,3,,,,,,5,6,3";
    String expected = "[1, 2, 3, 5, 6, 3]";
    //StringTokenizer strtok = new StringTokenizer(testStr, ",");
    //List<String> toks = new ArrayList<>();
    //while (strtok.hasMoreTokens()) {
    //    toks.add(strtok.nextToken());
    //}

    List<String> toks2 = StringUtil.tokenize(testStr, ",");
    assertEqual(expected, toks2.toString());
    return true;
    
}
 
Example #7
Source File: Storage.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * If a file name contains slashes replace them with underscores, same goes for *, %, ? etc.
 * @param name the file name
 * @return the fixed filename
 */
private String fixFileName(String name) {
    if(normalizeNames) {
        name = StringUtil.replaceAll(name, "/", "_");
        name = StringUtil.replaceAll(name, "\\", "_");
        name = StringUtil.replaceAll(name, "%", "_");
        name = StringUtil.replaceAll(name, "?", "_");
        name = StringUtil.replaceAll(name, "*", "_");
        name = StringUtil.replaceAll(name, ":", "_");
        name = StringUtil.replaceAll(name, "=", "_");            
    }
    return name;
}
 
Example #8
Source File: File.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Converts this file to a URI.
 * @return
 * @throws URISyntaxException 
 */
public URI toURI() throws URISyntaxException {
    String path = getAbsolutePath();
    path = path.substring(6);
    path = StringUtil.replaceAll(path, "\\", "/");
    while (path.startsWith("/")) {
        path = path.substring(1);
    }
    path = "/" + path;
    return new URI("file", null, path, null, null);
    
    
}
 
Example #9
Source File: ConnectionRequest.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param url the url to set
 */
public void setUrl(String url) {
    if(url.indexOf(' ') > -1) {
        url = StringUtil.replaceAll(url, " ", "%20");
    }
    url = url.intern();
    this.url = url;
}
 
Example #10
Source File: ProxyHttpTile.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Creates an Http Tile
 * 
 * @param tileSize the tile size
 * @param bbox the tile bounding box
 * @param url the url to bring the image from
 */
public ProxyHttpTile(Dimension tileSize, BoundingBox bbox, final String url) {
    super(tileSize, bbox, null);
    _url = url;
    String cacheId = url.substring(url.indexOf(":")+1);
    cacheId = StringUtil.replaceAll(cacheId, "\\", "_");
    cacheId = StringUtil.replaceAll(cacheId, "/", "_");
    cacheId = StringUtil.replaceAll(cacheId, ".", "_");
    cacheId = StringUtil.replaceAll(cacheId, "?", "_");
    cacheId = StringUtil.replaceAll(cacheId, "&", "_");
    
    ImageDownloadService.createImageToStorage(url, new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            NetworkEvent ne = (NetworkEvent) evt;

            Image i = (Image) ne.getMetaData();
            i.lock();
            _tile = new Tile(ProxyHttpTile.this.dimension(),
                    ProxyHttpTile.this.getBoundingBox(),
                    i);
            ProxyHttpTile.this.fireReady();
        }
    }, cacheId, true);


}
 
Example #11
Source File: UIManager.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
private String[][] tokenizeMultiArray(String s, char separator, char lineBreak) {
    Vector lines = StringUtil.tokenizeString(s, lineBreak);
    int lineCount = lines.size();
    String[][] result = new String[lineCount][];
    for(int iter = 0 ; iter < lineCount ; iter++) {
        String currentString = (String)lines.elementAt(iter);
        result[iter] = toStringArray(StringUtil.tokenizeString(currentString, separator));
    }
    return result;
}
 
Example #12
Source File: UIManager.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
private Hashtable parseTextFieldInputMode(String s) {
    Vector tokens = StringUtil.tokenizeString(s, '|');
    Hashtable response = new Hashtable();
    int count = tokens.size();
    for(int iter = 0 ; iter < count ; iter++) {
        String t = (String)tokens.elementAt(iter);
        int pos = t.indexOf('=');
        String key = t.substring(0, pos);
        String val = t.substring(pos + 1);
        response.put(Integer.valueOf(key), val);
    }
    return response;
}
 
Example #13
Source File: UIManager.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * The resource bundle allows us to implicitly localize the UI on the fly, once its
 * installed all internal application strings query the resource bundle and extract
 * their values from this table if applicable.
 * 
 * @param resourceBundle the localization bundle
 */
public void setBundle(Map<String, String> bundle) {
    if(localeAccessible) {
        this.bundle = bundle;
        if(bundle != null) {
            String v = (String)bundle.get("@rtl");
            if(v != null) {
                getLookAndFeel().setRTL(v.equalsIgnoreCase("true"));
                
                // update some "bidi sensitive" variables in the LaF
                current.refreshTheme(false);
            }
            String textFieldInputMode = (String)bundle.get("@im");
            if(textFieldInputMode != null && textFieldInputMode.length() > 0) {
                String[] tokenized = toStringArray(StringUtil.tokenizeString(textFieldInputMode, '|'));
                TextField.setDefaultInputModeOrder(tokenized);
                int tlen = tokenized.length;
                for(int iter = 0 ; iter < tlen; iter++) {
                    String val = tokenized[iter];
                    String actual = (String)bundle.get("@im-" + val);
                    // val can be null for builtin input mode types...
                    if(actual != null) {
                        TextField.addInputMode(val, parseTextFieldInputMode(actual), Character.isUpperCase(val.charAt(0)));
                    }
                }
            }
        }
    }
}
 
Example #14
Source File: BrowserComponent.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Injects parameters into a Javascript string expression.  This will quote strings properly.  The 
 *  expression should include placeholders for each parameter of the form ${0}, ${1}, etc..
 * @param jsExpression The javascript expression with placeholders to inject parameters.
 * @param params
 * @return The expression with placeholders replaced by parameters.
 */
public static String injectParameters(String jsExpression, Object... params) {
    int i=0;
    for (Object param : params) {
        
        String pattern = "${"+i+"}";
        if (param == null) {
            jsExpression = StringUtil.replaceAll(jsExpression, pattern, "null");
        } else if (param instanceof String) {
            jsExpression = StringUtil.replaceAll(jsExpression, pattern, quote((String)param));
        } else if (param instanceof JSProxy) {
            jsExpression = StringUtil.replaceAll(jsExpression, pattern, ((JSProxy)param).self);
        } else if (param instanceof JSExpression) {
            jsExpression = ((JSExpression)param).expression;
        } else if (param instanceof JSRef) {
            JSRef jsr = (JSRef)param;
            if (jsr.isNull()) {
                jsExpression = StringUtil.replaceAll(jsExpression, pattern, "null");
            } else if (jsr.getJSType() == JSType.STRING) {
                jsExpression = StringUtil.replaceAll(jsExpression, pattern, quote((String)jsr.getValue()));
            } else if (jsr.getJSType() == JSType.FUNCTION || jsr.getJSType() == JSType.OBJECT) {
                throw new IllegalArgumentException("Cannot inject JSRefs of functions or objects as parameters in JS expressions");
            } else {
                jsExpression = StringUtil.replaceAll(jsExpression, pattern, jsr.getValue());
            }
        } else {
            jsExpression = StringUtil.replaceAll(jsExpression, pattern, String.valueOf(param));
        }
        i++;
    }
    return jsExpression;
}
 
Example #15
Source File: ConstraintParser.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Parses "AAA[BBB]CCC[DDD]EEE" into {"AAA", "BBB", "CCC", "DDD", "EEE",
 * "FFF"}. Handles empty parts. Will always start and end outside a [] block
 * so that the number of returned elemets will always be uneven and at least
 * of length 3.
 * <p>
 * "|" is interpreted as "][".
 *
 * @param s The string. Might be "" but not null. Should be trimmed.
 * @return The string divided into elements. Never <code>null</code> and at
 * least of length 3.
 * @throws IllegalArgumentException If a [] mismatch of some kind. (If not
 * same [ as ] count or if the interleave.)
 */
private static ArrayList<String> getRowColAndGapsTrimmed(String s) {
    if (s.indexOf('|') != -1) {
        s = StringUtil.replaceAll(s, "\\|", "][");
    }

    ArrayList<String> retList = new ArrayList<String>(Math.max(s.length() >> 2 + 1, 3)); // Approx return length.
    int s0 = 0, s1 = 0; // '[' and ']' count.
    int st = 0; // Start of "next token to add".
    for (int i = 0, iSz = s.length(); i < iSz; i++) {
        char c = s.charAt(i);
        if (c == '[') {
            s0++;
        } else if (c == ']') {
            s1++;
        } else {
            continue;
        }

        if (s0 != s1 && (s0 - 1) != s1) {
            break;  // Wrong [ or ] found. Break for throw.
        }
        retList.add(s.substring(st, i).trim());
        st = i + 1;
    }
    if (s0 != s1) {
        throw new IllegalArgumentException("'[' and ']' mismatch in row/column format string: " + s);
    }

    if (s0 == 0) {
        retList.add("");
        retList.add(s);
        retList.add("");
    } else if (retList.size() % 2 == 0) {
        retList.add(s.substring(st, s.length()));
    }

    return retList;
}
 
Example #16
Source File: XMLWriter.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
private String encodeIfRequired(String text) {
    if (encodeText) {
        int elen = escapes.length;
        for (int i = 0; i < elen; i++) {
            text = StringUtil.replaceAll(text, escapes[i][0], escapes[i][1]);
        }
    }
    return text;
}
 
Example #17
Source File: JSObject.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Constructor for a JSObject.
 * 
 * <h5>Example</h5>
 * 
 * <code><pre>
 * // Create a JavascriptContext for a browser component
 * JavascriptContext ctx = new JavascriptContext(browserComponent);
 * 
 * // Get reference to the window object
 * JSObject window = new JSObject(ctx, "window");
 * 
 * // This is equivalent to
 * window = (JSObject)ctx.get("window");
 * 
 * </pre></code>
 * @param context The javascript context in which this object is being created.
 * 
 * @param expr A javascript expression that resolves to a Javascript Object.
 */
public JSObject(JavascriptContext context, String expr) {
    this.context = context;
    synchronized (context.browser){
        String escaped = StringUtil.replaceAll(expr, "\\", "\\\\");
        escaped = StringUtil.replaceAll(escaped, "'", "\\'");
        exec(R1+"=eval('"+escaped+"')");
        String type = exec("typeof("+R1+")");
        if ( !"object".equals(type) && !"function".equals(type)){
            throw new JSException("Attempt to create JSObject for expression "+expr+" which does not evaluate to an object.");
        }
        
        String lt = context.jsLookupTable;
        String js = "var id = "+R1+"."+ID_KEY+"; "+
                    "if (typeof(id)=='undefined' || typeof("+lt+"[id]) == 'undefined' || "+lt+"[id]."+ID_KEY+"!=id){"+
                        lt+".push("+R1+"); id="+lt+".indexOf("+R1+"); Object.defineProperty("+R1+",\""+ID_KEY+"\",{value:id, enumerable:false});"+
                        "Object.defineProperty("+R1+",\""+PROP_REFCOUNT+"\",{value:1, enumerable:false});"+
                    "} else { "+
                        R1+"."+PROP_REFCOUNT+"++;"+
                    "} id";
        
       
        String id = exec(js);
        this.objectId = Integer.parseInt(id);
        context.retain(this); 
    }
}
 
Example #18
Source File: AbstractEvaluator.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Utility method for subclasses to convert a string to an array, delimited
 * by comma, optionally enclosed in brackets, and elements optionally
 * enclosed in quotes.
 *
 * @param text value to transform
 * @return the value as an array.
 */
protected String[] explode(String arrayAsString) {
    arrayAsString = arrayAsString.trim();
    if (arrayAsString.startsWith("(") && arrayAsString.endsWith(")")) {
        arrayAsString = arrayAsString.substring(1, arrayAsString.length() - 1);
    }
    List v = StringUtil.tokenizeString(arrayAsString, ',');
    String a[] = new String[v.size()];
    for (int i = 0; i < v.size(); i++) {
        a[i] = stripQuotes(v.get(i).toString().trim());
    }
    return a;
}
 
Example #19
Source File: EditableResources.java    From CodenameOne with GNU General Public License v2.0 5 votes vote down vote up
private String encodeXML(String text) {
    
    int elen = escapes.length;
    for (int i = 0; i < elen; i++) {
        text = StringUtil.replaceAll(text, escapes[i][0], escapes[i][1]);
    }
    
    return text;
}
 
Example #20
Source File: JavascriptContext.java    From CodenameOne with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Sets a Javascript value given a compatible Java object value.  This is an abstraction
 * upon javascript to execute <code>key = value</code>.
 * 
 * <p>The key is any Javascript expression whose result can be assigned. The value
 * is a Java object that will be converted into a Javascript object as follows:</p>
 * 
 * <table>
 *  <thead>
 *      <tr><th>Java type</th><th>Converted to</th></tr>
 *  </thead>
 *  <tbody>
 *      <tr><td>Double</td><th>Number</td></tr>
 *      <tr><td>Integer</td><th>Number</td><tr>
 *      <tr><td>Float</td><td>Number</td></tr>
 *      <tr><td>Long</td><td>Number</td></tr>
 *      <tr><td>String</td><td>String</td></tr>
 *      <tr><td>JSObject</td><td>Object by ref</td></tr>
 *      <tr><td>null</td><td>null</td></tr>
 *  </tbody>
 * </table>
 * 
 * <p>Hence if you want to set a Javascript string value, you can just
 * pass a Java string into this method and it will be converted. </p>
 * 
 * <h5>JSObject "By Ref"</h5>
 * <p>You may notice that if you pass a JSObject as the value parameter, the 
 * table above indicates that it is passed by reference.  A JSObject merely 
 * stores a reference to a Javascript object from a lookup table in the 
 * Javascript runtime environment.  It is this lookup that is ultimately 
 * assigned to the "key" when you pass a JSObject as the value.   This has
 * the effect of setting the actual Javascript Object to this value, which
 * is effectively a pass-by-reference scenario.</p>
 * 
 * <h5>Examples</h5>
 * 
 * <code><pre>
 * // Set the window.location.href to a new URL
 * ctx.set("window.location.href", "http://google.com");
 * 
 * // Create a new JSObject, and set it as a property of another JSObject
 * JSObject camera = (JSObject)ctx.get("{}");
 * ctx.set("window.camera", camera);
 * 
 * // Set the name of the camera via JSObject.set()
 * camera.set("name", "My Camera");
 * 
 * // Get the camera's name via Javascript
 * String cameraName = (String)ctx.get("window.camera.name");
 *     // Should be "My Camera"
 * 
 * // Set the camera name via context.set()
 * ctx.set("camera.name", "New name");
 * 
 * String newName = (String)camera.get("name");
 *     // Should be "New name"
 * 
 * </pre></code>
 * @param key A Javascript expression whose result is being assigned the value.
 * @param value The object or value that is being assigned to the Javascript variable
 * on the left.
 */
public void set(String key, Object value){
    synchronized(browser) {


        String lhs = key;
        String rhs = "undefined";
        if ( String.class.isInstance(value)){
            String escaped = StringUtil.replaceAll((String)value, "\\", "\\\\");
            escaped = StringUtil.replaceAll(escaped, "'", "\\'");
            rhs = "'"+escaped+"'";
        } else if ( value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double ){
            rhs =value.toString();
        } else if ( JSObject.class.isInstance(value)){
            rhs = ((JSObject)value).toJSPointer();
        } else if (value instanceof Boolean){
            rhs = ((Boolean)value).booleanValue()?"true":"false";
        } else {
            rhs = "null";
        }

        exec(lhs+"="+rhs);
    }
}
 
Example #21
Source File: GameCanvasImplementation.java    From CodenameOne with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @inheritDoc
 */
public String[] getHeaderFields(String name, Object connection) throws IOException {
    HttpConnection c = (HttpConnection)connection;
    Vector r = new Vector();
    int i = 0;
    while (c.getHeaderFieldKey(i) != null) {
        if (c.getHeaderFieldKey(i).equalsIgnoreCase(name)) {
            String val = c.getHeaderField(i);
            //some J2ME devices such as Nokia send all the cookies in one 
            //header spereated by commas
            if(name.equalsIgnoreCase("Set-Cookie")){
                //it is not possible to simply tokenize on comma, because 
                //the expiration date of each cookie contains a comma, therefore 
                //we temporary remove this comma tokenize all the cookies and then 
                //fixing the comma in the expiration date
                String cookies = "";
                Vector v = StringUtil.tokenizeString(val, ';');
                for (int j = 0; j < v.size(); j++) {
                    String keyval = (String) v.elementAt(j);
                    if(keyval.indexOf("expires") > -1){
                        keyval = StringUtil.replaceAll(keyval, ",", "@__@");
                    }
                    cookies += keyval + ";";
                }
                cookies = cookies.substring(0, cookies.length() - 1);
                
                if(cookies.indexOf(",") > -1){
                   Vector v2 = StringUtil.tokenizeString(cookies, ',');
                    for (int j = 0; j < v2.size(); j++) {
                        String value = (String) v2.elementAt(j);
                        value = StringUtil.replaceAll(value, "@__@", ",");
                        r.addElement(value);
                    }
                }
            }else{
                r.addElement(val);
            }
        }
        i++;
    }
    
    if(r.size() == 0) {
        return null;
    }
    String[] response = new String[r.size()];
    for(int iter = 0 ; iter < response.length ; iter++) {
        response[iter] = (String)r.elementAt(iter);
    }
    return response;
}
 
Example #22
Source File: PopulationData.java    From codenameone-demos with GNU General Public License v2.0 4 votes vote down vote up
public void load(InputStream is) throws IOException {
    CSVParser parser = new CSVParser();
    String[][] pdata = parser.parse(is);
    String[] headings = null;
    int len=0;
    List<RegionData> tempRegionData = new ArrayList<RegionData>();
    Map<String,RegionData> tempYearRegionData = new HashMap<String,RegionData>();
    for (String[] row : pdata){
        if (headings == null){
            headings = row;
            len = headings.length;
        } else {
            Log.p("Processing row "+Arrays.toString(row));
            if ( row.length == 0){
                continue;
            }
            tempRegionData.clear();
            tempYearRegionData.clear();
            String region = row[0];
            
            
            for (int i=1; i<len; i++){
                RegionData d = null;
                
                List<String> parts = StringUtil.tokenize(headings[i], '_');
                
                int year = Integer.parseInt(parts.get(0));
                
                if (tempYearRegionData.containsKey(""+year)){
                    d = tempYearRegionData.get(""+year);
                } else {
                    d = new RegionData();
                    d.region = region;
                    d.year = year;
                    tempYearRegionData.put(""+year, d);
                }
                
                String type = parts.get(1);
                row[i] = StringUtil.replaceAll(row[i], ",", "");
                if (!"".equals(row[i])){
                    if ("POPULATION".equals(type)){
                        d.pop = Integer.parseInt(row[i]);
                    } else if ("DENSITY".equals(type)){
                        d.density = Double.parseDouble(row[i]);
                    } else if ("RANK".equals(type)){
                        d.rank = Integer.parseInt(row[i]);
                    } else {
                        throw new RuntimeException("Unexpected col heading.  Expecting POPULATION, DENSITY, or RANK, but found "+type);
                    }
                    
                }
                if (!tempRegionData.contains(d)){
                    tempRegionData.add(d);
                }
                
            }
            data.put(region, tempRegionData.toArray(new RegionData[tempRegionData.size()]));
        }
    }
}