text:
package org.path.episample.android.provider;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang3.CharEncoding;
import org.kxml2.io.KXmlSerializer;
import org.kxml2.kdom.Document;
import org.kxml2.kdom.Element;
import org.kxml2.kdom.Node;
import org.opendatakit.aggregate.odktables.rest.ElementDataType;
import org.opendatakit.aggregate.odktables.rest.ElementType;
import org.opendatakit.aggregate.odktables.rest.KeyValueStoreConstants;
import org.opendatakit.aggregate.odktables.rest.TableConstants;
import org.path.common.android.data.ColumnDefinition;
import org.path.common.android.database.DatabaseConstants;
import org.path.common.android.database.DatabaseFactory;
import org.path.common.android.logic.PropertyManager;
import org.path.common.android.provider.DataTableColumns;
import org.path.common.android.provider.KeyValueStoreColumns;
import org.path.common.android.utilities.ODKDatabaseUtils;
import org.path.common.android.utilities.ODKFileUtils;
import org.path.common.android.utilities.TableUtil;
import org.path.common.android.utilities.WebLogger;
import org.path.episample.android.logic.DynamicPropertiesCallback;
import org.path.episample.android.utilities.EncryptionUtils;
import org.path.episample.android.utilities.EncryptionUtils.EncryptedFormInformation;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

/**
 * The WebKit does better if there is a content provider vending files to it.
 * This provider vends files under the Forms and Instances directories (only).
 *
 * @author mitchellsundt@gmail.com
 *
 */
public class SubmissionProvider extends ContentProvider {
  private static final String ISO8601_DATE_ONLY_FORMAT = "yyyy-MM-dd";
  private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";

  private static final String t = "SubmissionProvider";

  public static final String XML_SUBMISSION_AUTHORITY = "org.path.common.android.provider.submission.xml";
  public static final String JSON_SUBMISSION_AUTHORITY = "org.path.common.android.provider.submission.json";

  public static final String XML_SUBMISSION_URL_PREFIX = ContentResolver.SCHEME_CONTENT + "://"
      + SubmissionProvider.XML_SUBMISSION_AUTHORITY;
  public static final String JSON_SUBMISSION_URL_PREFIX = ContentResolver.SCHEME_CONTENT + "://"
      + SubmissionProvider.JSON_SUBMISSION_AUTHORITY;

  private static final String XML_OPENROSA_NAMESPACE = "http://openrosa.org/xforms";
  private static final String XML_DEFAULT_NAMESPACE = null; // "http://opendatakit.org/xforms";
  // // any
  // arbitrary
  // namespace
  private static final String NEW_LINE = "\n";

  private PropertyManager propertyManager;

  @Override
  public boolean onCreate() {
    propertyManager = new PropertyManager(getContext());
    return true;
  }

  @SuppressWarnings("unchecked")
  private static final void putElementValue(HashMap<String, Object> dataMap, ColumnDefinition defn,
      Object value) {
    List<ColumnDefinition> nesting = new ArrayList<ColumnDefinition>();
    ColumnDefinition cur = defn.getParent();
    while (cur != null) {
      nesting.add(cur);
      cur = cur.getParent();
    }

    HashMap<String, Object> elem = dataMap;
    for (int i = nesting.size() - 1; i >= 0; --i) {
      cur = nesting.get(i);
      if (elem.containsKey(cur.getElementName())) {
        elem = (HashMap<String, Object>) elem.get(cur.getElementName());
      } else {
        elem.put(cur.getElementName(), new HashMap<String, Object>());
        elem = (HashMap<String, Object>) elem.get(cur.getElementName());
      }
    }
    elem.put(defn.getElementName(), value);
  }

  @SuppressWarnings("unchecked")
  private static final int generateXmlHelper(Document d, Element data, int idx, String key,
      Map<String, Object> values, WebLogger log) {
    Object o = values.get(key);

    Element e = d.createElement(XML_DEFAULT_NAMESPACE, key);

    if (o == null) {
      log.e(t, "Unexpected null value");
    } else if (o instanceof Integer) {
      e.addChild(0, Node.TEXT, ((Integer) o).toString());
    } else if (o instanceof Double) {
      e.addChild(0, Node.TEXT, ((Double) o).toString());
    } else if (o instanceof Boolean) {
      e.addChild(0, Node.TEXT, ((Boolean) o).toString());
    } else if (o instanceof String) {
      e.addChild(0, Node.TEXT, ((String) o));
    } else if (o instanceof List) {
      StringBuilder b = new StringBuilder();
      List<Object> al = (List<Object>) o;
      for (Object ob : al) {
        if (ob instanceof Integer) {
          b.append(((Integer) ob).toString());
        } else if (ob instanceof Double) {
          b.append(((Double) ob).toString());
        } else if (ob instanceof Boolean) {
          b.append(((Boolean) ob).toString());
        } else if (ob instanceof String) {
          b.append(((String) ob));
        } else {
          throw new IllegalArgumentException("Unexpected type in XML submission serializer");
        }
        b.append(" ");
      }
      e.addChild(0, Node.TEXT, b.toString().trim());
    } else if (o instanceof Map) {
      // it is an object...
      Map<String, Object> m = (Map<String, Object>) o;
      int nidx = 0;

      ArrayList<String> entryNames = new ArrayList<String>();
      entryNames.addAll(m.keySet());
      Collections.sort(entryNames);
      for (String name : entryNames) {
        nidx = generateXmlHelper(d, e, nidx, name, m, log);
      }
    } else {
      throw new IllegalArgumentException("Unexpected object type in XML submission serializer");
    }
    data.addChild(idx++, Node.ELEMENT, e);
    data.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);
    return idx;
  }

  /**
   * The incoming URI is of the form:
   * ..../appName/tableId/instanceId?formId=&formVersion=
   *
   * where instanceId is the DataTableColumns._ID
   */
  @SuppressWarnings("unchecked")
  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    final boolean asXml = uri.getAuthority().equalsIgnoreCase(XML_SUBMISSION_AUTHORITY);

    if (mode != null && !mode.equals("r")) {
      throw new IllegalArgumentException("Only read access is supported");
    }

    // URI == ..../appName/tableId/instanceId?formId=&formVersion=

    List<String> segments = uri.getPathSegments();

    if (segments.size() != 4) {
      throw new IllegalArgumentException("Unknown URI (incorrect number of path segments!) " + uri);
    }

    final String appName = segments.get(0);
    ODKFileUtils.verifyExternalStorageAvailability();
    ODKFileUtils.assertDirectoryStructure(appName);
    WebLogger log = WebLogger.getLogger(appName);

    final String tableId = segments.get(1);
    final String instanceId = segments.get(2);
    final String submissionInstanceId = segments.get(3);

    SQLiteDatabase db = null;
    try {
      db = DatabaseFactory.get().getDatabase(getContext(), appName);

      boolean success = false;
      try {
        success = ODKDatabaseUtils.get().hasTableId(db, tableId);
      } catch (Exception e) {
        e.printStackTrace();
        throw new SQLException("Unknown URI (exception testing for tableId) " + uri);
      }
      if (!success) {
        throw new SQLException("Unknown URI (missing data table for tableId) " + uri);
      }

      final String dbTableName = "\"" + tableId + "\"";

      // Get the table properties specific to XML submissions

      String xmlInstanceName = null;
      String xmlRootElementName = null;
      String xmlDeviceIdPropertyName = null;
      String xmlUserIdPropertyName = null;
      String xmlBase64RsaPublicKey = null;

      try {

        Cursor c = null;
        try {
          c = db.query(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, new String[] {
              KeyValueStoreColumns.KEY, KeyValueStoreColumns.VALUE }, KeyValueStoreColumns.TABLE_ID
              + "=? AND " + KeyValueStoreColumns.PARTITION + "=? AND "
              + KeyValueStoreColumns.ASPECT + "=? AND " + KeyValueStoreColumns.KEY
              + " IN (?,?,?,?,?)", new String[] { tableId, KeyValueStoreConstants.PARTITION_TABLE,
              KeyValueStoreConstants.ASPECT_DEFAULT, KeyValueStoreConstants.XML_INSTANCE_NAME,
              KeyValueStoreConstants.XML_ROOT_ELEMENT_NAME,
              KeyValueStoreConstants.XML_DEVICE_ID_PROPERTY_NAME,
              KeyValueStoreConstants.XML_USER_ID_PROPERTY_NAME,
              KeyValueStoreConstants.XML_BASE64_RSA_PUBLIC_KEY }, null, null, null);
          if (c.getCount() > 0) {
            c.moveToFirst();
            int idxKey = c.getColumnIndex(KeyValueStoreColumns.KEY);
            int idxValue = c.getColumnIndex(KeyValueStoreColumns.VALUE);
            do {
              String key = c.getString(idxKey);
              String value = c.getString(idxValue);
              if (KeyValueStoreConstants.XML_INSTANCE_NAME.equals(key)) {
                xmlInstanceName = value;
              } else if (KeyValueStoreConstants.XML_ROOT_ELEMENT_NAME.equals(key)) {
                xmlRootElementName = value;
              } else if (KeyValueStoreConstants.XML_DEVICE_ID_PROPERTY_NAME.equals(key)) {
                xmlDeviceIdPropertyName = value;
              } else if (KeyValueStoreConstants.XML_USER_ID_PROPERTY_NAME.equals(key)) {
                xmlUserIdPropertyName = value;
              } else if (KeyValueStoreConstants.XML_BASE64_RSA_PUBLIC_KEY.equals(key)) {
                xmlBase64RsaPublicKey = value;
              }
            } while (c.moveToNext());
          }
        } finally {
          c.close();
          c = null;
        }

        ArrayList<ColumnDefinition> orderedDefns = TableUtil.get()
            .getColumnDefinitions(db, appName, tableId);

        // Retrieve the values of the record to be emitted...

        HashMap<String, Object> values = new HashMap<String, Object>();

        // issue query to retrieve the most recent non-checkpoint data record
        // for the instanceId
        StringBuilder b = new StringBuilder();
        b.append("SELECT * FROM ").append(dbTableName).append(" as T WHERE ")
            .append(DataTableColumns.ID).append("=?").append(" AND ")
            .append(DataTableColumns.SAVEPOINT_TYPE).append(" IS NOT NULL AND ")
            .append(DataTableColumns.SAVEPOINT_TIMESTAMP).append("=(SELECT max(V.")
                .append(DataTableColumns.SAVEPOINT_TIMESTAMP).append(") FROM ").append(dbTableName)
                   .append(" as V WHERE V.").append(DataTableColumns.ID).append("=T.")
                   .append(DataTableColumns.ID).append(" AND V.")
                   .append(DataTableColumns.SAVEPOINT_TYPE).append(" IS NOT NULL").append(")");

        String[] selectionArgs = new String[] { instanceId };
        FileSet freturn = new FileSet(appName);

        String datestamp = null;

        try {
          c = db.rawQuery(b.toString(), selectionArgs);
          b.setLength(0);

          if (c.moveToFirst() && c.getCount() == 1) {
            String rowETag = null;
            String filterType = null;
            String filterValue = null;
            String formId = null;
            String locale = null;
            String savepointType = null;
            String savepointCreator = null;
            String savepointTimestamp = null;
            String instanceName = null;

            // OK. we have the record -- work through all the terms
            for (int i = 0; i < c.getColumnCount(); ++i) {
              ColumnDefinition defn = null;
              String columnName = c.getColumnName(i);
              try {
                defn = ColumnDefinition.find(orderedDefns, columnName);
              } catch (IllegalArgumentException e) {
                // ignore...
              }
              if (defn != null && !c.isNull(i)) {
                if (xmlInstanceName != null && defn.getElementName().equals(xmlInstanceName)) {
                  instanceName = ODKDatabaseUtils.get().getIndexAsString(c, i);
                }
                // user-defined column
                ElementType type = defn.getType();
                ElementDataType dataType = type.getDataType();

                log.i(t, "element type: " + defn.getElementType());
                if (dataType == ElementDataType.integer) {
                  Integer value = ODKDatabaseUtils.get().getIndexAsType(c, Integer.class, i);
                  putElementValue(values, defn, value);
                } else if (dataType == ElementDataType.number) {
                  Double value = ODKDatabaseUtils.get().getIndexAsType(c, Double.class, i);
                  putElementValue(values, defn, value);
                } else if (dataType == ElementDataType.bool) {
                  Integer tmp = ODKDatabaseUtils.get().getIndexAsType(c, Integer.class, i);
                  Boolean value = tmp == null ? null : (tmp != 0);
                  putElementValue(values, defn, value);
                } else if (type.getElementType().equals("date")) {
                  String value = ODKDatabaseUtils.get().getIndexAsString(c, i);
                  String jrDatestamp = (value == null) ? null : (new SimpleDateFormat(
                      ISO8601_DATE_ONLY_FORMAT, Locale.ENGLISH)).format(new Date(TableConstants
                      .milliSecondsFromNanos(value)));
                  putElementValue(values, defn, jrDatestamp);
                } else if (type.getElementType().equals("dateTime")) {
                  String value = ODKDatabaseUtils.get().getIndexAsString(c, i);
                  String jrDatestamp = (value == null) ? null : (new SimpleDateFormat(
                      ISO8601_DATE_FORMAT, Locale.ENGLISH)).format(new Date(TableConstants
                      .milliSecondsFromNanos(value)));
                  putElementValue(values, defn, jrDatestamp);
                } else if (type.getElementType().equals("time")) {
                  String value = ODKDatabaseUtils.get().getIndexAsString(c, i);
                  putElementValue(values, defn, value);
                } else if (dataType == ElementDataType.array) {
                  ArrayList<Object> al = ODKDatabaseUtils.get().getIndexAsType(c, ArrayList.class,
                      i);
                  putElementValue(values, defn, al);
                } else if (dataType == ElementDataType.string) {
                  String value = ODKDatabaseUtils.get().getIndexAsString(c, i);
                  putElementValue(values, defn, value);
                } else /* unrecognized */{
                  throw new IllegalStateException("unrecognized data type: "
                      + defn.getElementType());
                }

              } else if (columnName.equals(DataTableColumns.SAVEPOINT_TIMESTAMP)) {
                savepointTimestamp = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.ROW_ETAG)) {
                rowETag = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.FILTER_TYPE)) {
                filterType = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.FILTER_VALUE)) {
                filterValue = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.FORM_ID)) {
                formId = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.LOCALE)) {
                locale = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.FORM_ID)) {
                formId = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.SAVEPOINT_TYPE)) {
                savepointType = ODKDatabaseUtils.get().getIndexAsString(c, i);
              } else if (columnName.equals(DataTableColumns.SAVEPOINT_CREATOR)) {
                savepointCreator = ODKDatabaseUtils.get().getIndexAsString(c, i);
              }
            }

            // OK got all the values into the values map -- emit
            // contents
            b.setLength(0);
            File submissionXml = new File(ODKFileUtils.getInstanceFolder(appName, tableId,
                instanceId), (asXml ? "submission.xml" : "submission.json"));
            File manifest = new File(ODKFileUtils.getInstanceFolder(appName, tableId, instanceId),
                "manifest.json");
            submissionXml.delete();
            manifest.delete();
            freturn.instanceFile = submissionXml;

            if (asXml) {
              // Pre-processing -- collapse all geopoints into a
              // string-valued representation
              for (ColumnDefinition defn : orderedDefns) {
                ElementType type = defn.getType();
                ElementDataType dataType = type.getDataType();
                if (dataType == ElementDataType.object
                    && (type.getElementType().equals("geopoint") || type.getElementType().equals(
                        "mimeUri"))) {
                  Map<String, Object> parent = null;
                  List<ColumnDefinition> parents = new ArrayList<ColumnDefinition>();
                  ColumnDefinition d = defn.getParent();
                  while (d != null) {
                    parents.add(d);
                    d = d.getParent();
                  }
                  parent = values;
                  for (int i = parents.size() - 1; i >= 0; --i) {
                    Object o = parent.get(parents.get(i).getElementName());
                    if (o == null) {
                      parent = null;
                      break;
                    }
                    parent = (Map<String, Object>) o;
                  }
                  if (parent != null) {
                    Object o = parent.get(defn.getElementName());
                    if (o != null) {
                      if (type.getElementType().equals("geopoint")) {
                        Map<String, Object> geopoint = (Map<String, Object>) o;
                        // OK. we have geopoint -- get the
                        // lat, long, alt, etc.
                        Double latitude = (Double) geopoint.get("latitude");
                        Double longitude = (Double) geopoint.get("longitude");
                        Double altitude = (Double) geopoint.get("altitude");
                        Double accuracy = (Double) geopoint.get("accuracy");
                        String gpt = "" + latitude + " " + longitude + " " + altitude + " "
                            + accuracy;
                        parent.put(defn.getElementName(), gpt);
                      } else if (type.getElementType().equals("mimeUri")) {
                        Map<String, Object> mimeuri = (Map<String, Object>) o;
                        String uriFragment = (String) mimeuri.get("uriFragment");
                        String contentType = (String) mimeuri.get("contentType");

                        if (uriFragment != null) {
                          File f = ODKFileUtils.getAsFile(appName, uriFragment);
                          if (f.equals(manifest)) {
                            throw new IllegalStateException(
                                "Unexpected collision with manifest.json");
                          }
                          freturn.addAttachmentFile(f, contentType);
                          parent.put(defn.getElementName(), f.getName());
                        }
                      } else {
                        throw new IllegalStateException("Unhandled transform case");
                      }
                    }
                  }
                }
              }

              datestamp = (new SimpleDateFormat(ISO8601_DATE_FORMAT, Locale.ENGLISH))
                  .format(new Date(TableConstants.milliSecondsFromNanos(savepointTimestamp)));

              // For XML, we traverse the map to serialize it
              Document d = new Document();
              d.setStandalone(true);
              d.setEncoding(CharEncoding.UTF_8);
              Element e = d.createElement(XML_DEFAULT_NAMESPACE,
                  (xmlRootElementName == null) ? "data" : xmlRootElementName);
              e.setPrefix("jr", XML_OPENROSA_NAMESPACE);
              e.setPrefix("", XML_DEFAULT_NAMESPACE);
              d.addChild(0, Node.ELEMENT, e);
              e.setAttribute("", "id", tableId);
              DynamicPropertiesCallback cb = new DynamicPropertiesCallback(getContext(), appName,
                  tableId, instanceId);

              int idx = 0;
              Element meta = d.createElement(XML_OPENROSA_NAMESPACE, "meta");

              Element v = d.createElement(XML_OPENROSA_NAMESPACE, "instanceID");
              v.addChild(0, Node.TEXT, submissionInstanceId);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              if (xmlDeviceIdPropertyName != null) {
                String deviceId = propertyManager.getSingularProperty(xmlDeviceIdPropertyName, cb);
                if (deviceId != null) {
                  v = d.createElement(XML_OPENROSA_NAMESPACE, "deviceID");
                  v.addChild(0, Node.TEXT, deviceId);
                  meta.addChild(idx++, Node.ELEMENT, v);
                  meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);
                }
              }
              if (xmlUserIdPropertyName != null) {
                String userId = propertyManager.getSingularProperty(xmlUserIdPropertyName, cb);
                if (userId != null) {
                  v = d.createElement(XML_OPENROSA_NAMESPACE, "userID");
                  v.addChild(0, Node.TEXT, userId);
                  meta.addChild(idx++, Node.ELEMENT, v);
                  meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);
                }
              }
              v = d.createElement(XML_OPENROSA_NAMESPACE, "timeEnd");
              v.addChild(0, Node.TEXT, datestamp);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // these are extra metadata tags...
              if (instanceName != null) {
                v = d.createElement(XML_DEFAULT_NAMESPACE, "instanceName");
                v.addChild(0, Node.TEXT, instanceName);
                meta.addChild(idx++, Node.ELEMENT, v);
                meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);
              } else {
                v = d.createElement(XML_DEFAULT_NAMESPACE, "instanceName");
                v.addChild(0, Node.TEXT, savepointTimestamp);
                meta.addChild(idx++, Node.ELEMENT, v);
                meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);
              }

              // these are extra metadata tags...
              // rowID
              v = d.createElement(XML_DEFAULT_NAMESPACE, "rowID");
              v.addChild(0, Node.TEXT, instanceId);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // rowETag
              v = d.createElement(XML_DEFAULT_NAMESPACE, "rowETag");
              if (rowETag != null) {
                v.addChild(0, Node.TEXT, rowETag);
              }
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // filterType
              v = d.createElement(XML_DEFAULT_NAMESPACE, "filterType");
              if (filterType != null) {
                v.addChild(0, Node.TEXT, filterType);
              }
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // filterValue
              v = d.createElement(XML_DEFAULT_NAMESPACE, "filterValue");
              if (filterValue != null) {
                v.addChild(0, Node.TEXT, filterValue);
              }
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // formID
              v = d.createElement(XML_DEFAULT_NAMESPACE, "formID");
              v.addChild(0, Node.TEXT, formId);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // locale
              v = d.createElement(XML_DEFAULT_NAMESPACE, "locale");
              v.addChild(0, Node.TEXT, locale);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // savepointType
              v = d.createElement(XML_DEFAULT_NAMESPACE, "savepointType");
              v.addChild(0, Node.TEXT, savepointType);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // savepointCreator
              v = d.createElement(XML_DEFAULT_NAMESPACE, "savepointCreator");
              if (savepointCreator != null) {
                v.addChild(0, Node.TEXT, savepointCreator);
              }
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // savepointTimestamp
              v = d.createElement(XML_DEFAULT_NAMESPACE, "savepointTimestamp");
              v.addChild(0, Node.TEXT, savepointTimestamp);
              meta.addChild(idx++, Node.ELEMENT, v);
              meta.addChild(idx++, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              // and insert the meta block into the XML

              e.addChild(0, Node.IGNORABLE_WHITESPACE, NEW_LINE);
              e.addChild(1, Node.ELEMENT, meta);
              e.addChild(2, Node.IGNORABLE_WHITESPACE, NEW_LINE);

              idx = 3;
              ArrayList<String> entryNames = new ArrayList<String>();
              entryNames.addAll(values.keySet());
              Collections.sort(entryNames);
              for (String name : entryNames) {
                idx = generateXmlHelper(d, e, idx, name, values, log);
              }

              KXmlSerializer serializer = new KXmlSerializer();

              ByteArrayOutputStream bo = new ByteArrayOutputStream();
              serializer.setOutput(bo, CharEncoding.UTF_8);
              // setting the response content type emits the
              // xml header.
              // just write the body here...
              d.writeChildren(serializer);
              serializer.flush();
              bo.close();

              b.append(bo.toString(CharEncoding.UTF_8));

              // OK we have the document in the builder (b).
              String doc = b.toString();

              freturn.instanceFile = submissionXml;

              // see if the form is encrypted and we can
              // encrypt it...
              EncryptedFormInformation formInfo = EncryptionUtils.getEncryptedFormInformation(
                  appName, tableId, xmlBase64RsaPublicKey, instanceId);
              if (formInfo != null) {
                File submissionXmlEnc = new File(submissionXml.getParentFile(),
                    submissionXml.getName() + ".enc");
                submissionXmlEnc.delete();
                // if we are encrypting, the form cannot be
                // reopened afterward
                // and encrypt the submission (this is a
                // one-way operation)...
                if (!EncryptionUtils.generateEncryptedSubmission(freturn, doc, submissionXml,
                    submissionXmlEnc, formInfo)) {
                  return null;
                }
                // at this point, the freturn object has
                // been re-written with the encrypted media
                // and xml files.
              } else {
                exportFile(doc, submissionXml, log);
              }

            } else {
              // Pre-processing -- collapse all mimeUri into filename
              for (ColumnDefinition defn : orderedDefns) {
                ElementType type = defn.getType();
                ElementDataType dataType = type.getDataType();

                if (dataType == ElementDataType.object && type.getElementType().equals("mimeUri")) {
                  Map<String, Object> parent = null;
                  List<ColumnDefinition> parents = new ArrayList<ColumnDefinition>();
                  ColumnDefinition d = defn.getParent();
                  while (d != null) {
                    parents.add(d);
                    d = d.getParent();
                  }
                  parent = values;
                  for (int i = parents.size() - 1; i >= 0; --i) {
                    Object o = parent.get(parents.get(i).getElementName());
                    if (o == null) {
                      parent = null;
                      break;
                    }
                    parent = (Map<String, Object>) o;
                  }
                  if (parent != null) {
                    Object o = parent.get(defn.getElementName());
                    if (o != null) {
                      if (dataType == ElementDataType.object
                          && type.getElementType().equals("mimeUri")) {
                        Map<String, Object> mimeuri = (Map<String, Object>) o;
                        String uriFragment = (String) mimeuri.get("uriFragment");
                        String contentType = (String) mimeuri.get("contentType");
                        File f = ODKFileUtils.getAsFile(appName, uriFragment);
                        if (f.equals(manifest)) {
                          throw new IllegalStateException("Unexpected collision with manifest.json");
                        }
                        freturn.addAttachmentFile(f, contentType);
                        parent.put(defn.getElementName(), f.getName());
                      } else {
                        throw new IllegalStateException("Unhandled transform case");
                      }
                    }
                  }
                }
              }

              // For JSON, we construct the model, then emit model +
              // meta + data
              HashMap<String, Object> wrapper = new HashMap<String, Object>();
              wrapper.put("tableId", tableId);
              wrapper.put("instanceId", instanceId);
              HashMap<String, Object> formDef = new HashMap<String, Object>();
              formDef.put("table_id", tableId);
              formDef.put("model", ColumnDefinition.getDataModel(orderedDefns));
              wrapper.put("formDef", formDef);
              wrapper.put("data", values);
              wrapper.put("metadata", new HashMap<String, Object>());
              HashMap<String, Object> elem = (HashMap<String, Object>) wrapper.get("metadata");
              if (instanceName != null) {
                elem.put("instanceName", instanceName);
              }
              elem.put("saved", "COMPLETE");
              elem.put("timestamp", datestamp);

              b.append(ODKFileUtils.mapper.writeValueAsString(wrapper));

              // OK we have the document in the builder (b).
              String doc = b.toString();
              exportFile(doc, submissionXml, log);
            }
            exportFile(freturn.serializeUriFragmentList(getContext()), manifest, log);
            return ParcelFileDescriptor.open(manifest, ParcelFileDescriptor.MODE_READ_ONLY);

          }
        } finally {
          if (c != null && !c.isClosed()) {
            c.close();
          }
        }

      } catch (JsonParseException e) {
        e.printStackTrace();
      } catch (JsonMappingException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }

    } finally {
      if (db != null) {
        db.close();
      }
    }
    return null;
  }

  /**
   * This method actually writes the JSON appName-relative manifest to disk.
   *
   * @param payload
   * @param path
   * @return
   */
  private static boolean exportFile(String payload, File outputFilePath, WebLogger log) {
    // write xml file
    FileOutputStream os = null;
    OutputStreamWriter osw = null;
    try {
      os = new FileOutputStream(outputFilePath, false);
      osw = new OutputStreamWriter(os, CharEncoding.UTF_8);
      osw.write(payload);
      osw.flush();
      osw.close();
      return true;

    } catch (IOException e) {
      log.e(t, "Error writing file");
      e.printStackTrace();
      try {
        osw.close();
        os.close();
      } catch (IOException ex) {
        ex.printStackTrace();
      }
      return false;
    }
  }

  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
    return 0;
  }

  @Override
  public String getType(Uri uri) {
    return null;
  }

  @Override
  public Uri insert(Uri uri, ContentValues values) {
    return null;
  }

  @Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
      String sortOrder) {
    return null;
  }

  @Override
  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    return 0;
  }

}


text:
set -ev

PATH=$HOME/protoc/bin:$PATH
protoc --version
pub get
make clean run-tests

redpajama_set_name: RedPajamaGithub


text:
package com.fasterxml.jackson.core;

/**
 * Shared base class for streaming processing contexts used during
 * reading and writing of Json content using Streaming API.
 * This context is also exposed to applications:
 * context object can be used by applications to get an idea of
 * relative position of the parser/generator within json content
 * being processed. This allows for some contextual processing: for
 * example, output within Array context can differ from that of
 * Object context.
 */
public abstract class JsonStreamContext
{
    // // // Type constants used internally

    protected final static int TYPE_ROOT = 0;
    protected final static int TYPE_ARRAY = 1;
    protected final static int TYPE_OBJECT = 2;

    protected int _type;

    /**
     * Index of the currently processed entry. Starts with -1 to signal
     * that no entries have been started, and gets advanced each
     * time a new entry is started, either by encountering an expected
     * separator, or with new values if no separators are expected
     * (the case for root context).
     */
    protected int _index;

    /*
    /**********************************************************
    /* Life-cycle
    /**********************************************************
     */

    protected JsonStreamContext() { }

    /*
    /**********************************************************
    /* Public API, accessors
    /**********************************************************
     */

    /**
     * Accessor for finding parent context of this context; will
     * return null for root context.
     */
    public abstract JsonStreamContext getParent();

    /**
     * Method that returns true if this context is an Array context;
     * that is, content is being read from or written to a Json Array.
     */
    public final boolean inArray() { return _type == TYPE_ARRAY; }

    /**
     * Method that returns true if this context is a Root context;
     * that is, content is being read from or written to without
     * enclosing array or object structure.
     */
    public final boolean inRoot() { return _type == TYPE_ROOT; }

    /**
     * Method that returns true if this context is an Object context;
     * that is, content is being read from or written to a Json Object.
     */
    public final boolean inObject() { return _type == TYPE_OBJECT; }

    /**
     * Method for accessing simple type description of current context;
     * either ROOT (for root-level values), OBJECT (for field names and
     * values of JSON Objects) or ARRAY (for values of JSON Arrays)
     */
    public final String getTypeDesc() {
        switch (_type) {
        case TYPE_ROOT: return "ROOT";
        case TYPE_ARRAY: return "ARRAY";
        case TYPE_OBJECT: return "OBJECT";
        }
        return "?";
    }

    /**
     * @return Number of entries that are complete and started.
     */
    public final int getEntryCount() { return _index + 1; }

    /**
     * @return Index of the currently processed entry, if any
     */
    public final int getCurrentIndex() { return (_index < 0) ? 0 : _index; }

    /**
     * Method for accessing name associated with the current location.
     * Non-null for FIELD_NAME and value events that directly
     * follow field names; null for root level and array values.
     */
    public abstract String getCurrentName();

    /**
     * Method for accessing currently active value being used by data-binding
     * (as the source of streaming data to write, or destination of data being
     * read), at this level in hierarchy.
     *

     * Note that "current value" is NOT populated (or used) by Streaming parser or generator;
     * it is only used by higher-level data-binding functionality.
     * The reason it is included here is that it can be stored and accessed hierarchically,
     * and gets passed through data-binding.
     *
     * @return Currently active value, if one has been assigned.
     *
     * @since 2.5
     */
    public Object getCurrentValue() {
        return null;
    }

    /**
     * Method to call to pass value to be returned via {@link #getCurrentValue}; typically
     * called indirectly through {@link JsonParser#setCurrentValue}
     * or {@link JsonGenerator#setCurrentValue}).
     *
     * @since 2.5
     */
    public void setCurrentValue(Object v) { }
}


text:
from __future__ import print_function, division

import sys,os
qspin_path = os.path.join(os.getcwd(),"../")
sys.path.insert(0,qspin_path)

from quspin.basis import spin_basis_1d,tensor_basis
import numpy as np
import scipy.sparse as sp

from functools import reduce

L1 = 3
L2 = 4
L = L1+L2

np.random.seed(2)

spin_basis = spin_basis_1d(L)

spin_basis_left = spin_basis_1d(L1)
spin_basis_right = spin_basis_1d(L2)

Ns_l = spin_basis_left.Ns
Ns_r = spin_basis_right.Ns

test_basis = tensor_basis(spin_basis_left,spin_basis_right)
# print(test_basis)
# print(spin_basis)

psi = np.random.uniform(-1,1,size=(spin_basis.Ns,)) + 1j*np.random.uniform(-1,1,size=(spin_basis.Ns,))
psi /= np.linalg.norm(psi)

sp_psi = sp.csr_matrix(psi).T

psis = np.random.uniform(-1,1,size=(spin_basis.Ns,spin_basis.Ns)) + 1j*np.random.uniform(-1,1,size=(spin_basis.Ns,spin_basis.Ns))
psis /= np.linalg.norm(psis,axis=0)

p_DM=np.random.uniform(size=spin_basis.Ns)
p_DM/=p_DM.sum()

DM = reduce(np.dot,[psis,np.diag(p_DM/sum(p_DM)),psis.T.conj()])

DMs = np.dstack((DM for i in range(10)))

kwargs_list = [
				(dict(sub_sys_A="left",return_rdm=None,return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1),return_rdm=None,return_rdm_EVs=False)),
				(dict(sub_sys_A="left",return_rdm="A",return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1),return_rdm="A",return_rdm_EVs=False)),
				(dict(sub_sys_A="left",return_rdm="B",return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1),return_rdm="B",return_rdm_EVs=False)),
				(dict(sub_sys_A="left",return_rdm="both",return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1),return_rdm="both",return_rdm_EVs=False)),
				(dict(sub_sys_A="left",return_rdm=None,return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1),return_rdm=None,return_rdm_EVs=True)),
				(dict(sub_sys_A="left",return_rdm="A",return_rdm_EVs=True),		dict(density=False,sub_sys_A=range(L1),return_rdm="A",return_rdm_EVs=True)),
				(dict(sub_sys_A="left",return_rdm="B",return_rdm_EVs=True),		dict(density=False,sub_sys_A=range(L1),return_rdm="B",return_rdm_EVs=True)),
				(dict(sub_sys_A="left",return_rdm="both",return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1),return_rdm="both",return_rdm_EVs=True)),
				(dict(sub_sys_A="right",return_rdm=None,return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm=None,return_rdm_EVs=False)),
				(dict(sub_sys_A="right",return_rdm="A",return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="A",return_rdm_EVs=False)),
				(dict(sub_sys_A="right",return_rdm="B",return_rdm_EVs=False),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="B",return_rdm_EVs=False)),
				(dict(sub_sys_A="right",return_rdm="both",return_rdm_EVs=False),dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="both",return_rdm_EVs=False)),
				(dict(sub_sys_A="right",return_rdm=None,return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm=None,return_rdm_EVs=True)),
				(dict(sub_sys_A="right",return_rdm="A",return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="A",return_rdm_EVs=True)),
				(dict(sub_sys_A="right",return_rdm="B",return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="B",return_rdm_EVs=True)),
				(dict(sub_sys_A="right",return_rdm="both",return_rdm_EVs=True),	dict(density=False,sub_sys_A=range(L1,L,1),return_rdm="both",return_rdm_EVs=True)),
				]

np.set_printoptions(linewidth=10000000,precision=2)

for kwargs2,kwargs1 in kwargs_list:
	print("checking kwargs: {}".format(kwargs2))
	out_spin = spin_basis.ent_entropy(psi,**kwargs1)
	out_tensor = test_basis.ent_entropy(psi,**kwargs2)

	for key,val in out_spin.items():
		try:
			np.testing.assert_allclose((val - out_tensor[key]).toarray(),0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))
		except AttributeError:
			np.testing.assert_allclose(val - out_tensor[key],0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))

	out_spin = spin_basis.ent_entropy(psi,sparse=True,**kwargs1)
	out_tensor = test_basis.ent_entropy(psi,sparse=True,**kwargs2)
	for key,val in out_spin.items():
		try:
			np.testing.assert_allclose((val - out_tensor[key]).toarray(),0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))
		except AttributeError:
			np.testing.assert_allclose(val - out_tensor[key],0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))

	out_spin = spin_basis.ent_entropy(psis,enforce_pure=True,**kwargs1)
	out_tensor = test_basis.ent_entropy(psis,enforce_pure=True,**kwargs2)

	for key,val in out_spin.items():
		try:
			np.testing.assert_allclose((val - out_tensor[key]).toarray(),0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))
		except AttributeError:
			np.testing.assert_allclose(val - out_tensor[key],0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))

	out_spin = spin_basis.ent_entropy(DM,**kwargs1)
	out_tensor = test_basis.ent_entropy(DM,**kwargs2)

	for key,val in out_spin.items():
		try:
			np.testing.assert_allclose((val - out_tensor[key]).toarray(),0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))
		except AttributeError:
			np.testing.assert_allclose(val - out_tensor[key],0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))

	out_spin = spin_basis.ent_entropy(DMs,**kwargs1)
	out_tensor = test_basis.ent_entropy(DMs,**kwargs2)

	for key,val in out_spin.items():
		try:
			np.testing.assert_allclose((val - out_tensor[key]).toarray(),0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))
		except AttributeError:
			np.testing.assert_allclose(val - out_tensor[key],0.0,atol=1E-5,err_msg='Failed {} comparison!'.format(key))

print("tensor_basis ent_entropy passed!")


text:
//
// The Home Automation Controller
//
var client = require('ibmiotf')
var exec = require('child_process').exec

// Logger setup
var winston = require('winston')
// Setup the logger with the specified log level
// For more on Winston log levels, see https://github.com/winstonjs/winston#logging
setupWinstonLogger('debug');
//setupWinstonLogger('info');

// The configuration
var appConfig = require("./config/myAppConfig.json")
var deviceConfig = require("./config/myDeviceConfig.json")

// JSON defintions for working with devices
var discoveryJson = require("./config/discoveryMessage.json")

/**
 * Setup the Winston logger, pass it the log level. For example,
 * 'info', 'debug' and so on. See https://github.com/winstonjs/winston for
 * more info.
 */
function setupWinstonLogger(logLevel) {
    winston.add(winston.transports.File, { filename : "./winston.log"});
    winston.remove(winston.transports.Console);
    winston.add(winston.transports.Console, { timestamp : "true"});
    // Set log level
    winston.level = logLevel;
}

// Create the Application Client
var applicationClient = new client.IotfApplication(appConfig);
winston.info("Connecting application client...");
applicationClient.connect();

/**
 * When a connect message is received, we're good to go
 */
applicationClient.on("connect", function() {
    winston.info("Application client, connected.");
    applicationClient.subscribeToDeviceEvents(appConfig.deviceType);
});

/**
 * When an error is received, process it
 */
applicationClient.on("error", function(err) {
    winston.error("Application Client Error: " + err);
});

/**
 * When a device event is received, process it
 */
applicationClient.on("deviceEvent", function (deviceType, deviceId, eventType, format, payload) {

    winston.info("Device Event from :: " + deviceType + " : " + deviceId + " of event " + eventType + " with payload : " + payload);
    // Is the event a discovery request?
    if (isDiscoveryRequest(deviceType, deviceId, payload)) {
        // Send a discovery message in response to the request for one
        handleDiscoveryMessage();
    } else if (isDeviceRequest(payload)) {
        // Handle the device request
        handleDeviceRequest(payload);
    }
});

// Create the Device Client
var deviceClient = new client.IotfDevice(deviceConfig);
winston.info("Connecting device client...");
deviceClient.connect();

/**
 * When a connect message is received, we're good to go
 */
deviceClient.on("connect", function() {
    winston.info("Device client, connected.");
});

/**
 * When an error is received, process it
 */
deviceClient.on("error", function(err) {
    winston.info("Device Client Error: " + err);
});

/**
 * Investigates the specified deviceType, deviceId, and payload
 * to determine whether or not the payload contains a discovery
 * message.
 *
 * Return true if so, false otherwise.
 */
function isDiscoveryRequest(deviceType, deviceId, payload) {
    // Sanity check, we may have already checked this, but code gets churned, ya know?
    if (deviceType == appConfig.deviceType && deviceId == appConfig.deviceId) {
        var payloadJson = JSON.parse(payload);
        // Make sure the deviceRequest.deviceId is correct
        if ('d' in payloadJson &&
            'deviceRequest' in payloadJson.d &&
            payloadJson.d.deviceRequest.deviceId == appConfig.deviceId) {
            // Make sure the action is correct
            if (payloadJson.d.deviceRequest.action == "discovery") {
                return true;
            }
        }
    }
    return false;
}

/**
 * Investiates the specified deviceType, deviceId, and payload
 * to determine whether or not the payload contains a device event
 * that is understood by the home automation controller
 */
function isDeviceRequest(payload) {
    var deviceId = extractDeviceIdFromPayload(payload);
    if (deviceId != null) {
        winston.debug("Found deviceId: " + deviceId + " in JSON payload");
        return true;
    }
    return false;
}

/**
 * Send a discovery message
 */
function handleDiscoveryMessage() {
    winston.debug("Sending discovery message...");
    // Publish the response event with the discoveryJson message
    publishEvent("response", discoveryJson);
}

/**
 * Handle the device event contained in the specified payload.
 * Get the metadata for the device first, then get the metadata
 * for the action, and use that to send the action (command) to
 * the device.
 */
function handleDeviceRequest(payload) {
    // Grab the action
    var deviceId = extractDeviceIdFromPayload(payload);
    if (deviceId != null) {
        var action = extractActionFromPayload(payload);
        if (action != null) {
            var actionMetadata = findActionMetadata(deviceId, action, discoveryJson);
            if (actionMetadata != null) {
                // Apply the requested action to the IoT device
                applyIotDeviceAction(actionMetadata);
            } else {
                winston.error("Expected action metadata, but none was found.");
            }
        } else {
            winston.error("Expected an action in the payload for device ID '" + deviceId + "', but none was found!");
        }
    } else {
        winston.error("Expected a device ID in the payload, but none was found!");
    }
}

/**
 * Extracts the deviceId property from the specified payload and
 * returns its value.
 *
 * @param The payload JSON string from the incoming message
 *
 * @returns The deviceId property value from the payload
 */
function extractDeviceIdFromPayload(payload) {
    var payloadJson = JSON.parse(payload);
    winston.debug("Payload JSON: " + JSON.stringify(payloadJson));

    // Undefined error? No way, man.
    if ('d' in payloadJson && 'deviceRequest' in payloadJson.d &&
        'deviceId' in payloadJson.d.deviceRequest) {
        return payloadJson.d.deviceRequest.deviceId;
    }
    // Could not find it, return null
    winston.error("Could not locate a device ID in the payload: " + payload);
    return null;
}

/**
 * Extracts the action property from the specified payload and
 * returns its value.
 *
 * @param The payload JSON string from the incoming message
 *
 * @returns The deviceId property value from the payload
 */
function extractActionFromPayload(payload) {
    var payloadJson = JSON.parse(payload);
    winston.debug("Payload JSON: " + JSON.stringify(payloadJson));

    // Undefined error? No way, man.
    if ('d' in payloadJson && 'deviceRequest' in payloadJson.d &&
        'action' in payloadJson.d.deviceRequest) {
        return payloadJson.d.deviceRequest.action;
    }
    // Could not find it, return null
    winston.error("Could not locate an action in the payload: " + payload);
    return null;
}

/**
 * Loop through all of the device metadata. When a match on the
 * deviceId is found, search the actions for that deviceId for the
 * specified action. If the action is found, return its metadata
 * block, which contains the information about its 433MHz encoding
 * and so forth.
 *
 * @param deviceId - the deviceId to locate in the metadataJson
 *
 * @param action - the action within the deviceId to locate
 *
 * @param metadataJson - the metadata to search, should contain both
 * the deviceId we're looking for, and within that device metadata
 * the action as well.
 *
 * @returns The action metadata that corresponds to the specified action,
 * or null if no match was found.
 */
function findActionMetadata(deviceId, action, metadataJson) {
    winston.debug("Looking for device ID: " + deviceId + " and action '" + action + "'...");
    // Check all of the device requests we know about
    // Sanity check
    winston.debug("Looking through this JSON: " + JSON.stringify(metadataJson));
    // Sanity check. We may have already checked this, but code gets churned, ya know?
    if ('d' in metadataJson && 'devices' in metadataJson.d) {
        var devicesMetadata = metadataJson.d.devices;
        winston.debug("There are " + devicesMetadata.length + " devices to scan through...");
        // Loop through all of the device metadata. When a match on the
        /// deviceId is found, search the actions for that deviceId for the
        /// specified action.
        for (var aa = 0; aa < devicesMetadata.length; aa++) {
            var deviceMetadata = devicesMetadata[aa];
            winston.debug("Looking at device '" + JSON.stringify(deviceMetadata));
            // Found a match?
            if (deviceId == deviceMetadata.deviceId) {
                // If we got here, then we did not find a match on action. Bummer.
                actionMetadata = findActionMetadataWithinDeviceMetadata(action, deviceMetadata);
                if (actionMetadata != null) {
                    return actionMetadata;
                }
            }
            winston.error("Found a match for device ID '" + deviceId + "' but could not find any metadata for action '" + action);
        }
    } else {
        winston.warn("Device JSON did not have the expected structure: " + JSON.stringify(metadataJson));
    }
    return null;
}

/**
 * Find the metadata for the specified action within the block of
 * metadata for the deviceId it belongs to.
 *
 * @param action - the action to search for
 *
 * @param deviceMetadata - the metadata block within which to search
 * the actions array, looking for the specified action.
 *
 * @returns The action metadata block within the actions array, within
 * the specified device metadata, or null if the action could not be
 * located.
 */
function findActionMetadataWithinDeviceMetadata(action, deviceMetadata) {
    // Yes, we have a match on deviceId
    winston.debug("Found matching deviceId: '" + deviceMetadata.deviceId + "' in JSON metadata");
    // Now check for the action for that device ID
    var actionsMetadata = deviceMetadata.actions;
    for (var aa = 0; aa < actionsMetadata.length; aa++) {
        var actionMetadata = actionsMetadata[aa];
        winston.debug("Looking at action '" + JSON.stringify(actionMetadata));
        // Have a match on action?
        if (action == actionMetadata.action) {
            // Yes, we have a match on action
            winston.debug("Found matching action: '" + actionMetadata.action + "' in JSON metadata");
            // Return the action metadata
            return actionMetadata;
        }
    }
    return null;
}

/**
 * THIS ONE IS FOR ALL THE MARBLES!
 * TODO: Need a better description than that.
 */
function applyIotDeviceAction(actionMetadata) {
    // Execute the codesend program and pass it the arguments it needs
    var encoding = actionMetadata.encoding;
    var delay = actionMetadata.delay;

    // Build the transmit command that sends the signal to the
    /// 433MHz IoT device
    var transmitCommand = appConfig.transmitterProgram + " " + encoding + " " + delay;
    winston.debug("Sending command to device: " + transmitCommand);
    // Now execute the transmit command
    exec(transmitCommand, function (error, stdout, stderr) {
        winston.info("stdout: " + stdout);
        winston.info('stderr: ' + stderr);
        if (error) {
            winston.error("Error while invoking command '" + transmitCommand + ": " + error.message.toString());
        }
    });

}

/**
 * Publish the specified JSON message under the specified eventName
 */
function publishEvent(eventName, jsonMessageToPublish) {
    // Use the Device Client to publish the JSON event
    deviceClient.publish(eventName, "json", jsonMessageToPublish);
}


text:
"""Training script for Neural Neighbourhood Search."""

import timeit
from typing import List, Tuple

from absl import app
from absl import flags
from absl import logging
import ml_collections
from ml_collections.config_flags import config_flags
import sonnet as snt
import tensorflow.compat.v2 as tf

from neural_lns import data_utils
from neural_lns import light_gnn

FLAGS = flags.FLAGS
config_flags.DEFINE_config_file(
    'config', 'neural_lns/config_train.py',
    'Training configuration.')

MIN_LEARNING_RATE = 1e-5

def train_and_evaluate(
    train_datasets: List[Tuple[str, str]],
    valid_datasets: List[Tuple[str, str]],
    strategy: tf.distribute.Strategy, learning_rate: float,
    model_dir: str, use_tf_function: bool, decay_steps: int,
    num_train_steps: int, num_train_run_steps: int, eval_every_steps: int,
    eval_steps: int, grad_clip_norm: float,
    model_config: ml_collections.ConfigDict):
  """The main training and evaluation loop."""
  if eval_every_steps % num_train_run_steps != 0:
    raise ValueError(
        'eval_every_steps is not divisible by num_train_run_steps')

  train_ds_all = []
  for path, _ in train_datasets:
    train_ds = data_utils.get_dataset(path)
    train_ds_all.append(train_ds)
  train_data = tf.data.Dataset.sample_from_datasets(train_ds_all)

  valid_ds_all = []
  for path, _ in valid_datasets:
    valid_ds = data_utils.get_dataset(path)
    valid_ds_all.append(valid_ds)
  valid_data = tf.data.Dataset.sample_from_datasets(valid_ds_all)

  with strategy.scope():
    model = light_gnn.get_model(**model_config.params)
    global_step = tf.Variable(
        0, trainable=False, name='global_step', dtype=tf.int64)
    lr_schedule = tf.optimizers.schedules.ExponentialDecay(
        initial_learning_rate=learning_rate,
        decay_steps=decay_steps,
        decay_rate=0.9)
    optimizer = snt.optimizers.Adam(learning_rate)
    train_acc_metric = tf.keras.metrics.BinaryAccuracy(threshold=0.5)
    valid_acc_metric = tf.keras.metrics.BinaryAccuracy(threshold=0.5)
    train_auc_metric = tf.keras.metrics.AUC()
    valid_auc_metric = tf.keras.metrics.AUC()

  def train_step(train_inputs):
    """Perform a single training step. Returns the loss."""

    # step_fn is replicated when running with TPUStrategy.
    def step_fn(ds_tuple: data_utils.DatasetTuple):
      logging.info('retracing step_fn')

      with tf.GradientTape() as tape:
        logits = model(
            ds_tuple.graphs_tuple,
            is_training=True,
            node_indices=ds_tuple.integer_node_indices,
            labels=ds_tuple.integer_labels)
        local_loss = tf.nn.sigmoid_cross_entropy_with_logits(
            labels=tf.cast(ds_tuple.integer_labels, tf.float32),
            logits=logits)
        tf.assert_equal(tf.shape(ds_tuple.integer_labels), tf.shape(logits))

        local_loss = tf.reduce_sum(local_loss, axis=[2], keepdims=True)
        local_loss = tf.reduce_mean(local_loss, axis=[0])
        local_loss = local_loss / strategy.num_replicas_in_sync

      tf.print('Local loss', local_loss)

      # We log AUC and ACC by comparing the greedy sample (always choose the
      # value with highest probability) with the best solution.
      _, proba = model.greedy_sample(ds_tuple.graphs_tuple,
                                     ds_tuple.integer_node_indices)
      proba = tf.reshape(proba, [-1])

      best_label = tf.reshape(ds_tuple.integer_labels[:, 0, :], [-1])
      train_acc_metric.update_state(best_label, proba)
      train_auc_metric.update_state(best_label, proba)

      replica_ctx = tf.distribute.get_replica_context()
      grads = tape.gradient(local_loss, model.trainable_variables)
      grads = replica_ctx.all_reduce('sum', grads)
      if grad_clip_norm > 0:
        grads, _ = tf.clip_by_global_norm(grads, grad_clip_norm)
      lr = tf.maximum(lr_schedule(optimizer.step), MIN_LEARNING_RATE)
      optimizer.learning_rate = lr
      optimizer.apply(grads, model.trainable_variables)
      global_step.assign_add(1)
      return local_loss

    losses = []
    for _ in range(num_train_run_steps):
      per_replica_losses = strategy.run(
          step_fn, args=(next(train_inputs),))
      loss = strategy.reduce(
          tf.distribute.ReduceOp.SUM,
          per_replica_losses,
          axis=None)
      losses.append(loss)
    return tf.reduce_mean(losses)

  def eval_step(eval_inputs):

    def step_fn(ds_tuple: data_utils.DatasetTuple):  # pylint: disable=missing-docstring
      logits = model(
          ds_tuple.graphs_tuple,
          is_training=False,
          node_indices=ds_tuple.integer_node_indices,
          labels=ds_tuple.integer_labels)

      local_loss = tf.nn.sigmoid_cross_entropy_with_logits(
          labels=tf.cast(ds_tuple.integer_labels, tf.float32),
          logits=logits)

      local_loss = tf.reduce_sum(local_loss, axis=[2], keepdims=True)
      local_loss = tf.reduce_mean(local_loss, axis=[0])
      # We scale the local loss here so we can later sum the gradients.
      # This is cheaper than averaging all gradients.
      local_loss = local_loss / strategy.num_replicas_in_sync

      # We log AUC and ACC by comparing the greedy sample (always choose the
      # value with highest probability) with the best solution.
      _, proba = model.greedy_sample(ds_tuple.graphs_tuple,
                                     ds_tuple.integer_node_indices)
      proba = tf.reshape(proba, [-1])
      best_label = tf.reshape(ds_tuple.integer_labels[:, 0, :], [-1])
      valid_acc_metric.update_state(best_label, proba)
      valid_auc_metric.update_state(best_label, proba)

      return local_loss

    valid_losses = []
    for _ in range(eval_steps):
      valid_losses_per_replica = strategy.run(
          step_fn, args=(next(eval_inputs),))
      valid_loss = strategy.reduce(
          tf.distribute.ReduceOp.SUM,
          valid_losses_per_replica,
          axis=None)
      valid_losses.append(valid_loss)
    return tf.reduce_mean(valid_losses)

  if use_tf_function:
    train_step = tf.function(train_step)
    eval_step = tf.function(eval_step)

  ckpt = tf.train.Checkpoint(
      model=model, optimizer=optimizer, global_step=global_step)
  ckpt_manager = tf.train.CheckpointManager(
      checkpoint=ckpt, directory=model_dir, max_to_keep=5)
  ckpt.restore(ckpt_manager.latest_checkpoint)
  if ckpt_manager.latest_checkpoint:
    logging.info('Restored from %s', ckpt_manager.latest_checkpoint)
  else:
    logging.info('Initializing from scratch.')

  train_inputs = iter(train_data)
  logging.info('Starting training...')
  while global_step.numpy() < num_train_steps:
    start = timeit.default_timer()
    loss = train_step(train_inputs)
    end = timeit.default_timer()

    step = global_step.numpy()
    train_acc = train_acc_metric.result().numpy()
    train_auc = train_auc_metric.result().numpy()
    train_acc_metric.reset_states()
    train_auc_metric.reset_states()

    logging.info(f'[{step}] loss = {loss.numpy():.4f}, ' +
                 f'acc = {train_acc:.4f} auc = {train_auc:.4f} ' +
                 f'steps_per_second = {num_train_run_steps / (end - start)}')

    if step % eval_every_steps == 0:
      model.save_model(model_dir)
      eval_inputs = iter(valid_data)
      valid_loss = eval_step(eval_inputs)

      valid_acc = valid_acc_metric.result().numpy()
      valid_auc = valid_auc_metric.result().numpy()
      valid_acc_metric.reset_states()
      valid_auc_metric.reset_states()

      logging.info(f'[Valid: {step}] acc = ' +
                   f'{valid_acc:.4f} auc = {valid_auc:.4f} ' +
                   f'loss = {valid_loss:.4f}')

  saved_ckpt = ckpt_manager.save()
  logging.info('Saved checkpoint: %s', saved_ckpt)

def main(_):
  flags_config = FLAGS.config
  gpus = tf.config.experimental.list_logical_devices(device_type='GPU')
  if gpus:
    logging.info('Found GPUs: %s', gpus)
    strategy = snt.distribute.Replicator([g.name for g in gpus])
  else:
    strategy = tf.distribute.OneDeviceStrategy('CPU')

  logging.info('Distribution strategy: %s', strategy)
  logging.info('Devices: %s', tf.config.list_physical_devices())

  train_and_evaluate(
      train_datasets=flags_config.train_datasets,
      valid_datasets=flags_config.valid_datasets,
      strategy=strategy,
      learning_rate=flags_config.learning_rate,
      model_dir=flags_config.work_unit_dir,
      use_tf_function=True,
      decay_steps=flags_config.decay_steps,
      num_train_steps=flags_config.num_train_steps,
      num_train_run_steps=flags_config.num_train_run_steps,
      eval_every_steps=flags_config.eval_every_steps,
      eval_steps=flags_config.eval_steps,
      grad_clip_norm=flags_config.grad_clip_norm,
      model_config=flags_config.model_config)

if __name__ == '__main__':
  tf.enable_v2_behavior()
  app.run(main)


text:
require "test/unit"
require "net/http"
require "webrick"
require "webrick/httpproxy"
begin
  require "webrick/ssl"
  require "net/https"
rescue LoadError
  # test_connect will be skipped
end
require File.expand_path("utils.rb", File.dirname(__FILE__))

class TestWEBrickHTTPProxy < Test::Unit::TestCase
  def teardown
    WEBrick::Utils::TimeoutHandler.terminate
    super
  end

  def test_fake_proxy
    assert_nil(WEBrick::FakeProxyURI.scheme)
    assert_nil(WEBrick::FakeProxyURI.host)
    assert_nil(WEBrick::FakeProxyURI.port)
    assert_nil(WEBrick::FakeProxyURI.path)
    assert_nil(WEBrick::FakeProxyURI.userinfo)
    assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
  end

  def test_proxy
    # Testing GET or POST to the proxy server
    # Note that the proxy server works as the origin server.
    #                    +------+
    #                    V      |
    #  client -------> proxy ---+
    #        GET / POST     GET / POST
    #
    proxy_handler_called = request_handler_called = 0
    config = {
      :ServerName => "localhost.localdomain",
      :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
      :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
    }
    TestWEBrick.start_httpproxy(config){|server, addr, port, log|
      server.mount_proc("/"){|req, res|
        res.body = "#{req.request_method} #{req.path} #{req.body}"
      }
      http = Net::HTTP.new(addr, port, addr, port)

      req = Net::HTTP::Get.new("/")
      http.request(req){|res|
        assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
        assert_equal("GET / ", res.body, log.call)
      }
      assert_equal(1, proxy_handler_called, log.call)
      assert_equal(2, request_handler_called, log.call)

      req = Net::HTTP::Head.new("/")
      http.request(req){|res|
        assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
        assert_nil(res.body, log.call)
      }
      assert_equal(2, proxy_handler_called, log.call)
      assert_equal(4, request_handler_called, log.call)

      req = Net::HTTP::Post.new("/")
      req.body = "post-data"
      req.content_type = "application/x-www-form-urlencoded"
      http.request(req){|res|
        assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
        assert_equal("POST / post-data", res.body, log.call)
      }
      assert_equal(3, proxy_handler_called, log.call)
      assert_equal(6, request_handler_called, log.call)
    }
  end

  def test_no_proxy
    # Testing GET or POST to the proxy server without proxy request.
    #
    #  client -------> proxy
    #        GET / POST
    #
    proxy_handler_called = request_handler_called = 0
    config = {
      :ServerName => "localhost.localdomain",
      :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
      :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
    }
    TestWEBrick.start_httpproxy(config){|server, addr, port, log|
      server.mount_proc("/"){|req, res|
        res.body = "#{req.request_method} #{req.path} #{req.body}"
      }
      http = Net::HTTP.new(addr, port)

      req = Net::HTTP::Get.new("/")
      http.request(req){|res|
        assert_nil(res["via"], log.call)
        assert_equal("GET / ", res.body, log.call)
      }
      assert_equal(0, proxy_handler_called, log.call)
      assert_equal(1, request_handler_called, log.call)

      req = Net::HTTP::Head.new("/")
      http.request(req){|res|
        assert_nil(res["via"], log.call)
        assert_nil(res.body, log.call)
      }
      assert_equal(0, proxy_handler_called, log.call)
      assert_equal(2, request_handler_called, log.call)

      req = Net::HTTP::Post.new("/")
      req.content_type = "application/x-www-form-urlencoded"
      req.body = "post-data"
      http.request(req){|res|
        assert_nil(res["via"], log.call)
        assert_equal("POST / post-data", res.body, log.call)
      }
      assert_equal(0, proxy_handler_called, log.call)
      assert_equal(3, request_handler_called, log.call)
    }
  end

  def test_big_bodies
    require 'digest/md5'
    rand_str = File.read(__FILE__)
    rand_str.freeze
    nr = 1024 ** 2 / rand_str.size # bigger works, too
    exp = Digest::MD5.new
    nr.times { exp.update(rand_str) }
    exp = exp.hexdigest
    TestWEBrick.start_httpserver do |o_server, o_addr, o_port, o_log|
      o_server.mount_proc('/') do |req, res|
        case req.request_method
        when 'GET'
          res['content-type'] = 'application/octet-stream'
          if req.path == '/length'
            res['content-length'] = (nr * rand_str.size).to_s
          else
            res.chunked = true
          end
          res.body = ->(socket) { nr.times { socket.write(rand_str) } }
        when 'POST'
          dig = Digest::MD5.new
          req.body { |buf| dig.update(buf); buf.clear }
          res['content-type'] = 'text/plain'
          res['content-length'] = '32'
          res.body = dig.hexdigest
        end
      end

      http = Net::HTTP.new(o_addr, o_port)
      IO.pipe do |rd, wr|
        headers = {
          'Content-Type' => 'application/octet-stream',
          'Transfer-Encoding' => 'chunked',
        }
        post = Net::HTTP::Post.new('/', headers)
        th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
        post.body_stream = rd
        http.request(post) do |res|
          assert_equal 'text/plain', res['content-type']
          assert_equal 32, res.content_length
          assert_equal exp, res.body
        end
        assert_nil th.value
      end

      TestWEBrick.start_httpproxy do |p_server, p_addr, p_port, p_log|
        http = Net::HTTP.new(o_addr, o_port, p_addr, p_port)
        http.request_get('/length') do |res|
          assert_equal(nr * rand_str.size, res.content_length)
          dig = Digest::MD5.new
          res.read_body { |buf| dig.update(buf); buf.clear }
          assert_equal exp, dig.hexdigest
        end
        http.request_get('/') do |res|
          assert_predicate res, :chunked?
          dig = Digest::MD5.new
          res.read_body { |buf| dig.update(buf); buf.clear }
          assert_equal exp, dig.hexdigest
        end

        IO.pipe do |rd, wr|
          headers = {
            'Content-Type' => 'application/octet-stream',
            'Content-Length' => (nr * rand_str.size).to_s,
          }
          post = Net::HTTP::Post.new('/', headers)
          th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
          post.body_stream = rd
          http.request(post) do |res|
            assert_equal 'text/plain', res['content-type']
            assert_equal 32, res.content_length
            assert_equal exp, res.body
          end
          assert_nil th.value
        end

        IO.pipe do |rd, wr|
          headers = {
            'Content-Type' => 'application/octet-stream',
            'Transfer-Encoding' => 'chunked',
          }
          post = Net::HTTP::Post.new('/', headers)
          th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
          post.body_stream = rd
          http.request(post) do |res|
            assert_equal 'text/plain', res['content-type']
            assert_equal 32, res.content_length
            assert_equal exp, res.body
          end
          assert_nil th.value
        end
      end
    end
  end

  def test_http10_proxy_chunked
    # Testing HTTP/1.0 client request and HTTP/1.1 chunked response
    # from origin server.
    #                    +------+
    #                    V      |
    #  client -------> proxy ---+
    #           GET          GET
    #           HTTP/1.0     HTTP/1.1
    #           non-chunked  chunked
    #
    proxy_handler_called = request_handler_called = 0
    config = {
      :ServerName => "localhost.localdomain",
      :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
      :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
    }
    log_tester = lambda {|log, access_log|
      log.reject! {|str|
        %r{WARN  chunked is set for an HTTP/1\.0 request\. \(ignored\)} =~ str
      }
      assert_equal([], log)
    }
    TestWEBrick.start_httpproxy(config, log_tester){|server, addr, port, log|
      body = nil
      server.mount_proc("/"){|req, res|
        body = "#{req.request_method} #{req.path} #{req.body}"
        res.chunked = true
        res.body = -> (socket) { body.each_char {|c| socket.write c } }
      }

      # Don't use Net::HTTP because it uses HTTP/1.1.
      TCPSocket.open(addr, port) {|s|
        s.write "GET / HTTP/1.0\r\nHost: localhost.localdomain\r\n\r\n"
        response = s.read
        assert_equal(body, response[/.*\z/])
      }
    }
  end

  def make_certificate(key, cn)
    subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
    exts = [
      ["keyUsage", "keyEncipherment,digitalSignature", true],
    ]
    cert = OpenSSL::X509::Certificate.new
    cert.version = 2
    cert.serial = 1
    cert.subject = subject
    cert.issuer = subject
    cert.public_key = key
    cert.not_before = Time.now - 3600
    cert.not_after = Time.now + 3600
    ef = OpenSSL::X509::ExtensionFactory.new(cert, cert)
    exts.each {|args| cert.add_extension(ef.create_extension(*args)) }
    cert.sign(key, "sha256")
    return cert
  end if defined?(OpenSSL::SSL)

  def test_connect
    # Testing CONNECT to proxy server
    #
    #  client -----------> proxy -----------> https
    #    1.     CONNECT          establish TCP
    #    2.   ---- establish SSL session --->
    #    3.   ------- GET or POST ---------->
    #
    key = TEST_KEY_RSA2048
    cert = make_certificate(key, "127.0.0.1")
    s_config = {
      :SSLEnable =>true,
      :ServerName => "localhost",
      :SSLCertificate => cert,
      :SSLPrivateKey => key,
    }
    config = {
      :ServerName => "localhost.localdomain",
      :RequestCallback => Proc.new{|req, res|
        assert_equal("CONNECT", req.request_method)
      },
    }
    TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
      s_server.mount_proc("/"){|req, res|
        res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
      }
      TestWEBrick.start_httpproxy(config){|server, addr, port, log|
        http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
        http.use_ssl = true
        http.verify_callback = Proc.new do |preverify_ok, store_ctx|
          store_ctx.current_cert.to_der == cert.to_der
        end

        req = Net::HTTP::Get.new("/")
        req["Content-Type"] = "application/x-www-form-urlencoded"
        http.request(req){|res|
          assert_equal("SSL GET / ", res.body, s_log.call + log.call)
        }

        req = Net::HTTP::Post.new("/")
        req["Content-Type"] = "application/x-www-form-urlencoded"
        req.body = "post-data"
        http.request(req){|res|
          assert_equal("SSL POST / post-data", res.body, s_log.call + log.call)
        }
      }
    }
  end if defined?(OpenSSL::SSL)

  def test_upstream_proxy
    # Testing GET or POST through the upstream proxy server
    # Note that the upstream proxy server works as the origin server.
    #                                   +------+
    #                                   V      |
    #  client -------> proxy -------> proxy ---+
    #        GET / POST     GET / POST     GET / POST
    #
    up_proxy_handler_called = up_request_handler_called = 0
    proxy_handler_called = request_handler_called = 0
    up_config = {
      :ServerName => "localhost.localdomain",
      :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
      :RequestCallback => Proc.new{|req, res| up_request_handler_called += 1}
    }
    TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
      up_server.mount_proc("/"){|req, res|
        res.body = "#{req.request_method} #{req.path} #{req.body}"
      }
      config = {
        :ServerName => "localhost.localdomain",
        :ProxyURI => URI.parse("http://localhost:#{up_port}"),
        :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
        :RequestCallback => Proc.new{|req, res| request_handler_called += 1},
      }
      TestWEBrick.start_httpproxy(config){|server, addr, port, log|
        http = Net::HTTP.new(up_addr, up_port, addr, port)

        req = Net::HTTP::Get.new("/")
        http.request(req){|res|
          skip res.message unless res.code == '200'
          via = res["via"].split(/,\s+/)
          assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
          assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
          assert_equal("GET / ", res.body)
        }
        assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
        assert_equal(2, up_request_handler_called, up_log.call + log.call)
        assert_equal(1, proxy_handler_called, up_log.call + log.call)
        assert_equal(1, request_handler_called, up_log.call + log.call)

        req = Net::HTTP::Head.new("/")
        http.request(req){|res|
          via = res["via"].split(/,\s+/)
          assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
          assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
          assert_nil(res.body, up_log.call + log.call)
        }
        assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
        assert_equal(4, up_request_handler_called, up_log.call + log.call)
        assert_equal(2, proxy_handler_called, up_log.call + log.call)
        assert_equal(2, request_handler_called, up_log.call + log.call)

        req = Net::HTTP::Post.new("/")
        req.body = "post-data"
        req.content_type = "application/x-www-form-urlencoded"
        http.request(req){|res|
          via = res["via"].split(/,\s+/)
          assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
          assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
          assert_equal("POST / post-data", res.body, up_log.call + log.call)
        }
        assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
        assert_equal(6, up_request_handler_called, up_log.call + log.call)
        assert_equal(3, proxy_handler_called, up_log.call + log.call)
        assert_equal(3, request_handler_called, up_log.call + log.call)

        if defined?(OpenSSL::SSL)
          # Testing CONNECT to the upstream proxy server
          #
          #  client -------> proxy -------> proxy -------> https
          #    1.   CONNECT        CONNECT      establish TCP
          #    2.   -------- establish SSL session ------>
          #    3.   ---------- GET or POST -------------->
          #
          key = TEST_KEY_RSA2048
          cert = make_certificate(key, "127.0.0.1")
          s_config = {
            :SSLEnable =>true,
            :ServerName => "localhost",
            :SSLCertificate => cert,
            :SSLPrivateKey => key,
          }
          TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
            s_server.mount_proc("/"){|req2, res|
              res.body = "SSL #{req2.request_method} #{req2.path} #{req2.body}"
            }
            http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
            http.use_ssl = true
            http.verify_callback = Proc.new do |preverify_ok, store_ctx|
              store_ctx.current_cert.to_der == cert.to_der
            end

            req2 = Net::HTTP::Get.new("/")
            http.request(req2){|res|
              assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
            }

            req2 = Net::HTTP::Post.new("/")
            req2.body = "post-data"
            req2.content_type = "application/x-www-form-urlencoded"
            http.request(req2){|res|
              assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
            }
          }
        end
      }
    }
  end

  if defined?(OpenSSL::SSL)
    TEST_KEY_RSA2048 = OpenSSL::PKey.read <<-_end_of_pem_
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
-----END RSA PRIVATE KEY-----
    _end_of_pem_
  end
end


text:
"""

    OpenAPI spec version:

    Generated by: https://github.com/swagger-api/swagger-codegen.git

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""

from __future__ import absolute_import

import os
import sys
import unittest

import lib_openshift
from lib_openshift.rest import ApiException
from lib_openshift.models.v1_o_auth_authorize_token import V1OAuthAuthorizeToken

class TestV1OAuthAuthorizeToken(unittest.TestCase):
    """ V1OAuthAuthorizeToken unit test stubs """

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def testV1OAuthAuthorizeToken(self):
        """
        Test V1OAuthAuthorizeToken
        """
        model = lib_openshift.models.v1_o_auth_authorize_token.V1OAuthAuthorizeToken()

if __name__ == '__main__':
    unittest.main()