// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.components.runtime.util;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import gnu.lists.LList;
import gnu.lists.Pair;
import org.json.JSONException;
import java.util.Collection;
import java.util.List;
import android.util.Log;
/**
* The YailList is a wrapper around the gnu.list.Pair class used
* by the Kawa framework. YailList is the main list primitive used
* by App Inventor components.
*
*/
public class YailList extends Pair {
private static final String LOG_TAG = "YailList";
// Component writers take note!
// If you want to pass back a list to the blocks language, the
// straightforward way to do this is simply to pass
// back an ArrayList. If you construct a YailList to return
// to codeblocks, you must guarantee that the elements of the list
// are "sanitized". That is, you must pass back a tree whose
// subtrees are themselves YailLists, and whose leaves are all
// legitimate Yail data types. See the definition of sanitization
// in runtime.scm.
/**
* Create an empty YailList.
*/
public YailList() {
super(YailConstants.YAIL_HEADER, LList.Empty);
}
private YailList(Object cdrval) {
super(YailConstants.YAIL_HEADER, cdrval);
}
/**
* Create an empty YailList YailList from an array.
*/
public static YailList makeEmptyList() {
return new YailList();
}
/**
* Create a YailList from an array.
*/
public static YailList makeList(Object[] objects) {
LList newCdr = Pair.makeList(objects, 0);
return new YailList(newCdr);
}
/**
* Create a YailList from a List.
*/
public static YailList makeList(List vals) {
LList newCdr = Pair.makeList(vals);
return new YailList(newCdr);
}
/**
* Create a YailList from a Collection.
*/
public static YailList makeList(Collection vals) {
LList newCdr = Pair.makeList(vals.toArray(), 0);
return new YailList(newCdr);
}
/**
* Return this YailList as an array.
*/
@Override
public Object[] toArray() {
if (cdr instanceof Pair) {
return ((Pair) cdr).toArray();
} else if (cdr instanceof LList) {
return ((LList) cdr).toArray();
} else {
throw new YailRuntimeError("YailList cannot be represented as an array", "YailList Error.");
}
}
/**
* Return this YailList as an array of Strings.
* In the case of numbers, we convert to strings using
* YailNumberToString for consistency with the
* other places where we convert Yail numbers for printing.
*/
public String[] toStringArray() {
int size = this.size();
String[] objects = new String[size];
for (int i = 1; i <= size; i++) {
objects[i - 1] = YailListElementToString(get(i));
}
return objects;
}
/**
* Convert a YailList element to a string. This is the same as
* toString except in the case of numbers, which we convert to strings using
* YailNumberToString for consistency with the
* other places where we convert Yail numbers for printing.
* @param element
* @return the string
*/
public static String YailListElementToString(Object element) {
if (Number.class.isInstance(element)) {
return YailNumberToString.format(((Number) element).doubleValue());
} else {
return String.valueOf(element);
}
}
/**
* Return a strictly syntactically correct JSON text
* representation of this YailList. Only supports String, Number,
* Boolean, YailList, FString and arrays containing these types.
*/
public String toJSONString() {
try {
StringBuilder json = new StringBuilder();
String separator = "";
json.append('[');
int size = this.size();
for (int i = 1; i <= size; i++) {
Object value = get(i);
json.append(separator).append(JsonUtil.getJsonRepresentation(value));
separator = ",";
}
json.append(']');
return json.toString();
} catch (JSONException e) {
throw new YailRuntimeError("List failed to convert to JSON.", "JSON Creation Error.");
}
}
/**
* Return the size of this YailList.
*/
@Override
public int size() {
return super.size() - 1;
}
/**
* Return a String representation of this YailList.
*/
@Override
public String toString() {
if (cdr instanceof Pair) {
return ((Pair) cdr).toString();
} else if (cdr instanceof LList) {
return ((LList) cdr).toString();
} else {
throw new RuntimeException("YailList cannot be represented as a String");
}
}
/**
* Return the String at the given index.
*/
public String getString(int index) {
return get(index + 1).toString();
}
/**
* Return the Object at the given index.
*/
public Object getObject(int index) {
return get(index + 1);
}
}