text:
layout: post
status: publish
published: true
title: Clases & Objetos Parte IV
author: Ramses Velasquez
author_login: ramses
author_email: cotufa9@gmail.com
date: 2014-01-17 12:04:30.000000000 -04:30
serie: PHP desde Cero
description: Tutorial para aprender a implementar las interfaces y las clases abstractas
dificultad: novato
duracion: 20
categories:
- Cursos
- PHP
tags:
- php
- POO
---

En este capítulo de PHP vamos a conocer que son y como implementar las clases abstractas y las interfaces. Veremos algunos ejemplo para tratar de diferenciar las dos y así aprender a sacarle  provecho a estas herramientas que nos brinda la programación orientada a objetos.

¿Qué es una Clase Abstracta?

Las clases abstractas son clases con capacidades especiales, ya que sus propiedades y métodos pueden ser implementados o no. Esto dependerá de la necesidad que tengan a la hora de programar esta clase. Las clases abstractas sirven para ser heredades y no pueden ser instanciadas directamente. Solo se puede heredar una clase Abstracta a la vez, como cualquier otra clase, y son una descripción de que debe tener y como debe funcionar la clase hijo para que sea util y funcional. Para entender mejor esto veamos unos ejemplo

```php
<?php

class Fruta {
    private $color;

    public function comer() {
        //Comer la fruta
    }
}

class Naranja extends Fruta {
    public function comer() {
        // código para comer la naranja
    }
}

class Patilla extends Fruta {
    public function comer() {
        // código para comer la patilla
    }
}

$naranja = new Naranja();
$naranja->comer();

$fruta = new Fruta();
$fruta->comer();

?>
```

Vamos a analizar el ejemplo anterior, primero creamos una Naranja que extiende de Fruta y la comemos. Al crear la Naranja le estamos dando mas sentido a la clase de Fruta. En las ultimas lineas estamos creando una Fruta y la comemos también ¿pero a que sabe una Fruta? En este punto estamos haciendo algo que no tienen sentido y aquí es donde entran las clases y métodos abstractos. Veamos este ejemplo de nuevo pero Fruta sera una clase abstracta.

```php
<?php

// podemos observar que nuestra clase ahora es abstracta, por lo tanto podrá tener métodos y propiedades abstractos y no podrá ser instanciada directamente

// Para declarar una clase abstracta debemos utilizar la palabra reservada abstract antes de la declaración de la clase
absctract class Fruta {
    private $color;

    // nuestro método comer ahora es abstracto y debe ser implementado por la clase que herede Fruta
    // Para declarar un método abstracto debemos utilizar la palabra reservada abstract antes de la declaración normal del método y en vez de utilizar llaves para colocar el código utilizamos un punto y coma (;) ya que no vamos a tener código en la función.
    abstract public function comer();
}

// para extender una clase abstracta usamos la misma nomenclatura que para extender una clase normal.

class Naranja extends Fruta {
    public function comer() {
        // código para comer la naranja
    }
}

class Patilla extends Fruta {
    public function comer() {
        // código para comer la patilla
    }
}

$naranja = new Naranja();
$naranja->comer();

// Ahora estas dos lineas de código darán error y que no podemos instanciar una clase Fruta
$fruta = new Fruta();
$fruta->comer();

?>
```

Podemos ver como ahora tiene un poco mas de sentido el concepto de Fruta. Es una clase que solo puede ser extendida ya que una Fruta como tal no significa nada. Haciéndola una clase abstracta estamos obligados a extenderla y no instanciarla directamente.

¿Qué es una Interfaz?

Una interfaz es estructuralmente como una clase abstracta. Tiene un nombre, una serie de funciones sin implementación, pero al final no puede tener ningún tipo de lógica ni implementación (recordemos que en las clases abstractas puedes tener algunas funciones con implementación y otras no), es decir solo deben estar los nombres de los métodos o propiedades. Solo es un esqueleto para que quien los herede tenga como una guía de que métodos debe tener como mínimo en la clase que implementa la interfaz y así esta pueda funcionar dentro de el programa o sistema donde se usa.

Esto quiere decir que varias clases que son muy diferentes entre si, pueden funcionar y ejecutarse en el mismo fragmento de código solo por tener la misma interfaz implementada. Esto se debe a que tendrán los métodos mínimos que la interfaz les proporciona. Hay que tener en cuenta que una clase puede implementar todas las interfaces que sean necesarias.  Veamos un ejemplo de interfaces para entender toda esta información.

```php
<?php

// para declarar una interfaz se utiliza la palabra reservada interface en vez de la palabra class
interface Interaccion {

    // los métodos de la interface se declaran como en una clase normal pero sin implementación
    public function encender();
    public function apagar();
}

interface Direccion {
    public function girarDerecha();
    public function girarIzquierda();
}

// para hacer uso de una interfaz se deben declarar después de el nombre de la clase y anteponiendo la palabra implements.
// si se tienen varias interfaces entonces se separan con coma (,)
class Televisor implements Interaccion {

    public function encender() {
        // este metodo es heredado desde la interfaz
    }

    public function apagar() {
        // este metodo es heredado desde la interfaz
    }
}

class Carro implements Interaccion, Direccion {

    public function encender() {
        // este metodo es heredado desde la interfaz Interaccion
    }

    public function apagar() {
        // este metodo es heredado desde la interfaz Interaccion
    }

    public function girarDerecha(){
        // este método es heredado desde la interfaz Direccion
    }
    public function girarIzquierda(){
        // este método es heredado desde la interfaz Direccion
    }
}

?>
```

Conclusión

Hemos aprendido un poco más de la programación orientada a objetos en PHP y con esto tenemos más herramientas para enfrentar los problemas que se nos presenten a la hora de desarrollar grandes sistemas. Cualquier duda o comentario estaré atento a la sección de comentarios.


text:
import * as React from "react";
import * as css from "classnames";
import config from "../config/config";

interface IProps {
  children?: any;
  title: string;
  active?: boolean;
}

// function create(title: string, active: boolean, children: any) {
//   return [
//

//
//       { title }
//

//

//       { children }
//

//   ];
// }

// export default class Item extends React.Component<IProps, {}> {
//   render() {
//     return create (this.props.title, this.props.active, this.props.children);
//   }
// }

export const Item = ({children, title, active}: IProps) => (

      { config.i18n(title) }

      { children }

);
export default Item;

redpajama_set_name: RedPajamaGithub


text:
package com.huawei.networkos.ops.wizards;

import java.io.File;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

import com.huawei.network.opsdev.core.schema.OpsSchemaApiItem;
import com.huawei.network.opsdev.core.templet.ProjectTempletManager;

public class TreeContentProvider implements ITreeContentProvider {

    private List<OpsSchemaApiItem> lstOpsSchema = new ArrayList<OpsSchemaApiItem>();
	private ProjectTempletManager templetManager =null;

	public void setManager(ProjectTempletManager manager) {
		this.templetManager = manager;
	}

	public Object[] getChildren(Object arg0) {

		List<OpsSchemaApiItem> lstOpsSchema1  = new ArrayList<OpsSchemaApiItem>();
		if (arg0 instanceof OpsSchemaApiItem)
		{
			OpsSchemaApiItem item = null;
			OpsSchemaApiItem opsschema = (OpsSchemaApiItem)arg0;
			if (opsschema.isSchemaFile() && templetManager != null)
			{
				//  if parsed ,  get schema apis from memory
				if(opsschema.hasChildren())
				{
					return opsschema.getLstChild().toArray();
				}

				String schemaFile = opsschema.getSchemaFile();
				templetManager.addFile(schemaFile);
				 Map<String, List<String>>  lstMan = templetManager.getApiUrls();
				 String schemaName = (new File(schemaFile)).getName();

				for (String str : templetManager.getApiUrlsByName(schemaName)) {
					//TreeItem item = new TreeItem(rustfulTree.getSelection()[0], SWT.BORDER);
					//item.setText(str);
					item =  new OpsSchemaApiItem(schemaFile, str);
					lstOpsSchema1.add(item);
				}
				opsschema.addChild(lstOpsSchema1);
			}
		}
		return lstOpsSchema1.toArray();
	}

	public Object getParent(Object arg0) {
		return null;
	}

	public boolean hasChildren(Object arg0) {

		if (arg0 instanceof OpsSchemaApiItem)
		{
			OpsSchemaApiItem opsschema = (OpsSchemaApiItem)arg0;
			return opsschema.isSchemaFile();
		}
		return false;
	}

	public Object[] getElements(Object arg0) {
		return lstOpsSchema.toArray();
	}

	public void dispose() {
	}

	public void inputChanged(Viewer arg0, Object arg1, Object arg2) {

	}

	public void addOpsSchema(List<OpsSchemaApiItem> lstOpsScheam)
	{
		lstOpsSchema.addAll(lstOpsScheam);
	}

}


text:
/* This pane appears on drivers that have the HasEvents interface. */

var openmdao = (typeof openmdao === "undefined" || !openmdao ) ? {} : openmdao ;

openmdao.TriggersPane = function(elm, project, pathname, name) {
    var events,
        eventsDiv = jQuery("
"),
        addButton = jQuery("<button>Add Event</button>").button(),
        clrButton = jQuery("<button>Clear Events</button>").button(),
        columns = [
            {id:"del",     name:"",        field:"del",     width:25, formatter:buttonFormatter},
            {id:"target",  name:"Target",  field:"target",  width:500}
        ],
        options = {
            asyncEditorLoading: false,
            multiSelect: false,
            autoHeight: false,
            autoEdit: false
        };

    function buttonFormatter(row, cell, value, columnDef, dataContext) {
        button = '

';
        return button;
    }
    elm.append(eventsDiv);

    var tabdiv = jQuery('
'),
        table = jQuery('
'),
        row = jQuery('
').append(jQuery('').append(addButton))
                            .append(jQuery('').append(clrButton));
    table.append(row);
    tabdiv.append(table);
    elm.append(tabdiv);

    events = new Slick.Grid(eventsDiv, [], columns, options);
    events.onClick.subscribe(function(e) {
        var cell = events.getCellFromEvent(e);
        if (cell.cell === 0) {
            var delname = events.getData()[cell.row].target,
                cmd = pathname+'.remove_event("'+delname+'")';
            project.issueCommand(cmd);
        }
    });

    eventsDiv.bind('resizeCanvas', function() {
        events.resizeCanvas();
    });

    /** add a new event */
    function addEvent(target) {
        var cmd = pathname+".add_event('"+target+"')";
        project.issueCommand(cmd);
    }

    /** prompt for new event */
    function promptForEvent(callback) {

        var candidates = [];

        project.getAvailableEvents(pathname).done(function(cjson) {
            candidates = cjson;

            // Build dialog markup
            var win = jQuery('

'),
                target = jQuery('<input id="event-target" type="text" style="width:100%"></input>');

            win.append(jQuery('
Target:
').append(target));
            event_selector = win.find('#event-target');

            // update the event selector.
            event_selector.html('');
            event_selector.autocomplete({ source: candidates, minLength:0});

            function handleResponse(ok) {
                win.dialog('close');
                if (ok) {
                    callback(target.val());
                }
                win.remove();
            }

            function setupSelector(selector) {

                // process new selector value when selector loses focus
                selector.bind('blur', function(e) {
                    selector.autocomplete('close');
                });

                // set autocomplete to trigger blur (remove focus)
                selector.autocomplete({
                    select: function(event, ui) {
                        selector.val(ui.item.value);
                        selector.blur();
                    },
                    delay: 0,
                    minLength: 0
                });

                // set enter key to trigger blur (remove focus)
                selector.bind('keypress.enterkey', function(e) {
                    if (e.which === 13) {
                        selector.blur();
                        handleResponse(true);
                    }
                });
            }

            setupSelector(event_selector);

            // Display dialog
            jQuery(win).dialog({
                modal: true,
                title: 'New Event',
                buttons: [
                    {
                        text: 'Ok',
                        id: 'event-ok',
                        click: function() { handleResponse(true); }
                    },
                    {
                        text: 'Cancel',
                        id: 'event-cancel',
                        click: function() { handleResponse(false); }
                    }
                ]
            });
        });
    }

    /** clear all events */
    function clearEvents() {
        var cmd = pathname+".clear_events()";
        project.issueCommand(cmd);
    }

    addButton.click(function() { promptForEvent(addEvent); });
    clrButton.click(function() { clearEvents(); });

    /** load the table with the given properties */
    this.loadData = function(properties) {
        if (properties) {
            events.setData(properties);
        }
        else {
            events.setData([]);
            alert('Error getting properties for '+pathname+' ('+name+')');
        }
        events.resizeCanvas();
    };
};


text:
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#ifndef EIGEN_SPARSEVECTOR_H
#define EIGEN_SPARSEVECTOR_H

/** \class SparseVector
  *
  * \brief a sparse vector class
  *
  * \tparam _Scalar the scalar type, i.e. the type of the coefficients
  *
  * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
  *
  * This class can be extended with the help of the plugin mechanism described on the page
  * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_SPARSEVECTOR_PLUGIN.
  */

namespace internal {
template<typename _Scalar, int _Options, typename _Index>
struct traits<SparseVector<_Scalar, _Options, _Index> >
{
  typedef _Scalar Scalar;
  typedef _Index Index;
  typedef Sparse StorageKind;
  typedef MatrixXpr XprKind;
  enum {
    IsColVector = _Options & RowMajorBit ? 0 : 1,

    RowsAtCompileTime = IsColVector ? Dynamic : 1,
    ColsAtCompileTime = IsColVector ? 1 : Dynamic,
    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,
    Flags = _Options | NestByRefBit | LvalueBit,
    CoeffReadCost = NumTraits<Scalar>::ReadCost,
    SupportedAccessPatterns = InnerRandomAccessPattern
  };
};
}

template<typename _Scalar, int _Options, typename _Index>
class SparseVector
  : public SparseMatrixBase<SparseVector<_Scalar, _Options, _Index> >
{
  public:
    EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector)
    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
//     EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, =)

  protected:
  public:

    typedef SparseMatrixBase<SparseVector> SparseBase;
    enum { IsColVector = internal::traits<SparseVector>::IsColVector };

    enum {
      Options = _Options
    };

    CompressedStorage<Scalar,Index> m_data;
    Index m_size;

    CompressedStorage<Scalar,Index>& _data() { return m_data; }
    CompressedStorage<Scalar,Index>& _data() const { return m_data; }

  public:

    EIGEN_STRONG_INLINE Index rows() const { return IsColVector ? m_size : 1; }
    EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; }
    EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
    EIGEN_STRONG_INLINE Index outerSize() const { return 1; }
    EIGEN_STRONG_INLINE Index innerNonZeros(Index j) const { eigen_assert(j==0); return m_size; }

    EIGEN_STRONG_INLINE const Scalar* _valuePtr() const { return &m_data.value(0); }
    EIGEN_STRONG_INLINE Scalar* _valuePtr() { return &m_data.value(0); }

    EIGEN_STRONG_INLINE const Index* _innerIndexPtr() const { return &m_data.index(0); }
    EIGEN_STRONG_INLINE Index* _innerIndexPtr() { return &m_data.index(0); }

    inline Scalar coeff(Index row, Index col) const
    {
      eigen_assert((IsColVector ? col : row)==0);
      return coeff(IsColVector ? row : col);
    }
    inline Scalar coeff(Index i) const { return m_data.at(i); }

    inline Scalar& coeffRef(Index row, Index col)
    {
      eigen_assert((IsColVector ? col : row)==0);
      return coeff(IsColVector ? row : col);
    }

    /** \returns a reference to the coefficient value at given index \a i
      * This operation involes a log(rho*size) binary search. If the coefficient does not
      * exist yet, then a sorted insertion into a sequential buffer is performed.
      *
      * This insertion might be very costly if the number of nonzeros above \a i is large.
      */
    inline Scalar& coeffRef(Index i)
    {
      return m_data.atWithInsertion(i);
    }

  public:

    class InnerIterator;

    inline void setZero() { m_data.clear(); }

    /** \returns the number of non zero coefficients */
    inline Index nonZeros() const  { return static_cast<Index>(m_data.size()); }

    inline void startVec(Index outer)
    {
      eigen_assert(outer==0);
    }

    inline Scalar& insertBackByOuterInner(Index outer, Index inner)
    {
      eigen_assert(outer==0);
      return insertBack(inner);
    }
    inline Scalar& insertBack(Index i)
    {
      m_data.append(0, i);
      return m_data.value(m_data.size()-1);
    }

    inline Scalar& insert(Index row, Index col)
    {
      Index inner = IsColVector ? row : col;
      Index outer = IsColVector ? col : row;
      eigen_assert(outer==0);
      return insert(inner);
    }
    Scalar& insert(Index i)
    {
      Index startId = 0;
      Index p = m_data.size() - 1;
      // TODO smart realloc
      m_data.resize(p+2,1);

      while ( (p >= startId) && (m_data.index(p) > i) )
      {
        m_data.index(p+1) = m_data.index(p);
        m_data.value(p+1) = m_data.value(p);
        --p;
      }
      m_data.index(p+1) = i;
      m_data.value(p+1) = 0;
      return m_data.value(p+1);
    }

    /**
      */
    inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); }

    inline void finalize() {}

    void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
    {
      m_data.prune(reference,epsilon);
    }

    void resize(Index rows, Index cols)
    {
      eigen_assert(rows==1 || cols==1);
      resize(IsColVector ? rows : cols);
    }

    void resize(Index newSize)
    {
      m_size = newSize;
      m_data.clear();
    }

    void resizeNonZeros(Index size) { m_data.resize(size); }

    inline SparseVector() : m_size(0) { resize(0); }

    inline SparseVector(Index size) : m_size(0) { resize(size); }

    inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows,cols); }

    template<typename OtherDerived>
    inline SparseVector(const MatrixBase<OtherDerived>& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    template<typename OtherDerived>
    inline SparseVector(const SparseMatrixBase<OtherDerived>& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    inline SparseVector(const SparseVector& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    inline void swap(SparseVector& other)
    {
      std::swap(m_size, other.m_size);
      m_data.swap(other.m_data);
    }

    inline SparseVector& operator=(const SparseVector& other)
    {
      if (other.isRValue())
      {
        swap(other.const_cast_derived());
      }
      else
      {
        resize(other.size());
        m_data = other.m_data;
      }
      return *this;
    }

    template<typename OtherDerived>
    inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other)
    {
      if (int(RowsAtCompileTime)!=int(OtherDerived::RowsAtCompileTime))
        return Base::operator=(other.transpose());
      else
        return Base::operator=(other);
    }

    #ifndef EIGEN_PARSED_BY_DOXYGEN
    template<typename Lhs, typename Rhs>
    inline SparseVector& operator=(const SparseSparseProduct<Lhs,Rhs>& product)
    {
      return Base::operator=(product);
    }
    #endif

//       const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
//       if (needToTranspose)
//       {
//         // two passes algorithm:
//         //  1 - compute the number of coeffs per dest inner vector
//         //  2 - do the actual copy/eval
//         // Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed
//         typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
//         OtherCopy otherCopy(other.derived());
//         typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
//
//         resize(other.rows(), other.cols());
//         Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
//         // pass 1
//         // FIXME the above copy could be merged with that pass
//         for (int j=0; j<otherCopy.outerSize(); ++j)
//           for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
//             ++m_outerIndex[it.index()];
//
//         // prefix sum
//         int count = 0;
//         VectorXi positions(outerSize());
//         for (int j=0; j<outerSize(); ++j)
//         {
//           int tmp = m_outerIndex[j];
//           m_outerIndex[j] = count;
//           positions[j] = count;
//           count += tmp;
//         }
//         m_outerIndex[outerSize()] = count;
//         // alloc
//         m_data.resize(count);
//         // pass 2
//         for (int j=0; j<otherCopy.outerSize(); ++j)
//           for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
//           {
//             int pos = positions[it.index()]++;
//             m_data.index(pos) = j;
//             m_data.value(pos) = it.value();
//           }
//
//         return *this;
//       }
//       else
//       {
//         // there is no special optimization
//         return SparseMatrixBase<SparseMatrix>::operator=(other.derived());
//       }
//     }

    friend std::ostream & operator << (std::ostream & s, const SparseVector& m)
    {
      for (Index i=0; i<m.nonZeros(); ++i)
        s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
      s << std::endl;
      return s;
    }

    // this specialized version does not seems to be faster
//     Scalar dot(const SparseVector& other) const
//     {
//       int i=0, j=0;
//       Scalar res = 0;
//       asm("#begindot");
//       while (i<nonZeros() && j<other.nonZeros())
//       {
//         if (m_data.index(i)==other.m_data.index(j))
//         {
//           res += m_data.value(i) * internal::conj(other.m_data.value(j));
//           ++i; ++j;
//         }
//         else if (m_data.index(i)<other.m_data.index(j))
//           ++i;
//         else
//           ++j;
//       }
//       asm("#enddot");
//       return res;
//     }

    /** Destructor */
    inline ~SparseVector() {}

    /** Overloaded for performance */
    Scalar sum() const;

  public:

    /** \deprecated use setZero() and reserve() */
    EIGEN_DEPRECATED void startFill(Index reserve)
    {
      setZero();
      m_data.reserve(reserve);
    }

    /** \deprecated use insertBack(Index,Index) */
    EIGEN_DEPRECATED Scalar& fill(Index r, Index c)
    {
      eigen_assert(r==0 || c==0);
      return fill(IsColVector ? r : c);
    }

    /** \deprecated use insertBack(Index) */
    EIGEN_DEPRECATED Scalar& fill(Index i)
    {
      m_data.append(0, i);
      return m_data.value(m_data.size()-1);
    }

    /** \deprecated use insert(Index,Index) */
    EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c)
    {
      eigen_assert(r==0 || c==0);
      return fillrand(IsColVector ? r : c);
    }

    /** \deprecated use insert(Index) */
    EIGEN_DEPRECATED Scalar& fillrand(Index i)
    {
      return insert(i);
    }

    /** \deprecated use finalize() */
    EIGEN_DEPRECATED void endFill() {}

#   ifdef EIGEN_SPARSEVECTOR_PLUGIN
#     include EIGEN_SPARSEVECTOR_PLUGIN
#   endif
};

template<typename Scalar, int _Options, typename _Index>
class SparseVector<Scalar,_Options,_Index>::InnerIterator
{
  public:
    InnerIterator(const SparseVector& vec, Index outer=0)
      : m_data(vec.m_data), m_id(0), m_end(static_cast<Index>(m_data.size()))
    {
      eigen_assert(outer==0);
    }

    InnerIterator(const CompressedStorage<Scalar,Index>& data)
      : m_data(data), m_id(0), m_end(static_cast<Index>(m_data.size()))
    {}

    template<unsigned int Added, unsigned int Removed>
    InnerIterator(const Flagged<SparseVector,Added,Removed>& vec, Index )
      : m_data(vec._expression().m_data), m_id(0), m_end(m_data.size())
    {}

    inline InnerIterator& operator++() { m_id++; return *this; }

    inline Scalar value() const { return m_data.value(m_id); }
    inline Scalar& valueRef() { return const_cast<Scalar&>(m_data.value(m_id)); }

    inline Index index() const { return m_data.index(m_id); }
    inline Index row() const { return IsColVector ? index() : 0; }
    inline Index col() const { return IsColVector ? 0 : index(); }

    inline operator bool() const { return (m_id < m_end); }

  protected:
    const CompressedStorage<Scalar,Index>& m_data;
    Index m_id;
    const Index m_end;
};

#endif // EIGEN_SPARSEVECTOR_H


text:
package com.adaptris.core.transform;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import com.adaptris.core.AdaptrisMessage;
import com.adaptris.core.AdaptrisMessageFactory;
import com.adaptris.core.CoreException;
import com.adaptris.core.DefaultMessageFactory;
import com.adaptris.core.Service;
import com.adaptris.core.ServiceException;
import com.adaptris.core.stubs.MessageHelper;
import com.adaptris.core.util.DocumentBuilderFactoryBuilder;
import com.adaptris.core.util.LifecycleHelper;
import com.adaptris.core.util.XmlHelper;
import com.adaptris.util.KeyValuePair;
import com.adaptris.util.text.xml.StxTransformerFactory;
import com.adaptris.util.text.xml.XPath;
import com.adaptris.util.text.xml.XmlTransformerFactory;
import com.adaptris.util.text.xml.XsltTransformerFactory;
import net.sf.saxon.serialize.MessageWarner;
import net.sf.saxon.trans.UncheckedXPathException;

@SuppressWarnings("deprecation")
public class XmlTransformServiceTest
    extends com.adaptris.interlok.junit.scaffolding.services.TransformServiceExample {

  static final String KEY_XML_NODE_TRANSFORM_URL = "XmlTransformService.outputNodeTransform";

  public static final String KEY_XML_TEST_INPUT = "XmlTransformService.outputTestMessage";
  public static final String KEY_XML_TEST_TRANSFORM_URL = "XmlTransformService.outputTestTransform";
  public static final String KEY_XML_TEST_TRANSFORM_URL_XSL_MESSAGE = "XmlTransformService.outputTestTransformWithXslMessage";
  public static final String KEY_XML_TEST_INVALID_TRANSFORM_URL = "XmlTransformService.outputTestInvalidTransform";
  public static final String KEY_XML_TEST_FATAL_TRANSFORM_URL = "XmlTransformService.outputTestFatalTransform";
  public static final String KEY_XML_TEST_STX_TRANSFORM_URL = "XmlTransformService.outputTestStxTransform";
  public static final String KEY_XML_TEST_OUTPUT = "XmlTransformService.outputTestResult";

  static final String KEY_ISSUE2641_INPUT = "XmlTransformService.issue2641.input";
  static final String KEY_ISSUE2641_TRANSFORM_URL = "XmlTransformService.issue2641.transform";

  static final String ISSUE2641_DEST_XPATH = "/Envelope/QualityDocument/DocumentLine[6]/Criteria/CriteriaID";
  static final String ISSUE2641_SRC_XPATH = "/root/segment_Header/record_/critere6";

  static final String KEY_XML_REMOVE_NAMESPACE_MAPPING = "XmlTransformService.remove.namespace.mapping";

  static final String XML_WITH_NAMESPACE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
      + "<svrl:schematron-output xmlns:svrl=\"http://purl.oclc.org/dsdl/svrl\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sch=\"http://www.ascc.net/xml/schematron\" xmlns:iso=\"http://purl.oclc.org/dsdl/schematron\" xmlns:dp=\"http://www.dpawson.co.uk/ns#\" title=\"Anglia Farmers AF xml Invoice Schematron File\" schemaVersion=\"ISO19757-3\">\n"
      + "<svrl:ns-prefix-in-attribute-values uri=\"http://www.dpawson.co.uk/ns#\" prefix=\"dp\"/>\n" + "<svrl:active-pattern/>\n"
      + "<svrl:fired-rule context=\"SageData/JoinedData\"/>\n"
      + "<svrl:failed-assert test=\"STOCK_CODE != ''\" location=\"/SageData[1]/JoinedData[1]\">\n"
      + "<svrl:text>Error: Product Code must be present.</svrl:text>\n" + "</svrl:failed-assert>\n"
      + "<svrl:fired-rule context=\"SageData/JoinedData/CUST_ORDER_NUMBER[. != '']\"/>\n"
      + "<svrl:fired-rule context=\"SageData/JoinedData/AF_NUMBER[. != '']\"/>\n"
      + "<svrl:failed-assert test=\"string-length(.) = 5\" location=\"/SageData[1]/JoinedData[1]/AF_NUMBER[1]\">\n"
      + "<svrl:text>Error: Anglia Farmer's Supplier Number must be 5 digits long. (Current Value: 62826123)</svrl:text>\n"
      + "</svrl:failed-assert>\n" + "</svrl:schematron-output>";

  private enum FactoryConfig {
    STX(new StxTransformerFactory()),
    XSLT(new XsltTransformerFactory()) {
      @Override
      XmlTransformService configure(XmlTransformService s) {
        DocumentBuilderFactoryBuilder dbfb = new DocumentBuilderFactoryBuilder();
        dbfb.getFeatures().add(new KeyValuePair("http://xml.org/sax/features/external-general-entities", "false"));
        ((XsltTransformerFactory) factory).setXmlDocumentFactoryConfig(dbfb);
        s.setXmlTransformerFactory(factory);
        return s;
      }
    };

    XmlTransformerFactory factory;

    FactoryConfig(XmlTransformerFactory fac) {
      factory = fac;
    }

    XmlTransformService configure(XmlTransformService s) {
      s.setXmlTransformerFactory(factory);
      return s;
    }
  }
  private enum ParameterConfig {
    IGNORE(new IgnoreMetadataParameter()), METADATA(new StringMetadataParameter(new String[]
    {
      ".*metadataToInclude.*"
    }, new String[]
    {
      ".*metadataToExclude.*"
    })), COMPOSITE(new XmlTransformParameterBuilder(new StringMetadataParameter(new String[]
    {
      ".*metadataToInclude.*"
    }, new String[]
    {
      ".*metadataToExclude.*"
    }), new ObjectMetadataParameter(".*myObjectMetadataKeys.*"))), OBJECT(new ObjectMetadataParameter(".*myObjectMetadataKeys.*"));
    XmlTransformParameter param;

    ParameterConfig(XmlTransformParameter p) {
      param = p;
    }

    XmlTransformService configure(XmlTransformService s) {
      s.setTransformParameter(param);
      return s;
    }
  }

  @Test
  public void testRemoveNamespaceMapping() throws Exception {
    // This explicit tests some behavioural changes that might have occured due to migration SaxonHE
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_REMOVE_NAMESPACE_MAPPING));
    service.setOutputMessageEncoding("ISO-8859-1");
    AdaptrisMessage msg = AdaptrisMessageFactory.getDefaultInstance().newMessage(XML_WITH_NAMESPACE, "UTF-8");
    execute(service, msg);
    log.debug(msg.getContent());
  }

  @Test
  public void testSetUrl() {
    try {
      XmlTransformService service = new XmlTransformService();
      service.setUrl("");
      fail();
    }
    catch (IllegalArgumentException expected) {
    }
    XmlTransformService service = new XmlTransformService();
    service.setUrl("url");
    assertEquals("url", service.getUrl());
  }

  @Test
  public void testSetMetadataKey() {
    try {
      XmlTransformService service = new XmlTransformService();
      service.setMetadataKey("");
      fail();
    }
    catch (IllegalArgumentException expected) {
    }
    XmlTransformService service = new XmlTransformService();
    service.setMetadataKey("key");
    assertEquals("key", service.getMetadataKey());
  }

  @Test
  public void testInitDefault() {
    XmlTransformService service = new XmlTransformService();
    try {
      LifecycleHelper.init(service);
      assertTrue(service.allowOverride()); // set by init
    }
    catch (CoreException e) {
      fail(); // there is a now default metadata key
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testInitWithUrl() {
    XmlTransformService service = new XmlTransformService();
    try {
      service.setUrl("url");
      LifecycleHelper.init(service);
      assertTrue(!service.allowOverride()); // left as configured
    }
    catch (CoreException e) {
      fail();
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testInitWithMetadataKey() {
    XmlTransformService service = new XmlTransformService();
    try {
      service.setMetadataKey("key");
      LifecycleHelper.init(service);
      assertTrue(service.allowOverride()); // set by init
    }
    catch (CoreException e) {
      fail();
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithUrlOnly() throws Exception {
    XmlTransformService service = new XmlTransformService();
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    try {
      service.setUrl("url");
      LifecycleHelper.init(service);

      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithNullMetadataValueInMessage() throws Exception {
    XmlTransformService service = new XmlTransformService();
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      LifecycleHelper.init(service);

      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithEmptyMetadataValueInMessage() throws Exception {
    XmlTransformService service = new XmlTransformService();
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    msg.addMetadata("key", "");
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      LifecycleHelper.init(service);

      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithMetadataValueInMessage() throws Exception {
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    msg.addMetadata("key", "val");
    XmlTransformService service = new XmlTransformService();
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      LifecycleHelper.init(service);

      // allow override is false
      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithMetadataValueInMessageAllowOverride() throws Exception {

    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    XmlTransformService service = new XmlTransformService();
    msg.addMetadata("key", "val");
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      service.setAllowOverride(true);
      LifecycleHelper.init(service);

      // allow override is false
      assertTrue(service.obtainUrlToUse(msg).equals("val"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithNoMetadataValueNoUrl() throws Exception {
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    XmlTransformService service = new XmlTransformService();
    try {
      service.setMetadataKey("key");
      service.setAllowOverride(true);
      LifecycleHelper.init(service);
      try {
        service.obtainUrlToUse(msg);
      }
      catch (ServiceException expected) {
      }
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithNoMetadataValue() throws Exception {
    XmlTransformService service = new XmlTransformService();
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      service.setAllowOverride(true);
      LifecycleHelper.init(service);
      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  @Test
  public void testObtainUrlWithEmptyMetadataValue() throws Exception {
    AdaptrisMessage msg = new DefaultMessageFactory().newMessage();
    msg.addMetadata("key", "");
    XmlTransformService service = new XmlTransformService();
    try {
      service.setUrl("url");
      service.setMetadataKey("key");
      service.setAllowOverride(true);
      LifecycleHelper.init(service);

      assertTrue(service.obtainUrlToUse(msg).equals("url"));
    }
    finally {
      LifecycleHelper.close(service);
    }
  }

  protected XmlTransformService createBaseExample() {
    XmlTransformService service = new XmlTransformService();
    service.setUrl("URL of transform to apply");
    service.setMetadataKey("optional metadata key against which over-ride URL may be stored, only if allowOverride == true");
    service.setAllowOverride(true);
    return service;
  }

  @Override
  protected String createBaseFileName(Object object) {
    XmlTransformService service = (XmlTransformService) object;
    return super.createBaseFileName(object) + "-" + service.getXmlTransformerFactory().getClass().getSimpleName() + "-"
        + service.getTransformParameter().getClass().getSimpleName();
  }

  @Override
  protected Object retrieveObjectForSampleConfig() {
    return null; // over-rides retrieveServices below instead
  }

  @Override
  protected List<Service> retrieveObjectsForSampleConfig() {
    List<Service> result = new ArrayList<>();

    for (FactoryConfig fac : FactoryConfig.values()) {
      for (ParameterConfig param : ParameterConfig.values()) {
        result.add(param.configure(fac.configure(createBaseExample())));
      }
    }
    return result;
  }

  @Test
  public void testOutputWithCache() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    AdaptrisMessage m2 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));

    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    try {
      start(service);
      service.doService(m1);
      service.doService(m2);
      assertEquals("payload " + m1.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m1.getContent());
      assertEquals("payload " + m2.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m2.getContent());
    }
    finally {
      stop(service);
    }
  }

  // INTERLOK-3113

  @Test
  public void testOutputWithCacheResetsParameters() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    m1.addMessageHeader("myKey", "myValue");
    AdaptrisMessage m2 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));

    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    service.setCacheTransforms(true);
    service.setTransformParameter(new StringMetadataParameter(new String[] {"myKey"}, new String[0]));
    try {
      start(service);
      service.doService(m1);
      assertNotNull(service.getTransforms().get(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL)).getParameter("myKey"));
      service.doService(m2);
      assertNull(service.getTransforms().get(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL)).getParameter("myKey"));

    }
    finally {
      stop(service);
    }
  }

  @Test
  public void testOutputWithNoCache() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    AdaptrisMessage m2 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));

    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    service.setCacheTransforms(false);
    try {
      start(service);
      service.doService(m1);
      service.doService(m2);
      assertEquals("payload " + m1.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m1.getContent());
      assertEquals("payload " + m2.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m2.getContent());
    }
    finally {
      stop(service);
    }
  }

  @Test
  public void testXSLTOutput() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    execute(service, m1);
    assertEquals("payload " + m1.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m1.getContent());
  }

  @Test
  public void testXSLTOutput_NamedXsltTransformFactory() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    XmlTransformService service = new XmlTransformService();
    XsltTransformerFactory fac = new XsltTransformerFactory(net.sf.saxon.TransformerFactoryImpl.class.getCanonicalName());
    service.setXmlTransformerFactory(fac);
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    execute(service, m1);
    assertEquals("payload " + m1.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m1.getContent());
  }

  @Test
  public void testSTXOutput() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_STX_TRANSFORM_URL));

    service.setXmlTransformerFactory(new StxTransformerFactory());

    execute(service, m1);
    assertEquals("payload " + m1.getContent(), PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT), m1.getContent());
  }

  @Test
  public void testXSLT_RecoverableError() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(getName());
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_INVALID_TRANSFORM_URL));
    try {
      execute(service, m1);
      // INTERLOK-1850 - Saxon 9.7 won't report exceptions, so even if we throw, it'll just eat it.
      // fail("Exception expected but none thrown");
    } catch (ServiceException e) {
      assertTrue(e.getCause() instanceof TransformerException);
    }
    finally {
      Thread.currentThread().setName(oldName);
    }
  }

  @Test
  public void testXSLT_RecoverableError_NoFail() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(getName());
    XmlTransformService service = new XmlTransformService();
    XsltTransformerFactory fac = new XsltTransformerFactory();
    fac.setFailOnRecoverableError(false);
    service.setXmlTransformerFactory(fac);

    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_INVALID_TRANSFORM_URL));
    try {
      execute(service, m1);
    }
    finally {
      Thread.currentThread().setName(oldName);
    }

  }

  @Test
  public void testXSLT_FatalError() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_FATAL_TRANSFORM_URL));
    try {
      execute(service, m1);
      fail("Exception expected but none thrown");
    } catch (ServiceException expected) {
      assertExceptionCause(expected, TransformerException.class, UncheckedXPathException.class);
    }
  }

  @Test
  public void testSingleParameter_XSLTOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("world", "World");
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    service.setTransformParameter(new StringMetadataParameter());
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));

  }

  @Test
  public void testObjectMetadataParameter_XSLTOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addObjectHeader("myDocumentObject", XmlHelper.createDocument("<data>World</data>"));
    msg.addObjectHeader("anotherDocument", XmlHelper.createDocument("<data>GoodBye</data>"));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_NODE_TRANSFORM_URL));
    service.setTransformParameter(new ObjectMetadataParameter(".*my.*"));
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));

  }

  @Test
  public void testObjectMetadataParameter_NoRegexp() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addObjectHeader("myDocumentObject", XmlHelper.createDocument("<data>World</data>"));
    msg.addObjectHeader("anotherDocument", XmlHelper.createDocument("<data>GoodBye</data>"));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_NODE_TRANSFORM_URL));
    service.setTransformParameter(new ObjectMetadataParameter());
    try {
      execute(service, msg);
      fail();
    }
    catch (ServiceException expected) {

    }
  }

  @Test
  public void testParameterBuilder_XSLTOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("world", "World");
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    service.setTransformParameter(new XmlTransformParameterBuilder(new IgnoreMetadataParameter(), new StringMetadataParameter()));
    execute(service, msg);

    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));
  }

  @Test
  public void testParameterBuilder_ObjectMetadata_XSLTOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("key", "value");
    msg.addObjectHeader("myDocumentObject", XmlHelper.createDocument("<data>World</data>"));
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_NODE_TRANSFORM_URL));
    service.setTransformParameter(new XmlTransformParameterBuilder(new IgnoreMetadataParameter(), new StringMetadataParameter(),
        new ObjectMetadataParameter(".*")));
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));
  }

  @Test
  public void testSingleParameter_STXOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("world", "World");
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_STX_TRANSFORM_URL));
    service.setXmlTransformerFactory(new StxTransformerFactory());
    service.setTransformParameter(new StringMetadataParameter());
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));
  }

  @Test
  public void testMultipleParameters_XSLTOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("world", "World");
    msg.addMetadata("one", "World");
    msg.addMetadata("two", "World");
    msg.addMetadata("three", "World");
    msg.addMetadata("four", "World");
    XmlTransformService service = new XmlTransformService();

    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL));
    service.setTransformParameter(new StringMetadataParameter());
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));
  }

  @Test
  public void testMultipleParameters_STXOutput() throws Exception {
    AdaptrisMessage msg = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    msg.addMetadata("world", "World");
    msg.addMetadata("one", "World");
    msg.addMetadata("two", "World");
    msg.addMetadata("three", "World");
    msg.addMetadata("four", "World");
    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_STX_TRANSFORM_URL));
    service.setXmlTransformerFactory(new StxTransformerFactory());
    service.setTransformParameter(new StringMetadataParameter());
    execute(service, msg);
    assertTrue("payload " + msg.getContent(),
        msg.getContent().equals(PROPERTIES.getProperty(KEY_XML_TEST_OUTPUT) + "World"));
  }

  @Test
  public void testIssue2641() throws Exception {
    DefaultMessageFactory factory = new DefaultMessageFactory();
    factory.setDefaultCharEncoding("ISO-8859-1");
    AdaptrisMessage msg =
        MessageHelper.createMessage(factory, PROPERTIES.getProperty(KEY_ISSUE2641_INPUT));
    Document srcXml = createDocument(msg.getPayload());
    XPath srcXpath = new XPath();
    String srcValue = srcXpath.selectSingleTextItem(srcXml, ISSUE2641_SRC_XPATH);
    assertEquals("ISO-8859-1", msg.getContentEncoding());

    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_ISSUE2641_TRANSFORM_URL));
    service.setOutputMessageEncoding("UTF-8");
    execute(service, msg);

    assertEquals("UTF-8", msg.getContentEncoding());
    Document destXml = createDocument(msg.getPayload());

    XPath destXpath = new XPath();
    String destValue = destXpath.selectSingleTextItem(destXml, ISSUE2641_DEST_XPATH);
    log.debug("testIssue2641:: srcValue  = [" + srcValue + "]");
    log.debug("testIssue2641:: destValue = [" + destValue + "]");

    // All things being equal, they should be the same.
    assertEquals(srcValue, destValue);

  }

  @Test
  public void testIssue2641_NoOutputMessageEncoding() throws Exception {
    DefaultMessageFactory factory = new DefaultMessageFactory();
    factory.setDefaultCharEncoding("ISO-8859-1");
    AdaptrisMessage msg =
        MessageHelper.createMessage(factory, PROPERTIES.getProperty(KEY_ISSUE2641_INPUT));
    Document srcXml = createDocument(msg.getPayload());
    XPath srcXpath = new XPath();
    String srcValue = srcXpath.selectSingleTextItem(srcXml, ISSUE2641_SRC_XPATH);
    assertEquals("ISO-8859-1", msg.getContentEncoding());

    XmlTransformService service = new XmlTransformService();
    service.setUrl(PROPERTIES.getProperty(KEY_ISSUE2641_TRANSFORM_URL));
    execute(service, msg);

    assertEquals("ISO-8859-1", msg.getContentEncoding());
    // We're using UTF-8 as the encoding; get bytes will give us the right thing.
    Document destXml = createDocument(msg.getPayload());
    XPath destXpath = new XPath();
    String destValue = destXpath.selectSingleTextItem(destXml, ISSUE2641_DEST_XPATH);
    log.debug("testIssue2641:: srcValue  = [" + srcValue + "]");
    log.debug("testIssue2641:: destValue = [" + destValue + "]");

    // All things being equal, they should be the same.
    assertEquals(srcValue, destValue);
  }

  @Test
  public void testXSLT_XslMessageTerminate() throws Exception {
    AdaptrisMessage m1 = MessageHelper.createMessage(PROPERTIES.getProperty(KEY_XML_TEST_INPUT));
    XmlTransformService service = new XmlTransformService();
    XsltTransformerFactory fac = new XsltTransformerFactory();
    fac.getTransformerFactoryAttributes()
        .add(new KeyValuePair("http://saxon.sf.net/feature/messageEmitterClass", MessageWarner.class.getCanonicalName()));
    fac.getTransformerFactoryFeatures().add(new KeyValuePair(XMLConstants.FEATURE_SECURE_PROCESSING, "true"));
    service.setXmlTransformerFactory(fac);
    service.setUrl(PROPERTIES.getProperty(KEY_XML_TEST_TRANSFORM_URL_XSL_MESSAGE));
    try {
      execute(service, m1);
      fail();
    } catch (ServiceException expected) {
      assertExceptionCause(expected, TransformerException.class, UncheckedXPathException.class);
    }
  }

  private static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = domFactory.newDocumentBuilder();
    return builder;
  }

  private Document createDocument(byte[] bytes) throws Exception {
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    return newDocumentBuilder().parse(new InputSource(in));
  }

  // INTERLOK-3101, Saxon-9.9.1-4 onwards throws a different Exception.
  private void assertExceptionCause(Exception e, Class...classes) {
    assertNotNull(e.getCause());
    List<Class> validClasses = Arrays.asList(classes);
    Throwable t = e.getCause();
    boolean matches =
        validClasses.stream().anyMatch((clazz) -> clazz.isAssignableFrom(t.getClass()));
    assertTrue("Exception cause is expected", matches);
  }

}


text:
class ApplicationController < ActionController::API
  include JSONFormatting

  before_filter :cors_set_access_control_headers

  before_action :authenticate

  protected

  def cors_set_access_control_headers
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, PATCH, DELETE, OPTIONS'
    headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Accept, Authorization, Token'
  end

  def add_attributes(object, args)
    object.attributes = args.reject {|k,v| !object.attributes.keys.member?(k.to_s)}
  end

  def authenticate
    authenticate_token || render_unauthorized
  end

  def authenticate_token
    permit_params[:token] == ENV['ROOMIES_SECRET']
  end

  def render_unauthorized
    self.headers['WWW-Authenticate'] = 'Token realm="Application"'
    render json: 'Bad credentials', status: 401
  end
end


text:
'''
Created on 30 oct. 2018

@author: david
'''

import logging
import time

from engine.driver import Driver
#from sensor.imu_dummy import ImuDummy
from sensor.imu6050 import Imu6050

logging.basicConfig(level=logging.DEBUG)

MAX_THROTTLE = 40.0
MIN_THROTTLE = 25.0

PRECISION_DEGREES = 2.0
PID_PERIOD = 0.02

KP = 0.01
KI = 0.01
KD = 0.005

def turnTo(targetAngle, imu, driver):

    driver.setNeutral()
    driver.setMode(Driver.MODE_ROTATE)
    imu.updateGyroTime()
    lastTime = time.time()
    currentAngle = imu.readAngleZ()
    err1 = (targetAngle-currentAngle)%360.0
    err2 = (currentAngle-targetAngle)%360.0
    integral = 0.0
    lastError = 0.0
    if err1 < err2:
        err = -err1
    else:
        err = err2
    while abs(err) > PRECISION_DEGREES:
        currentTime = time.time()
        currentAngle = imu.readAngleZ()
        logging.debug("current angle = {0:.3f}°".format(currentAngle))
        err1 = (targetAngle-currentAngle)%360.0
        logging.debug("current err1 = {0:.3f}°".format(err1))
        err2 = (currentAngle-targetAngle)%360.0
        logging.debug("current err2 = {0:.3f}°".format(err2))
        if err1 < err2:
            err = -err1
            minThrottle = -MIN_THROTTLE
        else:
            err = err2
            minThrottle = MIN_THROTTLE

        dt = currentTime - lastTime
        integral += err * dt
        deriv = (err - lastError) / dt
        direction = minThrottle + (KP * err) + (KI * integral) + (KD * deriv)
        lastTime = currentTime
        lastError = err

        if direction > MAX_THROTTLE:
            direction = MAX_THROTTLE
        elif direction < -MAX_THROTTLE:
            direction = -MAX_THROTTLE
        logging.debug("direction = {0}".format(direction))
        driver.setDirection(direction)
        time.sleep(PID_PERIOD)

    logging.info("Target reached")
    driver.setNeutral()

#driver = Driver.createForTesting()
#imu = ImuDummy(0.0)
driver = Driver.createForRobot()
imu = Imu6050()

logging.info("Init IMU")
imu.start()
logging.info("Init driver")
driver.start()

try:

    turnTo(45.0, imu, driver)
    time.sleep(1)
    turnTo(315.0, imu, driver)
    time.sleep(1)
    turnTo(0.0, imu, driver)
    time.sleep(1)
    turnTo(180.0, imu, driver)
    time.sleep(1)
    turnTo(270.0, imu, driver)
    time.sleep(1)
    turnTo(0.0, imu, driver)
    time.sleep(1)

finally:
    driver.stop()
    imu.stop()


text:
<?
namespace Concrete\Controller\SinglePage\Dashboard\System\Registration;
use \Concrete\Core\Page\Controller\DashboardPageController;
use Config;
use Loader;

class Profiles extends DashboardPageController {

	public $helpers = array('form');

	public function update_profiles() {
		if ($this->isPost()) {
			Config::save('concrete.user.profiles_enabled', ($this->post('public_profiles')?true:false));
			Config::save('concrete.user.gravatar.enabled', ($this->post('gravatar_fallback')?true:false));
			Config::save('concrete.user.gravatar.max_level', Loader::helper('security')->sanitizeString($this->post('gravatar_max_level')));
			Config::save('concrete.user.gravatar.image_set', Loader::helper('security')->sanitizeString($this->post('gravatar_image_set')));
			// $message = ($this->post('public_profiles')?t('Public profiles have been enabled'):t('Public profiles have been disabled.'));
            if($this->post('public_profiles')) {
			    $this->redirect('/dashboard/system/registration/profiles/profiles_enabled');
            } else {
                $this->redirect('/dashboard/system/registration/profiles/profiles_disabled');
            }
		}
	}

    public function profiles_enabled(){
        $this->set('message', t('Public profiles have been enabled'));
        $this->view();
    }

    public function profiles_disabled(){
        $this->set('message', t('Public profiles have been disabled'));
        $this->view();
    }

	public function view($message = NULL) {
		if($message) {
			$this->set('message',$message);
		}
    $this->token = Loader::helper('validation/token');

    $this->set('public_profiles',Config::get('concrete.user.profiles_enabled'));
    $this->set('gravatar_fallback', Config::get('concrete.user.gravatar.enabled'));
    $this->set('gravatar_max_level', Config::get('concrete.user.gravatar.max_level'));
    $this->set('gravatar_level_options', array('g' => 'G', 'pg' => 'PG', 'r' => 'R', 'x' => 'X'));
    $this->set('gravatar_image_set', Config::get('concrete.user.gravatar.image_set'));
    $this->set('gravatar_set_options', array('404' => '404', 'mm' => 'mm', 'identicon' => 'identicon', 'monsterid' => 'monsterid', 'wavatar' => "wavatar"));
	}
}


text:
package cn.flyaudio.widgetswitch.view;

import static cn.flyaudio.widgetswitch.alltools.Constants.delectIds;
import static cn.flyaudio.widgetswitch.alltools.Constants.iconIds;
import static cn.flyaudio.widgetswitch.alltools.Constants.lableIds;
import static cn.flyaudio.widgetswitch.alltools.Constants.shortcutIds;
import static cn.flyaudio.widgetswitch.alltools.Constants.viewIds;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.SystemProperties;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
//import cn.flyaudio.widgetswitch.R;

import cn.flyaudio.widgetswitch.alltools.AppWidgetService;
import cn.flyaudio.widgetswitch.alltools.Constants;
import cn.flyaudio.widgetswitch.alltools.DrawableTools;
import cn.flyaudio.widgetswitch.alltools.Flog;
import cn.flyaudio.widgetswitch.alltools.FlyShortcutXMLParser;
import cn.flyaudio.widgetswitch.alltools.SetConmmonView;
import cn.flyaudio.widgetswitch.alltools.SkinResource;
import cn.flyaudio.widgetswitch.db.AppWidgetDao;
import cn.flyaudio.widgetswitch.state.BrightnessButton;
import cn.flyaudio.widgetswitch.state.FlyModel;
import cn.flyaudio.widgetswitch.state.MobileDataButton;
import cn.flyaudio.widgetswitch.state.WifiApButton;
import cn.flyaudio.widgetswitch.state.WifiButton;

public class SwitchWidget extends AppWidgetProvider {

	public static final String TAG = Constants.TAG;
	public static AppWidgetManager appWidgetManager = null;
	public static Map<String, String> flyShortcutNeedShow = null;
	private static Drawable whiteBg = null;
	private static SetConmmonView set1;
	private boolean isUpdate = true;

	public static int[] shuzi = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	public static String[] broadcast = new String[] {
			"cn.flyaudio.shortcut.bright.picture",
			"cn.flyaudio.shortcut.wifiAP.picture",
			"cn.flyaudio.shortcut.jiasu.picture",
			"cn.flyaudio.shortcut.reset.picture",
			"cn.flyaudio.shortcut.data.picture",
			"cn.flyaudio.shortcut.wifi.picture",
			"cn.flyaudio.shortcut.fly.picture",
			"cn.flyaudio.shortcut.system.picture",
			"cn.flyaudio.shortcut.car.picture",
			"cn.flyaudio.shortcut.screen.picture" };
	private Picturechange picturechange;

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		super.onReceive(context, intent);
		String action = intent.getAction();
		Log.e("lixuanbright", "actionaction=====" + action);
		if (action.equals(Intent.ACTION_LOCALE_CHANGED)) {
			Log.d("lixuanbright", "onReceive====android.intent.action.LOCALE_CHANGED");
		} else if (action.equals("android.appwidget.action.APPWIDGET_UPDATE")) {

			Log.d("lixuanbright", "===APPWIDGET_UPDATE   =  =======");
			RemoteViews remoteViews = null;
			if (SwitchWidget.appWidgetManager == null) {
				SwitchWidget.appWidgetManager = AppWidgetManager
						.getInstance(context);
			}

			flyShortcutNeedShow = initFlyApp(); // 得到解析XML数据 data
			Flog.d(TAG, "lyl-------onUpdate-------flyShortcutNeedShow="
					+ flyShortcutNeedShow);

			for (int appWidgetId : appWidgetIds) { // appWidgetIds
				// Flog.d(TAG, "appWidgetId:" + appWidgetId);
				Log.d("lixuanbright", "appWidgetId  循环次数   =  ==" + appWidgetId);
				AppWidgetDao.saveAppWidgetId(context, appWidgetId); // 对appWidgetId存储
				remoteViews = initRemoteViews(context, appWidgetId); // restore
																		// shortcut
																		// had
																		// been
																		// set

				dataRestore(context, appWidgetId, remoteViews, false);
				appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
			}

		}
	}

	private int[] appWidgetIds;

	@Override
	// 周期更新时调用
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		Log.d("lixuanbright", "  onUpdate= == ==   ");
		this.appWidgetIds = appWidgetIds;

	}

	@Override
	public void onEnabled(Context context) {
		// TODO Auto-generated method stub
		Log.d("lixuanbright", "  --------          -onEnabled    -  -----    ");

		context.startService(new Intent(context, AppWidgetService.class));
		IntentFilter intentFilter = new IntentFilter();
		intentFilter
				.addAction("com.android.systemui.updatebrightnessstate");
		intentFilter.addAction("android.intent.action.AIRPLANE_MODE");
		intentFilter
				.addAction("com.android.flyaudio.powerwidget.mobiledatabutton");
		intentFilter.addAction("android.net.wifi.WIFI_AP_STATE_CHANGED");
		intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
		picturechange = new Picturechange();
		context.getApplicationContext().registerReceiver(picturechange,
				intentFilter);
		super.onEnabled(context);
	}

	/**
	 * initialize a remoteViews set click pendingIntent with start
	 * 初始化一个remoteViews,具有点击事件,4个PendingInten,当点击插件4个+加好型的图标,启动AppSelectActivity
	 * 同时有 发送cn.flyaudio.shortcut.edititem广播,,, 具有编辑功能 设置好Widget 的背景!
	 * AppSelectActivity
	 *
	 * @param context
	 * @param appWidgetId
	 * @return
	 */
	public static RemoteViews initRemoteViews(Context context, int appWidgetId) {
		// RemoteViews remoteViews;
		// remoteViews = new RemoteViews(context.getPackageName(),
		// R.layout.widget_layout); // 插件布局
		Log.d("lixuanbright", "initRemoteViews   =  ==");
		RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
				.getPackageName(),
				SkinResource.getSkinLayoutIdByName("widget_layout"));
		/*
		 * if (flyShortcutNeedShow == null) { flyShortcutNeedShow =
		 * initFlyApp(); }
		 */
		for (int index = 0; index < Constants.viewIds.length; index++) { // 4个PendingInten,当点击插件4个图标,
			Intent intent = new Intent(context, AppSelectActivity.class); // 启动AppSelectActivity
			intent.putExtra(Constants.KEY_VIEW_ID, index); // viewId
			intent.putExtra(Constants.KEY_APPWIDGET_ID, appWidgetId); // appWidgetId
			// the second parameter must be set to distinguish different
			// PendingIntent
			PendingIntent selectIntent = PendingIntent.getActivity(context,
					appWidgetId * Constants.viewIds.length // viewIds.length=4
							+ index, intent, PendingIntent.FLAG_UPDATE_CURRENT);
			remoteViews.setOnClickPendingIntent(Constants.viewIds[index],
					selectIntent);
			if (Constants.DEBUG)
				Flog.d(TAG, "[ShortcutWidget initRemoteViews] appWidgetId:"
						+ appWidgetId + " viewId:" + Constants.viewIds[index]);

		}

		/*
		 * Intent intent_text = new Intent(context, AppSelectActivity.class);
		 * intent_text.putExtra("titlesId", 0);
		 * intent_text.putExtra(Constants.KEY_APPWIDGET_ID, appWidgetId);
		 * PendingIntent textIntent = PendingIntent.getActivity(context,
		 * appWidgetId * Constants.titles.length + 0, intent_text,
		 * PendingIntent.FLAG_UPDATE_CURRENT);
		 * remoteViews.setOnClickPendingIntent(Constants.titles[0], textIntent);
		 */

		Intent intent_edit = new Intent("cn.flyaudio.switchwidgetcut.edititem"); // 发送
																					// 点击编辑的Intent,,,,
		intent_edit.putExtra("titlesId", 1);
		intent_edit.putExtra("isEdit", true);
		intent_edit.putExtra(Constants.KEY_APPWIDGET_ID, appWidgetId);
		PendingIntent editIntent = PendingIntent.getBroadcast(context,
				appWidgetId * Constants.titles.length + 1, intent_edit,
				PendingIntent.FLAG_UPDATE_CURRENT);
		remoteViews.setOnClickPendingIntent(Constants.titles[1], editIntent);

		// set background color theme

		whiteBg = SkinResource
				.getSkinContext()
				.getResources()
				.getDrawable(
						SkinResource
								.getSkinDrawableIdByName("color_changed_background"));
		Drawable drawable = SkinResource
				.getSkinContext()
				.getResources()
				.getDrawable(
						SkinResource
								.getSkinDrawableIdByName("widget_layout_bg"));

		Bitmap bitmap = DrawableTools.drawableToBitmap(drawable);
		bitmap = DrawableTools.colorChange(bitmap, whiteBg);
		remoteViews.setImageViewBitmap(
				SkinResource.getSkinResourceId("widget_background", "id"),
				bitmap);
		return remoteViews;
	}

	/**
	 * restore the remoteViews app which have set from database
	 *
	 * @param context
	 * @param appWidgetId
	 * @param view
	 */
	public static void dataRestore(Context context, int appWidgetId,
			RemoteViews view, boolean isEdit) {
		Log.d("lixuanbright", "dataRestore    ==");
		// Flog.d(TAG, "lyl-----------dataRestore:appWidgetId=" + appWidgetId);
		// data persistence:restore from database
		set1 = new SetConmmonView();
		AppWidgetDao dao = new AppWidgetDao(context);
		int[] pkgNames = dao.query2(appWidgetId); // 查询数据库。得到pkgNames的值,存到数组中
		int[] iconAll = dao.query1(appWidgetId);

		boolean flag = false;

		for (int i = 0; i < Constants.viewIds.length; i++) {

			if (pkgNames.length == 0 || pkgNames[i] == 0) {
				Flog.d("lixuanupdata", "onupdate==pkgNames   - ------");
				continue;
			}
			flag = true;
			int name = pkgNames[i];
			try {
				for (int x : shuzi) {
					// set click event //设置点击有程序图标的点击事件。。。。
					if (name == (AppSelectActivity.titless2[x])) {
						Log.d("lixuanbright", "dataRestore  -- =  ==" + name
								+ "         " + AppSelectActivity.titless2[x]
								+ "        " + x);
						if (x != 8) {
							Intent intent_d = new Intent(broadcast[x]);
							intent_d.putExtra(Constants.KEY_VIEW_ID, i);
							intent_d.putExtra(Constants.KEY_APPWIDGET_ID,
									appWidgetId);

							PendingIntent pendingIntent_d = PendingIntent
									.getBroadcast(context, appWidgetId
											* Constants.viewIds.length + i,
											intent_d,
											PendingIntent.FLAG_UPDATE_CURRENT);

							view.setOnClickPendingIntent(
									Constants.shortcutIds[i], pendingIntent_d);
						} else {

							// 启动cheji的Intent,
							Intent intent = new Intent().setClass(context,
									AppWidgetService.class);
							intent.putExtra(Constants.KEY_VIEW_ID, i);
							intent.putExtra(Constants.KEY_APPWIDGET_ID,
									appWidgetId);
							intent.putExtra(Constants.KEY_FLYAPP, 120);
							PendingIntent pendingIntent = PendingIntent
									.getService(context, (appWidgetId
											* viewIds.length + i) * 10, intent,
											PendingIntent.FLAG_UPDATE_CURRENT);
							view.setOnClickPendingIntent(shortcutIds[i],
									pendingIntent);
						}

						if (isEdit) // 是否可编辑
						{
							editModel(context, appWidgetId, view, i);

						} else {
							Log.d("lixuanbright", "editModel=======else");
							view.setViewVisibility(delectIds[i], View.GONE);
							Drawable icon = SkinResource
									.getSkinContext()
									.getResources()
									.getDrawable(
											SkinResource
													.getSkinDrawableIdByName("widget_edit"));
							view.setImageViewBitmap(Constants.titles[1],
									DrawableTools.drawableToBitmap(icon));
						}

					} else {
						continue;
					}
					if (name == (AppSelectActivity.titless2[0])) {
						Log.d("lixuanbright", "亮度               "+name);
						set1.setCommonView2(context, view, i, iconAll[i],
								pkgNames[i]);
					} else {
						Log.d("lixuanbright", "不是亮度       "+name);
						set1.setCommonView(context, view, i, iconAll[i],
								pkgNames[i]);
					}
				} // for循环结束

			} catch (Exception e) {
				// TODO Auto-generated catch block
				Flog.d("lixuan", "55" + i);
				e.printStackTrace();
			}
		} // 一个Constants.viewIds 的for结束

		if (!flag) { // widget上面的编辑图标 titles【1】
			Drawable icon = SkinResource
					.getSkinContext()
					.getResources()
					.getDrawable(
							SkinResource.getSkinDrawableIdByName("widget_edit"));
			view.setImageViewBitmap(Constants.titles[1],
					DrawableTools.drawableToBitmap(icon));
		}
		// update remoteViews
		AppWidgetManager appWidgetManager = AppWidgetManager
				.getInstance(context);
		appWidgetManager.updateAppWidget(appWidgetId, view);
		dao.close();
	}

	private static void editModel(Context context, int appWidgetId,
			RemoteViews view, int i) {
		view.setViewVisibility(delectIds[i], View.VISIBLE);
		Intent intent_d = new Intent("cn.flyaudio.switchwidgetcut.delectitem");
		intent_d.putExtra(Constants.KEY_VIEW_ID, i);
		intent_d.putExtra(Constants.KEY_APPWIDGET_ID, appWidgetId);
		PendingIntent pendingIntent_d = PendingIntent.getBroadcast(context,
				appWidgetId * Constants.viewIds.length + i, intent_d,
				PendingIntent.FLAG_UPDATE_CURRENT);
		// view.setOnClickPendingIntent(delectIds[i], pendingIntent_d);
		view.setOnClickPendingIntent(Constants.shortcutIds[i], pendingIntent_d);
		// String text =
		// context.getResources().getString(R.string.widget_Canceledit);
		/*
		 * Drawable icon = context.getResources().getDrawable(
		 * R.drawable.widget_canceledit);
		 */

		Drawable icon = SkinResource
				.getSkinContext()
				.getResources()
				.getDrawable(
						SkinResource
								.getSkinDrawableIdByName("widget_canceledit"));
		view.setImageViewBitmap(Constants.titles[1],
				DrawableTools.drawableToBitmap(icon));

		Flog.d(TAG, "editModel----------:appWidgetId=" + appWidgetId);

		for (int index = 0; index < Constants.viewIds.length; index++) {
			Intent intent_edit = new Intent(
					"cn.flyaudio.switchwidgetcut.edititem");

			intent_edit.putExtra("titlesId", 1);
			intent_edit.putExtra("isEdit", false);
			intent_edit.putExtra(Constants.KEY_APPWIDGET_ID, appWidgetId);
			PendingIntent editIntent = PendingIntent.getBroadcast(context,
					appWidgetId * Constants.titles.length + 1, intent_edit,
					PendingIntent.FLAG_UPDATE_CURRENT);
			view.setOnClickPendingIntent(Constants.viewIds[index], editIntent);
		}

	}

	private static Map<String, String> initFlyApp() {
		InputStream f = null;
		String path = SystemProperties.get("persist.fly.car.select", "default"); // 通过这个接口可以对系统的属性进行读取
		path = "flysystem/flyconfig/" + path
				+ "/uiconfig/flyshortcutconfig.xml";
		try {
			f = new FileInputStream(new File(path));
		} catch (Exception e) {
			f = null;
		}
		Flog.d(TAG, "lyl-------initFlyApp()-------f=" + f);
		FlyShortcutXMLParser parser = new FlyShortcutXMLParser();
		return ((FlyShortcutXMLParser) cn.flyaudio.widgetswitch.alltools.XMLTool
				.parse(f, parser)).getData(); // 得到解析XML数据 data
	}

	@Override
	public void onDisabled(Context context) {
		// TODO Auto-generated method stub
		Log.d("lixuanbright", "onDisabled:");
		super.onDisabled(context);
		context.stopService(new Intent(context, AppWidgetService.class));

	}

	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		// TODO Auto-generated method stub
		super.onDeleted(context, appWidgetIds);
		for (int appWidgetId : appWidgetIds) {
			Log.d(TAG, "[ShortcutWidget onDeleted] appWidgetId:" + appWidgetId);
			// data persistence:deleted
			new AppWidgetDao(context).delete(appWidgetId).close();
			AppWidgetDao.removeAppWidgetId(context, appWidgetId);
		}
	}

	class Picturechange extends BroadcastReceiver {

		private WifiButton wifiButton;
		private WifiApButton wifiapButton;
		private FlyModel flymode;
		private MobileDataButton wifidata;
		private Boolean datastate;
		private BrightnessButton brightness;

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			// wifi 状态改变的广播,使图片改变
			if (intent.getAction()
					.equals("android.net.wifi.WIFI_STATE_CHANGED")) {
				// Flog.d("lixuanwifi", "Action=" + intent.getAction());
				AppWidgetDao dao = new AppWidgetDao(context);
				List<Picture> three = dao.queryPkgName();
				Iterator<Picture> it = three.iterator();
				wifiButton = new WifiButton();

				while (it.hasNext()) {
					Picture threes = (Picture) it.next();
					int name = threes.getPkgNames();
					int index = threes.getIndexViewId();
					int appWidgetId = threes.getAppWidgetId();

					if (name == AppSelectActivity.titless2[5]) {
						RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
								.getPackageName(),
								SkinResource.getSkinLayoutIdByName("widget_layout"));
						int x = wifiButton.getActualStatemy(context);
						if ((2 == x) || (4 == x) || (6 == x)) {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor", Color.WHITE);
						} else {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor",
									DrawableTools.getCurColorTheme());
						}

						setCommonView1(remoteViews, index, 5);
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						appWidgetManager.updateAppWidget(appWidgetId,
								remoteViews);
					}
				}
			}
			// 改变 AP图片的广播
			if (intent.getAction().equals(
					"android.net.wifi.WIFI_AP_STATE_CHANGED")) {
				// Flog.d("lixuanwifiAP", "Action=" + intent.getAction());
				AppWidgetDao dao = new AppWidgetDao(context);
				List<Picture> three = dao.queryPkgName();
				wifiapButton = new WifiApButton();
				Iterator<Picture> it = three.iterator();

				while (it.hasNext()) {
					Picture threes = (Picture) it.next();
					int name = threes.getPkgNames();
					int index = threes.getIndexViewId();
					int appWidgetId = threes.getAppWidgetId();

					if (name == AppSelectActivity.titless2[1]) {
						RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
								.getPackageName(),
								SkinResource.getSkinLayoutIdByName("widget_layout"));
						int x = wifiapButton.getActualStatemy(context);
						if ((2 == x) || (4 == x) || (6 == x)) {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor", Color.WHITE);
						} else {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor",
									DrawableTools.getCurColorTheme());
						}
						setCommonView1(remoteViews, index, 1);
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						appWidgetManager.updateAppWidget(appWidgetId,
								remoteViews);
					}
				}
			}
			// 改变数据流量的广播
			if (intent.getAction().equals(
					"com.android.flyaudio.powerwidget.mobiledatabutton")) {
				// Flog.d("lixuandata", "Action=" + intent.getAction());
				Log.d("lixuandata",
						"Action=====WifiChange" + intent.getAction());
				AppWidgetDao dao = new AppWidgetDao(context);
				List<Picture> three = dao.queryPkgName();
				Iterator<Picture> it = three.iterator();
				wifidata = new MobileDataButton(context);
				while (it.hasNext()) {
					Picture threes = (Picture) it.next();
					int name = threes.getPkgNames();
					int index = threes.getIndexViewId();
					int appWidgetId = threes.getAppWidgetId();
					if (name == AppSelectActivity.titless2[4]) {
						RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
								.getPackageName(),
								SkinResource.getSkinLayoutIdByName("widget_layout"));
						datastate = wifidata.getActualStatemy(context);
						if (!datastate) {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor", Color.WHITE);
						} else {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor",
									DrawableTools.getCurColorTheme());
						}

						setCommonView1(remoteViews, index, 4);
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						appWidgetManager.updateAppWidget(appWidgetId,
								remoteViews);
					}
				}
			}
			// 改变飞行模式的图片广播
			if (intent.getAction()
					.equals("android.intent.action.AIRPLANE_MODE")) {
				// Flog.d("lixuanflystate", "Action=" + intent.getAction());
				AppWidgetDao dao = new AppWidgetDao(context);
				List<Picture> three = dao.queryPkgName();
				flymode = new FlyModel();
				Iterator<Picture> it = three.iterator();

				while (it.hasNext()) {

					Picture threes = (Picture) it.next();
					int name = threes.getPkgNames();
					int index = threes.getIndexViewId();
					int appWidgetId = threes.getAppWidgetId();

					if (name == AppSelectActivity.titless2[6]) {

						RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
								.getPackageName(),
								SkinResource.getSkinLayoutIdByName("widget_layout"));
						Boolean flystate = flymode.getActualState(context);

						if (!flystate) {
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor", Color.WHITE);
						} else {
							// Flog.d("lixuanflystate", "设置图片的背景色 系统色" +
							// flystate);
							remoteViews.setInt(iconIds[index],
									"setBackgroundColor",
									DrawableTools.getCurColorTheme());
						}

						setCommonView1(remoteViews, index, 6);
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						appWidgetManager.updateAppWidget(appWidgetId,
								remoteViews);
					}
				}
			}
			// 接收改变 亮度图片的广播
			if (intent.getAction().equals(
					"com.android.systemui.updatebrightnessstate")) {
				Log.d("lixuanbright", "intend=" + intent.getAction());
				brightness = new BrightnessButton();
				brightness.changeCurrentBrightness(context, intent);
				int x = brightness.getActualState(context);
				Log.d("lixuanbright", "intend= =  =  =  x      " + x);
				AppWidgetDao dao = new AppWidgetDao(context);
				List<Picture> three = dao.queryPkgName();
				Iterator<Picture> it = three.iterator();

				while (it.hasNext()) {
					// Flog.d("lixuanbright", "进入while循环");
					Picture threes = (Picture) it.next();
					int name = threes.getPkgNames();
					int index = threes.getIndexViewId();
					int appWidgetId = threes.getAppWidgetId();

					if (name == AppSelectActivity.titless2[0]) {
						RemoteViews remoteViews = new RemoteViews(SkinResource.getSkinContext()
								.getPackageName(),
								SkinResource.getSkinLayoutIdByName("widget_layout"));
						if (0 == x || 1 == x) {
							remoteViews.setImageViewResource(iconIds[index],
									AppSelectActivity.statepic_light[0]);
							Log.d("lixuanbright", "进入x====" + x);
							remoteViews
									.setTextViewText(
											lableIds[index],
											SkinResource
													.getSkinStringById(AppSelectActivity.titless_bright[0])); //
						} else if (2 == x) {
							// Flog.d("lixuanbright", "x====2");
							remoteViews.setImageViewResource(iconIds[index],
									AppSelectActivity.statepic[0]);
							remoteViews
									.setTextViewText(
											lableIds[index],
											SkinResource
													.getSkinStringById(AppSelectActivity.titless_bright[1]));
						} else if (3 == x) {
							remoteViews.setImageViewResource(iconIds[index],
									AppSelectActivity.statepic_light[1]);
							remoteViews
									.setTextViewText(
											lableIds[index],
											SkinResource
													.getSkinStringById(AppSelectActivity.titless_bright[2]));
						}
						AppWidgetManager appWidgetManager = AppWidgetManager
								.getInstance(context);
						appWidgetManager.updateAppWidget(appWidgetId,
								remoteViews);

					}
				}
			}
			// 接收改变 的Share 值
			if (intent.getAction().equals(
					"cn.flyaudio.systemui.changebrightness")) {
				Log.d("lixuanbright", "intend=" + intent.getAction());
				brightness = new BrightnessButton();
				brightness.changeCurrentBrightness(context, intent);
			}

		}

		private void setCommonView1(RemoteViews remoteViews, int indexViewId,
				int x) {
			remoteViews.setImageViewResource(iconIds[indexViewId],
					AppSelectActivity.statepic[x]);
		}
	}
}


text:
class FSEvent::FileEvent::DirectoryState
  attr_reader :path

  # * _path_: the path to a directory.
  # * _glob_: the glob pattern used to list the files in _path_.
  #
  # _glob_ is optional and defaults to "*".
  #
  # Don't use recursive globs (e.g.: "**/*"), FileEvent will create one
  # DirectoryState instance for each subfolder in a watched path, as need
  # arises.
  def initialize(path, glob = nil)
    @path       = File.expand_path(path)
    @glob       = glob || "*"
    @file_stats = {}
  end

  # Update the :hot status for the watched files in #path.
  #
  # A path is marked hot if:
  # * its _mtime_ is newer than it was during last #refresh!, or
  # * its _mtime_ is not older than 60 seconds and we don't have a previous
  #   _mtime_ entry for it.
  #
  # You can get a list of currently hot paths by calling #hot_paths.
  def refresh!
    now = Time.now
    candidate_paths = Dir[File.join(path, @glob)].select { |path| File.file? path }
    (@file_stats.keys - candidate_paths).each { |k| @file_stats.delete(k) }
    candidate_paths.each do |path|
      h_stat            = @file_stats[path] ||= {}
      mtime             = File.mtime(path)
      h_stat[:hot]      = h_stat[:mtime]  ?  mtime > h_stat[:mtime]  :  now - mtime < 60.0 # ∆t in seconds
      h_stat[:mtime]    = mtime
      @file_stats[path] = h_stat
    end
    self
  end

  # Return the paths that have been marked :hot during last #refresh!.
  def hot_paths
    @file_stats.select { |k, hv| hv[:hot] }.map { |k, v| k }
  end

  # You should call touch on paths that you modify after a #refresh!.
  #
  # When your code updates a file that a path points to, this path may be sent
  # back to the fsevents stream, at which point it may change it again, and
  # now you risk entering a (potentially infinite) loop.
  #
  # #touch only needs to be called if you have modified the file at _path_.
  # It is, however, harmless to call it otherwise.
  def touch(path, time = Time.now)
    @file_stats[path][:mtime] = time
  end
end


text:
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved
// Plugin written by Philipp Buerki. Copyright 2017. All Rights reserved..

#pragma once

#include "CoreMinimal.h"
#include "UObject/CoreOnline.h"
#include "OnlineSubsystemB3atZTypes.h"
#include "OnlineDelegateMacros.h"

/**
 * Account credentials needed to sign in to an online service
 */
class FOnlineAccountCredentials
{
public:

	/** Type of account. Needed to identity the auth method to use (epic, internal, facebook, etc) */
	FString Type;
	/** Id of the user logging in (email, display name, facebook id, etc) */
	FString Id;
	/** Credentials of the user logging in (password or auth token) */
	FString Token;

	/**
	 * Equality operator
	 */
	bool operator==(const FOnlineAccountCredentials& Other) const
	{
		return Other.Type == Type &&
			Other.Id == Id;
	}

	/**
	 * Constructor
	 */
	FOnlineAccountCredentials(const FString& InType, const FString& InId, const FString& InToken) :
		Type(InType),
		Id(InId),
		Token(InToken)
	{
	}

	/**
	 * Constructor
	 */
	FOnlineAccountCredentials()
	{
	}
};

namespace EUserPrivileges
{
	enum Type
	{
		/** Whether the user can play at all, online or offline - may be age restricted */
		CanPlay,
		/** Whether the user can play in online modes */
		CanPlayOnline,
		/** Whether the user can use voice and text chat */
		CanCommunicateOnline,
		/** Whether the user can use content generated by other users */
		CanUseUserGeneratedContent
	};
}

/**
 * Delegate called when a player logs in/out
 *
 * @param LocalUserNum the controller number of the associated user
 */
DECLARE_MULTICAST_DELEGATE_OneParam(FOnLoginChanged, int32 /*LocalUserNum*/);
typedef FOnLoginChanged::FDelegate FOnLoginChangedDelegate;

/**
 * Delegate called when a player's status changes but doesn't change profiles
 *
 * @param LocalUserNum the controller number of the associated user
 * @param OldStatus the old login status for the user
 * @param NewStatus the new login status for the user
 * @param NewId the new id to associate with the user
 */
DECLARE_MULTICAST_DELEGATE_FourParams(FOnLoginStatusChanged, int32 /*LocalUserNum*/, ELoginStatusB3atZ::Type /*OldStatus*/, ELoginStatusB3atZ::Type /*NewStatus*/, const FUniqueNetId& /*NewId*/);
typedef FOnLoginStatusChanged::FDelegate FOnLoginStatusChangedDelegate;

/**
 * Delegate called when a controller-user pairing changes
 *
 * @param LocalUserNum the controller number of the controller whose pairing changed
 * @param PreviousUser the user that used to be paired with this controller
 * @param NewUser the user that is currently paired with this controller
 */
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnControllerPairingChanged, int /*LocalUserNum*/, const FUniqueNetId& /*PreviousUser*/, const FUniqueNetId& /*NewUser*/);
typedef FOnControllerPairingChanged::FDelegate FOnControllerPairingChangedDelegate;

/**
 * Called when user account login has completed after calling Login() or AutoLogin()
 *
 * @param LocalUserNum the controller number of the associated user
 * @param bWasSuccessful true if server was contacted and a valid result received
 * @param UserId the user id received from the server on successful login
 * @param Error string representing the error condition
 */
DECLARE_MULTICAST_DELEGATE_FourParams(FOnLoginComplete, int32 /*LocalUserNum*/, bool /*bWasSuccessful*/, const FUniqueNetId& /*UserId*/, const FString& /*Error*/);
typedef FOnLoginComplete::FDelegate FOnLoginCompleteDelegate;

/**
 * Delegate used in notifying the UI/game that the manual logout completed
 *
 * @param LocalUserNum the controller number of the associated user
 * @param bWasSuccessful whether the async call completed properly or not
 */
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnLogoutComplete, int32 /*LocalUserNum*/, bool /*bWasSuccessful*/);
typedef FOnLogoutComplete::FDelegate FOnLogoutCompleteDelegate;

/**
 * Interface for registration/authentication of user identities
 */
class IOnlineIdentity
{

protected:
	IOnlineIdentity() {};

public:

	enum class EPrivilegeResults
	{
		/** The user has the requested privilege */
		NoFailures				=	0,
		/** Patch required before the user can use the privilege */
		RequiredPatchAvailable	=	1 << 0,
		/** System update required before the user can use the privilege */
		RequiredSystemUpdate	=	1 << 1,
		/** Parental control failure usually */
		AgeRestrictionFailure	=	1 << 2,
		/** XboxLive Gold / PSPlus required but not available */
		AccountTypeFailure		=	1 << 3,
		/** Invalid user */
		UserNotFound			=	1 << 4,
		/** User must be logged in */
		UserNotLoggedIn			=	1 << 5,
		/** User restricted from chat */
		ChatRestriction			=	1 << 6,
		/** User restricted from User Generated Content */
		UGCRestriction			=	1 << 7,
		/** Platform failed for unknown reason and handles its own dialogs */
		GenericFailure			=	1 << 8,
	};

	virtual ~IOnlineIdentity() {};

	/**
	 * Delegate called when a player logs in/out
	 *
	 * @param LocalUserNum the player that logged in/out
	 */
	DEFINE_ONLINE_DELEGATE_ONE_PARAM(OnLoginChanged, int32);

	/**
	 * Delegate called when a player's login status changes but doesn't change identity
	 *
	 * @param LocalUserNum the controller number of the associated user
	 * @param OldStatus the previous status of the user
	 * @param NewStatus the new login status for the user
	 * @param NewId the new id to associate with the user
	 */
	DEFINE_ONLINE_PLAYER_DELEGATE_THREE_PARAM(MAX_LOCAL_PLAYERS, OnLoginStatusChanged, ELoginStatusB3atZ::Type /*Previous*/, ELoginStatusB3atZ::Type /*Current*/, const FUniqueNetId&);

	/**
	 * Delegate called when a controller-user pairing changes
	 *
	 * @param LocalUserNum the controller number of the associated user
	 * @param PreviousUser the new login status for the user
	 * @param NewUser the new id to associate with the user
	 */
	DEFINE_ONLINE_DELEGATE_THREE_PARAM(OnControllerPairingChanged, int, const FUniqueNetId&, const FUniqueNetId&);

	/**
	 * Login/Authenticate with user credentials.
	 * Will call OnLoginComplete() delegate when async task completes
	 *
	 * @param LocalUserNum the controller number of the associated user
	 * @param AccountCredentials user account credentials needed to sign in to the online service
	 *
	 * @return true if login task was started
	 */
	virtual bool Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials) = 0;

	/**
	 * Called when user account login has completed after calling Login() or AutoLogin()
	 *
	 * @param LocalUserNum the controller number of the associated user
	 * @param bWasSuccessful true if server was contacted and a valid result received
	 * @param UserId the user id received from the server on successful login
	 * @param Error string representing the error condition
	 */
	DEFINE_ONLINE_PLAYER_DELEGATE_THREE_PARAM(MAX_LOCAL_PLAYERS, OnLoginComplete, bool, const FUniqueNetId&, const FString&);

	/**
	 * Signs the player out of the online service
	 * Will call OnLogoutComplete() delegate when async task completes
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return true if logout task was started
	 */
	virtual bool Logout(int32 LocalUserNum) = 0;

	/**
	 * Delegate used in notifying the that manual logout completed
	 *
	 * @param LocalUserNum the controller number of the associated user
	 * @param bWasSuccessful whether the async call completed properly or not
	 */
	DEFINE_ONLINE_PLAYER_DELEGATE_ONE_PARAM(MAX_LOCAL_PLAYERS, OnLogoutComplete, bool);

	/**
	 * Logs the player into the online service using parameters passed on the
	 * command line. Expects -AUTH_LOGIN=<UserName> -AUTH_PASSWORD=<password>. If either
	 * are missing, the function returns false and doesn't start the login
	 * process
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return true if the async call started ok, false otherwise
	 */
	virtual bool AutoLogin(int32 LocalUserNum) = 0;

	/**
	 * Obtain online account info for a user that has been registered
	 *
	 * @param UserId user to search for
	 *
	 * @return info about the user if found, NULL otherwise
	 */
	virtual TSharedPtr<FB3atZUserOnlineAccount> GetUserAccount(const FUniqueNetId& UserId) const = 0;

	/**
	 * Obtain list of all known/registered user accounts
	 *
	 * @param UserId user to search for
	 *
	 * @return info about the user if found, NULL otherwise
	 */
	virtual TArray<TSharedPtr<FB3atZUserOnlineAccount> > GetAllUserAccounts() const = 0;

	/**
	 * Gets the platform specific unique id for the specified player
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return Valid player id object if the call succeeded, NULL otherwise
	 */
	virtual TSharedPtr<const FUniqueNetId> GetUniquePlayerId(int32 LocalUserNum) const = 0;

	/**
	 * Gets the platform specific unique id for the sponsor of the specified player
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return Valid player id object if the sponsor exists, NULL otherwise
	 */
	virtual TSharedPtr<const FUniqueNetId> GetSponsorUniquePlayerId(int32 LocalUserNum) const { return nullptr; }

	/**
	 * Create a unique id from binary data (used during replication)
	 *
	 * @param Bytes opaque data from appropriate platform
	 * @param Size size of opaque data
	 *
	 * @return UniqueId from the given data, NULL otherwise
	 */
	virtual TSharedPtr<const FUniqueNetId> CreateUniquePlayerId(uint8* Bytes, int32 Size) = 0;

	/**
	 * Create a unique id from string
	 *
	 * @param Str string holding textual representation of an Id
	 *
	 * @return UniqueId from the given data, NULL otherwise
	 */
	virtual TSharedPtr<const FUniqueNetId> CreateUniquePlayerId(const FString& Str) = 0;

	/**
	 * Fetches the login status for a given player
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return the enum value of their status
	 */
	virtual ELoginStatusB3atZ::Type GetLoginStatus(int32 LocalUserNum) const = 0;

	/**
	 * Fetches the login status for a given player
	 *
	 * @param UserId the unique net id of the associated user
	 *
	 * @return the enum value of their status
	 */
	virtual ELoginStatusB3atZ::Type GetLoginStatus(const FUniqueNetId& UserId) const = 0;

	/**
	 * Reads the player's nick name from the online service
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return a string containing the players nick name
	 */
	//@todo - move to user interface
	virtual FString GetPlayerNickname(int32 LocalUserNum) const = 0;

	/**
	 * Reads the player's nick name from the online service
	 *
	 * @param UserId the unique net of the associated user
	 *
	 * @return a string containing the players nick name
	 */
	//@todo - move to user interface
	virtual FString GetPlayerNickname(const FUniqueNetId& UserId) const = 0;

	/**
	 * Gets a user's platform specific authentication token to verify their identity
	 *
	 * @param LocalUserNum the controller number of the associated user
	 *
	 * @return String representing the authentication token
	 */
	//@todo - remove and use GetUserAccount instead
	virtual FString GetAuthToken(int32 LocalUserNum) const = 0;

	/**
	 * Delegate executed when we get a user privilege result.
	 *
	 * @param UniqueId The unique id of the user who was queried
	 * @param Privilege the privilege that was queried
	 * @param PrivilegeResult bitwise OR of any privilege failures. 0 is success.
	 */
	DECLARE_DELEGATE_ThreeParams(FOnGetUserPrivilegeCompleteDelegate, const FUniqueNetId&, EUserPrivileges::Type, uint32);

	/**
	 * Gets the status of a user's privilege.
	 *
	 * @param UserId the unique id of the user to query
	 * @param Privilege the privilege you want to know about
	 * @param Delegate delegate to execute when the async task completes
	 */
	virtual void GetUserPrivilege(const FUniqueNetId& UserId, EUserPrivileges::Type Privilege, const FOnGetUserPrivilegeCompleteDelegate& Delegate) = 0;

	/**
	 * Temporary hack to get a corresponding FUniqueNetId from a PlatformUserId
	 *
	 * @param UniqueNetId The unique id to look up
	 * @return The corresponding id or PLATFORMID_NONE if not found
	 */
	virtual FPlatformUserId GetPlatformUserIdFromUniqueNetId(const FUniqueNetId& UniqueNetId) = 0;

	/**
	 * Get the auth type associated with accounts for this platform
	 *
	 * @return The auth type associated with accounts for this platform
	 */
	virtual FString GetAuthType() const = 0;
};

typedef TSharedPtr<IOnlineIdentity, ESPMode::ThreadSafe> IOnlineIdentityPtr;