text:
use std::ops::Neg;
use na::{Translation, POrd, Translate, Bounded};
use na;
use bounding_volume::BoundingVolume;
use math::{Scalar, Point, Vect};

/// Trait of objects that can be bounded by an AABB.
pub trait HasAABB
 {
    /// The object's AABB.
    fn aabb(&self, &M) -> AABB
;
}

// Seems useful to help type inference. See issue #84.
/// Computes the axis-aligned bounding box of a shape `g` transformed by `m`.
///
/// Same as `g.aabb(m)`.
pub fn aabb
(g: &G, m: &M) -> AABB

    where G: HasAABB
 {
    g.aabb(m)
}

/// An Axis Aligned Bounding Box.
#[derive(Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
pub struct AABB
 {
    mins: P,
    maxs: P
}

impl
 AABB
 {
    /// Creates a new AABB.
    ///
    /// # Arguments:
    ///   * `mins` - position of the point with the smallest coordinates.
    ///   * `maxs` - position of the point with the highest coordinates. Each component of `mins`
    ///   must be smaller than the related components of `maxs`.
    pub fn new(mins: P, maxs: P) -> AABB
 {
        assert!(na::partial_le(&mins, &maxs));

        AABB {
            mins: mins,
            maxs: maxs
        }
    }
}

impl<P: Neg<Output = P> + POrd + Bounded> AABB
 {
    /// Creates an invalid AABB with:
    /// * `mins = Bounded::max_value()`
    /// * `maxs = Bounded::max_value()`.
    /// This is useful to build aabb using merges.
    pub fn new_invalid() -> AABB
 {
        let _max: P = Bounded::max_value();
        AABB {
            mins: Bounded::max_value(),
            maxs: -_max,
        }
    }
}

impl
 AABB
 {
    /// Reference to the AABB point with the smallest components along each axis.
    #[inline]
    pub fn mins(&self) -> &P {
        &self.mins
    }

    /// Reference to the AABB point with the biggest components along each axis.
    #[inline]
    pub fn maxs(&self) -> &P {
        &self.maxs
    }
}

impl
 AABB

    where P: Point {
    /// The center of this AABB.
    #[inline]
    pub fn center(&self) -> P {
        na::center(&self.mins, &self.maxs)
    }

    /// The half extents of this AABB.
    #[inline]
    pub fn half_extents(&self) -> P::Vect {
        (self.maxs - self.mins) / na::cast(2.0f64)
    }
}

impl
 BoundingVolume<
::Scalar> for AABB

    where P: Point {
    #[inline]
    fn intersects(&self, other: &AABB
) -> bool {
        na::partial_le(&self.mins, &other.maxs) &&
        na::partial_ge(&self.maxs, &other.mins)
    }

    #[inline]
    fn contains(&self, other: &AABB
) -> bool {
        na::partial_le(&self.mins, &other.mins) &&
        na::partial_ge(&self.maxs, &other.maxs)
    }

    #[inline]
    fn merge(&mut self, other: &AABB
) {
        self.mins = na::inf(&self.mins, &other.mins);
        self.maxs = na::sup(&self.maxs, &other.maxs);
    }

    #[inline]
    fn merged(&self, other: &AABB
) -> AABB
 {
        AABB {
            mins: na::inf(&self.mins, &other.mins),
            maxs: na::sup(&self.maxs, &other.maxs)
        }
    }

    #[inline]
    fn loosen(&mut self, amount:
::Scalar) {
        assert!(amount >= na::zero(), "The loosening margin must be positive.");
        self.mins = self.mins + na::repeat(-amount);
        self.maxs = self.maxs + na::repeat(amount);
    }

    #[inline]
    fn loosened(&self, amount:
::Scalar) -> AABB
 {
        assert!(amount >= na::zero(), "The loosening margin must be positive.");
        AABB {
            mins: self.mins + na::repeat(-amount),
            maxs: self.maxs + na::repeat(amount)
        }
    }

    #[inline]
    fn tighten(&mut self, amount:
::Scalar) {
        assert!(amount >= na::zero(), "The tightening margin must be positive.");
        self.mins = self.mins + na::repeat(amount);
        self.maxs = self.maxs + na::repeat(-amount);
        assert!(na::partial_le(&self.mins, &self.maxs), "The tightening margin is to large.");
    }

    #[inline]
    fn tightened(&self, amount:
::Scalar) -> AABB
 {
        assert!(amount >= na::zero(), "The tightening margin must be positive.");

        AABB::new(self.mins + na::repeat(amount), self.maxs + na::repeat(-amount))
    }
}

impl
 Translation
 for AABB

    where P: Point,
          P::Vect: Translate
 {
    #[inline]
    fn translation(&self) -> P::Vect {
        na::center(&self.mins, &self.maxs).to_vec()
    }

    #[inline]
    fn inv_translation(&self) -> P::Vect {
        -self.translation()
    }

    #[inline]
    fn append_translation_mut(&mut self, dv: &P::Vect) {
        self.mins = self.mins + *dv;
        self.maxs = self.maxs + *dv;
    }

    #[inline]
    fn append_translation(&self, dv: &P::Vect) -> AABB
 {
        AABB::new(self.mins + *dv, self.maxs + *dv)
    }

    #[inline]
    fn prepend_translation_mut(&mut self, dv: &P::Vect) {
        self.append_translation_mut(dv)
    }

    #[inline]
    fn prepend_translation(&self, dv: &P::Vect) -> AABB
 {
        self.append_translation(dv)
    }

    #[inline]
    fn set_translation(&mut self, v: P::Vect) {
        let center = self.translation();
        let total_translation = center + v;

        self.mins = na::inv_translate(&total_translation, &self.mins);
        self.maxs = na::inv_translate(&total_translation, &self.maxs);
    }
}


text:
'use strict';

const AstNodeInfo = require('../helpers/ast-node-info');
const Rule = require('./base');

const message = 'Tables must have a table group (thead, tbody or tfoot).';
const orderingMessage =
  'Tables must have table groups in the correct order (caption, colgroup, thead, tbody then tfoot).';

const ALLOWED_TABLE_CHILDREN = ['caption', 'colgroup', 'thead', 'tbody', 'tfoot'];

// For effective children, we skip over any control flow helpers,
// since we know that they don't render anything on their own
function getEffectiveChildren(node) {
  const unflattenedEffectiveChildren = AstNodeInfo.childrenFor(node).map(node => {
    if (AstNodeInfo.isControlFlowHelper(node)) {
      return getEffectiveChildren(node);
    } else {
      return [node];
    }
  });

  return [].concat.apply([], unflattenedEffectiveChildren); // eslint-disable-line prefer-spread
}

function isAllowedTableChild(node) {
  let tagNamePair;
  let tagNameAttribute;
  let index;
  switch (node.type) {
    case 'BlockStatement':
    case 'MustacheStatement':
      tagNamePair = node.hash.pairs.find(pair => pair.key === 'tagName');
      if (tagNamePair) {
        index = ALLOWED_TABLE_CHILDREN.indexOf(tagNamePair.value.value);
        return { allowed: index > -1, index };
      } else if (node.path.original === 'yield') {
        return { allowed: true, index: -1 };
      }
      break;
    case 'ElementNode':
      index = ALLOWED_TABLE_CHILDREN.indexOf(node.tag);
      if (index > -1) {
        return { allowed: true, index };
      }
      tagNameAttribute = node.attributes.find(attribute => attribute.name === '@tagName');
      if (tagNameAttribute) {
        index = ALLOWED_TABLE_CHILDREN.indexOf(tagNameAttribute.value.chars);
        return { allowed: index > -1, index };
      }
      break;
    case 'CommentStatement':
    case 'MustacheCommentStatement':
      return { allowed: true, index: -1 };
    case 'TextNode':
      return { allowed: !/\S/.test(node.chars), index: -1 };
  }

  return { allowed: false };
}

module.exports = class TableGroups extends Rule {
  visitor() {
    return {
      ElementNode(node) {
        if (node.tag === 'table') {
          const children = getEffectiveChildren(node);
          let currentAllowedIndex = 0;
          for (let i = 0; i < children.length; i++) {
            const allowedWithIndex = isAllowedTableChild(children[i]);
            if (!allowedWithIndex.allowed) {
              this.log({
                message,
                line: node.loc && node.loc.start.line,
                column: node.loc && node.loc.start.column,
                source: this.sourceForNode(node),
              });
              break;
            }
            if (allowedWithIndex.index > -1 && allowedWithIndex.index < currentAllowedIndex) {
              this.log({
                message: orderingMessage,
                line: node.loc && node.loc.start.line,
                column: node.loc && node.loc.start.column,
                source: this.sourceForNode(node),
              });
              break;
            }
            currentAllowedIndex = allowedWithIndex.index;
          }
        }
      },
    };
  }
};

module.exports.message = message;
module.exports.orderingMessage = orderingMessage;

redpajama_set_name: RedPajamaGithub


text:
package com.astudio.android.bitmapfun.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.content.Context;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;

import com.astudio.inspicsoc.BuildConfig;
import com.astudio.inspicsoc.common.InsUrl;

/**
 * A simple subclass of {@link ImageResizer} that fetches and resizes images
 * fetched from a URL.
 */
public class ImageFetcher extends ImageResizer {
	private static final String TAG = "ImageFetcher";
	private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10MB
	public static final String HTTP_CACHE_DIR = "http";

	/**
	 * Initialize providing a target image width and height for the processing
	 * images.
	 *
	 * @param context
	 * @param imageWidth
	 * @param imageHeight
	 */
	public ImageFetcher(Context context, int imageWidth, int imageHeight) {
		super(context, imageWidth, imageHeight);
		init(context);
	}

	/**
	 * Initialize providing a single target image size (used for both width and
	 * height);
	 *
	 * @param context
	 * @param imageSize
	 */
	public ImageFetcher(Context context, int imageSize) {
		super(context, imageSize);
		init(context);
	}

	private void init(Context context) {
		checkConnection(context);
	}

	/**
	 * Simple network connection check.
	 *
	 * @param context
	 */
	private void checkConnection(Context context) {
		final ConnectivityManager cm = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
		if (networkInfo == null || !networkInfo.isConnectedOrConnecting()) {
			Toast.makeText(context, "世界上最遥远的距离就是没有网络", Toast.LENGTH_LONG)
					.show();
			Log.e(TAG, "checkConnection - no connection found");
		}
	}

	/**
	 * The main process method, which will be called by the ImageWorker in the
	 * AsyncTask background thread.
	 *
	 * @param data
	 *            The data to load the bitmap, in this case, a regular http URL
	 * @return The downloaded and resized bitmap
	 */
	private Bitmap processBitmap(String data) {
		if (BuildConfig.DEBUG) {
			// Log.d(TAG, "processBitmap - " + data);
		}

		// Download a bitmap, write it to a file
		final File f = downloadBitmap(mContext, data);

		if (f != null) {
			// Return a sampled down version
			return decodeSampledBitmapFromFile(f.toString(), mImageWidth,
					mImageHeight);
		}

		return null;
	}

	@Override
	protected Bitmap processBitmap(Object data) {
		return processBitmap(String.valueOf(data));
	}

	/**
	 * Download a bitmap from a URL, write it to a disk and return the File
	 * pointer. This implementation uses a simple disk cache.
	 *
	 * @param context
	 *            The context to use
	 * @param urlString
	 *            The URL to fetch
	 * @return A File pointing to the fetched bitmap
	 */
	public static File downloadBitmap(Context context, String urlString) {
		final File cacheDir = DiskLruCache.getDiskCacheDir(context,
				HTTP_CACHE_DIR);

		final DiskLruCache cache = DiskLruCache.openCache(context, cacheDir,
				HTTP_CACHE_SIZE);

		urlString = InsUrl.GET_IMAGE_REQ.replace("@path", urlString);
		final File cacheFile = new File(cache.createFilePath(urlString));

		if (cache.containsKey(urlString)) {
			if (BuildConfig.DEBUG) {
				// Log.d(TAG, "downloadBitmap - found in http cache - " +
				// urlString);
			}
			return cacheFile;
		}

		if (BuildConfig.DEBUG) {
			// Log.d(TAG, "downloadBitmap - downloading - " + urlString);
		}

		Utils.disableConnectionReuseIfNecessary();
		HttpURLConnection urlConnection = null;
		BufferedOutputStream out = null;

		try {
			final URL url = new URL(urlString);
			urlConnection = (HttpURLConnection) url.openConnection();
			final InputStream in = new BufferedInputStream(
					urlConnection.getInputStream(), Utils.IO_BUFFER_SIZE);
			out = new BufferedOutputStream(new FileOutputStream(cacheFile),
					Utils.IO_BUFFER_SIZE);

			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}

			return cacheFile;

		} catch (final IOException e) {
			Log.e(TAG, "Error in downloadBitmap - " + e);
		} finally {
			if (urlConnection != null) {
				urlConnection.disconnect();
			}
			if (out != null) {
				try {
					out.close();
				} catch (final IOException e) {
					Log.e(TAG, "Error in downloadBitmap - " + e);
				}
			}
		}

		return null;
	}
}


text:
package org.jclouds.cloudstack.options;

import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.tags;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.accountInDomain;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.domainId;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.id;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.named;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.virtualMachineId;
import static org.testng.Assert.assertEquals;

import com.google.common.collect.ImmutableMap;
import org.testng.annotations.Test;

import com.google.common.collect.ImmutableList;

/**
 * Tests behavior of {@code ListSecurityGroupsOptions}
 */
@Test(groups = "unit")
public class ListSecurityGroupsOptionsTest {

   public void testId() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().id("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
   }

   public void testIdStatic() {
      ListSecurityGroupsOptions options = id("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
   }

   public void testAccount() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().accountInDomain("account", "1");
      assertEquals(ImmutableList.of("account"), options.buildQueryParameters().get("account"));
   }

   public void testAccountStatic() {
      ListSecurityGroupsOptions options = accountInDomain("account", "1");
      assertEquals(ImmutableList.of("account"), options.buildQueryParameters().get("account"));
   }

   public void testName() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().named("securityGroupName");
      assertEquals(ImmutableList.of("securityGroupName"), options.buildQueryParameters().get("securitygroupname"));
   }

   public void testNameStatic() {
      ListSecurityGroupsOptions options = named("securityGroupName");
      assertEquals(ImmutableList.of("securityGroupName"), options.buildQueryParameters().get("securitygroupname"));
   }

   public void testDomainId() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().domainId("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
   }

   public void testDomainIdStatic() {
      ListSecurityGroupsOptions options = domainId("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("domainid"));
   }

   public void testVirtualMachineId() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().virtualMachineId("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("virtualmachineid"));
   }

   public void testVirtualMachineIdStatic() {
      ListSecurityGroupsOptions options = virtualMachineId("6");
      assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("virtualmachineid"));
   }

   public void testTags() {
      ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
   }

   public void testTagsStatic() {
      ListSecurityGroupsOptions options = tags(ImmutableMap.of("tag1", "val1", "tag2", "val2"));
      assertEquals(ImmutableList.of("tag1"), options.buildQueryParameters().get("tags[0].key"));
      assertEquals(ImmutableList.of("tag2"), options.buildQueryParameters().get("tags[1].key"));
      assertEquals(ImmutableList.of("val1"), options.buildQueryParameters().get("tags[0].value"));
      assertEquals(ImmutableList.of("val2"), options.buildQueryParameters().get("tags[1].value"));
   }
}


text:
ActiveRecord::Schema.define(:version => 20111211073631) do

  create_table "collectivity_members", :force => true do |t|
    t.integer  "organization_id"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "phone"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "email",                                 :default => "", :null => false
    t.string   "encrypted_password",     :limit => 128, :default => "", :null => false
    t.string   "password_salt"
    t.integer  "failed_attempts",                       :default => 0
    t.string   "unlock_token"
    t.datetime "locked_at"
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",                         :default => 0
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "authentication_token"
  end

  add_index "collectivity_members", ["authentication_token"], :name => "index_collectivity_members_on_authentication_token", :unique => true
  add_index "collectivity_members", ["confirmation_token"], :name => "index_collectivity_members_on_confirmation_token", :unique => true
  add_index "collectivity_members", ["email"], :name => "index_collectivity_members_on_email", :unique => true
  add_index "collectivity_members", ["reset_password_token"], :name => "index_collectivity_members_on_reset_password_token", :unique => true
  add_index "collectivity_members", ["unlock_token"], :name => "index_collectivity_members_on_unlock_token", :unique => true

  create_table "collectivity_organizations", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "collectivity_plans", :force => true do |t|
    t.string   "name"
    t.integer  "days_per_week"
    t.integer  "price_in_cents",    :default => 0,         :null => false
    t.string   "currency",          :default => "USD"
    t.string   "billing_frequency", :default => "monthly"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end


text:
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.omnibox;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView.BufferType;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem;
import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxSuggestionDelegate;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestion.MatchClassification;
import org.chromium.chrome.browser.widget.TintedDrawable;
import org.chromium.ui.base.DeviceFormFactor;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * Container view for omnibox suggestions made very specific for omnibox suggestions to minimize
 * any unnecessary measures and layouts.
 */
class SuggestionView extends ViewGroup {
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            SUGGESTION_ICON_UNDEFINED,
            SUGGESTION_ICON_BOOKMARK,
            SUGGESTION_ICON_HISTORY,
            SUGGESTION_ICON_GLOBE,
            SUGGESTION_ICON_MAGNIFIER,
            SUGGESTION_ICON_VOICE
    })
    private @interface SuggestionIcon {}

    private static final int SUGGESTION_ICON_UNDEFINED = -1;
    private static final int SUGGESTION_ICON_BOOKMARK = 0;
    private static final int SUGGESTION_ICON_HISTORY = 1;
    private static final int SUGGESTION_ICON_GLOBE = 2;
    private static final int SUGGESTION_ICON_MAGNIFIER = 3;
    private static final int SUGGESTION_ICON_VOICE = 4;

    private static final long RELAYOUT_DELAY_MS = 20;

    static final int TITLE_COLOR_STANDARD_FONT_DARK = 0xFF333333;
    private static final int TITLE_COLOR_STANDARD_FONT_LIGHT = 0xFFFFFFFF;
    private static final int URL_COLOR = 0xFF5595FE;

    private static final float ANSWER_IMAGE_SCALING_FACTOR = 1.15f;

    private final LocationBar mLocationBar;
    private UrlBar mUrlBar;
    private ImageView mNavigationButton;

    private final int mSuggestionHeight;
    private final int mSuggestionAnswerHeight;
    private int mNumAnswerLines = 1;

    private OmniboxResultItem mSuggestionItem;
    private OmniboxSuggestion mSuggestion;
    private OmniboxSuggestionDelegate mSuggestionDelegate;
    private Boolean mUseDarkColors;
    private int mPosition;

    private final SuggestionContentsContainer mContentsView;

    private final int mRefineWidth;
    private final View mRefineView;
    private TintedDrawable mRefineIcon;

    private final int[] mViewPositionHolder = new int[2];

    // Pre-computed offsets in px.
    private final int mPhoneUrlBarLeftOffsetPx;
    private final int mPhoneUrlBarLeftOffsetRtlPx;

    /**
     * Constructs a new omnibox suggestion view.
     *
     * @param context The context used to construct the suggestion view.
     * @param locationBar The location bar showing these suggestions.
     */
    public SuggestionView(Context context, LocationBar locationBar) {
        super(context);
        mLocationBar = locationBar;

        mSuggestionHeight =
                context.getResources().getDimensionPixelOffset(R.dimen.omnibox_suggestion_height);
        mSuggestionAnswerHeight =
                context.getResources().getDimensionPixelOffset(
                        R.dimen.omnibox_suggestion_answer_height);

        TypedArray a = getContext().obtainStyledAttributes(
                new int [] {R.attr.selectableItemBackground});
        Drawable itemBackground = a.getDrawable(0);
        a.recycle();

        mContentsView = new SuggestionContentsContainer(context, itemBackground);
        addView(mContentsView);

        mRefineView = new View(context) {
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);

                if (mRefineIcon == null) return;
                canvas.save();
                canvas.translate(
                        (getMeasuredWidth() - mRefineIcon.getIntrinsicWidth()) / 2f,
                        (getMeasuredHeight() - mRefineIcon.getIntrinsicHeight()) / 2f);
                mRefineIcon.draw(canvas);
                canvas.restore();
            }

            @Override
            public void setVisibility(int visibility) {
                super.setVisibility(visibility);

                if (visibility == VISIBLE) {
                    setClickable(true);
                    setFocusable(true);
                } else {
                    setClickable(false);
                    setFocusable(false);
                }
            }

            @Override
            protected void drawableStateChanged() {
                super.drawableStateChanged();

                if (mRefineIcon != null && mRefineIcon.isStateful()) {
                    mRefineIcon.setState(getDrawableState());
                }
            }
        };
        mRefineView.setContentDescription(getContext().getString(
                R.string.accessibility_omnibox_btn_refine));

        // Although this has the same background as the suggestion view, it can not be shared as
        // it will result in the state of the drawable being shared and always showing up in the
        // refine view.
        mRefineView.setBackground(itemBackground.getConstantState().newDrawable());
        mRefineView.setId(R.id.refine_view_id);
        mRefineView.setClickable(true);
        mRefineView.setFocusable(true);
        mRefineView.setLayoutParams(new LayoutParams(0, 0));
        addView(mRefineView);

        mRefineWidth = getResources()
                .getDimensionPixelSize(R.dimen.omnibox_suggestion_refine_width);

        mUrlBar = (UrlBar) locationBar.getContainerView().findViewById(R.id.url_bar);

        mPhoneUrlBarLeftOffsetPx = getResources().getDimensionPixelOffset(
                R.dimen.omnibox_suggestion_phone_url_bar_left_offset);
        mPhoneUrlBarLeftOffsetRtlPx = getResources().getDimensionPixelOffset(
                R.dimen.omnibox_suggestion_phone_url_bar_left_offset_rtl);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (getMeasuredWidth() == 0) return;

        if (mSuggestion.getType() != OmniboxSuggestionType.SEARCH_SUGGEST_TAIL) {
            mContentsView.resetTextWidths();
        }

        boolean refineVisible = mRefineView.getVisibility() == VISIBLE;
        boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(this);
        int contentsViewOffsetX = isRtl && refineVisible ? mRefineWidth : 0;
        mContentsView.layout(
                contentsViewOffsetX,
                0,
                contentsViewOffsetX + mContentsView.getMeasuredWidth(),
                mContentsView.getMeasuredHeight());
        int refineViewOffsetX = isRtl ? 0 : getMeasuredWidth() - mRefineWidth;
        mRefineView.layout(
                refineViewOffsetX,
                0,
                refineViewOffsetX + mRefineWidth,
                mContentsView.getMeasuredHeight());
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = mSuggestionHeight;
        boolean refineVisible = mRefineView.getVisibility() == VISIBLE;
        int refineWidth = refineVisible ? mRefineWidth : 0;
        if (mNumAnswerLines > 1) {
            mContentsView.measure(
                    MeasureSpec.makeMeasureSpec(width - refineWidth, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(mSuggestionAnswerHeight * 2, MeasureSpec.AT_MOST));
            height = mContentsView.getMeasuredHeight();
        } else if (!TextUtils.isEmpty(mSuggestion.getAnswerContents())) {
            height = mSuggestionAnswerHeight;
        }
        setMeasuredDimension(width, height);

        // The width will be specified as 0 when determining the height of the popup, so exit early
        // after setting the height.
        if (width == 0) return;

        if (mNumAnswerLines == 1) {
            mContentsView.measure(
                    MeasureSpec.makeMeasureSpec(width - refineWidth, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        }
        mContentsView.getLayoutParams().width = mContentsView.getMeasuredWidth();
        mContentsView.getLayoutParams().height = mContentsView.getMeasuredHeight();

        mRefineView.measure(
                MeasureSpec.makeMeasureSpec(mRefineWidth, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        mRefineView.getLayoutParams().width = mRefineView.getMeasuredWidth();
        mRefineView.getLayoutParams().height = mRefineView.getMeasuredHeight();
    }

    @Override
    public void invalidate() {
        super.invalidate();
        mContentsView.invalidate();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // Whenever the suggestion dropdown is touched, we dispatch onGestureDown which is
        // used to let autocomplete controller know that it should stop updating suggestions.
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) mSuggestionDelegate.onGestureDown();
        return super.dispatchTouchEvent(ev);
    }

    /**
     * Sets the contents and state of the view for the given suggestion.
     *
     * @param suggestionItem The omnibox suggestion item this view represents.
     * @param suggestionDelegate The suggestion delegate.
     * @param position Position of the suggestion in the dropdown list.
     * @param useDarkColors Whether dark colors should be used for fonts and icons.
     */
    public void init(OmniboxResultItem suggestionItem,
            OmniboxSuggestionDelegate suggestionDelegate,
            int position, boolean useDarkColors) {
        ViewCompat.setLayoutDirection(this, ViewCompat.getLayoutDirection(mUrlBar));

        // Update the position unconditionally.
        mPosition = position;
        jumpDrawablesToCurrentState();
        boolean colorsChanged = mUseDarkColors == null || mUseDarkColors != useDarkColors;
        if (suggestionItem.equals(mSuggestionItem) && !colorsChanged) return;
        mUseDarkColors = useDarkColors;
        if (colorsChanged) {
            mContentsView.mTextLine1.setTextColor(getStandardFontColor());
            setRefineIcon(true);
        }

        mSuggestionItem = suggestionItem;
        mSuggestion = suggestionItem.getSuggestion();
        mSuggestionDelegate = suggestionDelegate;
        // Reset old computations.
        mContentsView.resetTextWidths();
        mContentsView.mAnswerImage.setVisibility(GONE);
        mContentsView.mAnswerImage.getLayoutParams().height = 0;
        mContentsView.mAnswerImage.getLayoutParams().width = 0;
        mContentsView.mAnswerImage.setImageDrawable(null);
        mContentsView.mAnswerImageMaxSize = 0;
        mContentsView.mTextLine1.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
                .getDimension(R.dimen.omnibox_suggestion_first_line_text_size));
        mContentsView.mTextLine2.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
                .getDimension(R.dimen.omnibox_suggestion_second_line_text_size));

        // Suggestions with attached answers are rendered with rich results regardless of which
        // suggestion type they are.
        if (mSuggestion.hasAnswer()) {
            setAnswer(mSuggestion.getAnswer());
            mContentsView.setSuggestionIcon(SUGGESTION_ICON_MAGNIFIER, colorsChanged);
            mContentsView.mTextLine2.setVisibility(VISIBLE);
            setRefinable(true);
            return;
        } else {
            mNumAnswerLines = 1;
            mContentsView.mTextLine2.setEllipsize(null);
            mContentsView.mTextLine2.setSingleLine();
        }

        boolean sameAsTyped =
                suggestionItem.getMatchedQuery().equalsIgnoreCase(mSuggestion.getDisplayText());
        int suggestionType = mSuggestion.getType();
        if (mSuggestion.isUrlSuggestion()) {
            if (mSuggestion.isStarred()) {
                mContentsView.setSuggestionIcon(SUGGESTION_ICON_BOOKMARK, colorsChanged);
            } else if (suggestionType == OmniboxSuggestionType.HISTORY_URL) {
                mContentsView.setSuggestionIcon(SUGGESTION_ICON_HISTORY, colorsChanged);
            } else {
                mContentsView.setSuggestionIcon(SUGGESTION_ICON_GLOBE, colorsChanged);
            }
            boolean urlShown = !TextUtils.isEmpty(mSuggestion.getUrl());
            boolean urlHighlighted = false;
            if (urlShown) {
                urlHighlighted = setUrlText(suggestionItem);
            } else {
                mContentsView.mTextLine2.setVisibility(INVISIBLE);
            }
            setSuggestedQuery(suggestionItem, true, urlShown, urlHighlighted);
            setRefinable(!sameAsTyped);
        } else {
            @SuggestionIcon int suggestionIcon = SUGGESTION_ICON_MAGNIFIER;
            if (suggestionType == OmniboxSuggestionType.VOICE_SUGGEST) {
                suggestionIcon = SUGGESTION_ICON_VOICE;
            } else if ((suggestionType == OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED)
                    || (suggestionType == OmniboxSuggestionType.SEARCH_HISTORY)) {
                // Show history icon for suggestions based on user queries.
                suggestionIcon = SUGGESTION_ICON_HISTORY;
            }
            mContentsView.setSuggestionIcon(suggestionIcon, colorsChanged);
            setRefinable(!sameAsTyped);
            setSuggestedQuery(suggestionItem, false, false, false);
            if ((suggestionType == OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY)
                    || (suggestionType == OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE)) {
                showDescriptionLine(SpannableString.valueOf(mSuggestion.getDescription()), false);
            } else {
                mContentsView.mTextLine2.setVisibility(INVISIBLE);
            }
        }
    }

    private void setRefinable(boolean refinable) {
        if (refinable) {
            mRefineView.setVisibility(VISIBLE);
            mRefineView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Post the refine action to the end of the UI thread to allow the refine view
                    // a chance to update its background selection state.
                    PerformRefineSuggestion performRefine = new PerformRefineSuggestion();
                    if (!post(performRefine)) performRefine.run();
                }
            });
        } else {
            mRefineView.setOnClickListener(null);
            mRefineView.setVisibility(GONE);
        }
    }

    private int getStandardFontColor() {
        return (mUseDarkColors == null || mUseDarkColors)
                ? TITLE_COLOR_STANDARD_FONT_DARK : TITLE_COLOR_STANDARD_FONT_LIGHT;
    }

    @Override
    public void setSelected(boolean selected) {
        super.setSelected(selected);
        if (selected && !isInTouchMode()) {
            mSuggestionDelegate.onSetUrlToSuggestion(mSuggestion);
        }
    }

    private void setRefineIcon(boolean invalidateIcon) {
        if (!invalidateIcon && mRefineIcon != null) return;

        mRefineIcon = TintedDrawable.constructTintedDrawable(
                getResources(), R.drawable.btn_suggestion_refine);
        mRefineIcon.setTint(ApiCompatibilityUtils.getColorStateList(getResources(),
                mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint));
        mRefineIcon.setBounds(
                0, 0,
                mRefineIcon.getIntrinsicWidth(),
                mRefineIcon.getIntrinsicHeight());
        mRefineIcon.setState(mRefineView.getDrawableState());
        mRefineView.postInvalidateOnAnimation();
    }

    /**
     * Sets (and highlights) the URL text of the second line of the omnibox suggestion.
     *
     * @param result The suggestion containing the URL.
     * @return Whether the URL was highlighted based on the user query.
     */
    private boolean setUrlText(OmniboxResultItem result) {
        OmniboxSuggestion suggestion = result.getSuggestion();
        Spannable str = SpannableString.valueOf(suggestion.getDisplayText());
        boolean hasMatch = applyHighlightToMatchRegions(
                str, suggestion.getDisplayTextClassifications());
        showDescriptionLine(str, true);
        return hasMatch;
    }

    private boolean applyHighlightToMatchRegions(
            Spannable str, List<MatchClassification> classifications) {
        boolean hasMatch = false;
        for (int i = 0; i < classifications.size(); i++) {
            MatchClassification classification = classifications.get(i);
            if ((classification.style & MatchClassificationStyle.MATCH)
                    == MatchClassificationStyle.MATCH) {
                int matchStartIndex = classification.offset;
                int matchEndIndex;
                if (i == classifications.size() - 1) {
                    matchEndIndex = str.length();
                } else {
                    matchEndIndex = classifications.get(i + 1).offset;
                }
                matchStartIndex = Math.min(matchStartIndex, str.length());
                matchEndIndex = Math.min(matchEndIndex, str.length());

                hasMatch = true;
                // Bold the part of the URL that matches the user query.
                str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
                        matchStartIndex, matchEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return hasMatch;
    }

    /**
     * Sets a description line for the omnibox suggestion.
     *
     * @param str The description text.
     * @param isUrl Whether this text is a URL (as opposed to a normal string).
     */
    private void showDescriptionLine(Spannable str, boolean isUrl) {
        TextView textLine = mContentsView.mTextLine2;
        if (textLine.getVisibility() != VISIBLE) {
            textLine.setVisibility(VISIBLE);
        }
        textLine.setText(str, BufferType.SPANNABLE);

        // Force left-to-right rendering for URLs. See UrlBar constructor for details.
        if (isUrl) {
            textLine.setTextColor(URL_COLOR);
            ApiCompatibilityUtils.setTextDirection(textLine, TEXT_DIRECTION_LTR);
        } else {
            textLine.setTextColor(getStandardFontColor());
            ApiCompatibilityUtils.setTextDirection(textLine, TEXT_DIRECTION_INHERIT);
        }
    }

    /**
     * Sets the text of the first line of the omnibox suggestion.
     *
     * @param suggestionItem The item containing the suggestion data.
     * @param showDescriptionIfPresent Whether to show the description text of the suggestion if
     *                                 the item contains valid data.
     * @param isUrlQuery Whether this suggestion is showing an URL.
     * @param isUrlHighlighted Whether the URL contains any highlighted matching sections.
     */
    private void setSuggestedQuery(
            OmniboxResultItem suggestionItem, boolean showDescriptionIfPresent,
            boolean isUrlQuery, boolean isUrlHighlighted) {
        String userQuery = suggestionItem.getMatchedQuery();
        String suggestedQuery = null;
        List<MatchClassification> classifications;
        OmniboxSuggestion suggestion = suggestionItem.getSuggestion();
        if (showDescriptionIfPresent && !TextUtils.isEmpty(suggestion.getUrl())
                && !TextUtils.isEmpty(suggestion.getDescription())) {
            suggestedQuery = suggestion.getDescription();
            classifications = suggestion.getDescriptionClassifications();
        } else {
            suggestedQuery = suggestion.getDisplayText();
            classifications = suggestion.getDisplayTextClassifications();
        }
        if (suggestedQuery == null) {
            assert false : "Invalid suggestion sent with no displayable text";
            suggestedQuery = "";
            classifications = new ArrayList<MatchClassification>();
            classifications.add(new MatchClassification(0, MatchClassificationStyle.NONE));
        }

        if (mSuggestion.getType() == OmniboxSuggestionType.SEARCH_SUGGEST_TAIL) {
            String fillIntoEdit = mSuggestion.getFillIntoEdit();
            // Data sanity checks.
            if (fillIntoEdit.startsWith(userQuery)
                    && fillIntoEdit.endsWith(suggestedQuery)
                    && fillIntoEdit.length() < userQuery.length() + suggestedQuery.length()) {
                final String ellipsisPrefix = "\u2026 ";
                suggestedQuery = ellipsisPrefix + suggestedQuery;

                // Offset the match classifications by the length of the ellipsis prefix to ensure
                // the highlighting remains correct.
                for (int i = 0; i < classifications.size(); i++) {
                    classifications.set(i, new MatchClassification(
                            classifications.get(i).offset + ellipsisPrefix.length(),
                            classifications.get(i).style));
                }
                classifications.add(0, new MatchClassification(0, MatchClassificationStyle.NONE));

                if (DeviceFormFactor.isTablet(getContext())) {
                    TextPaint tp = mContentsView.mTextLine1.getPaint();
                    mContentsView.mRequiredWidth =
                            tp.measureText(fillIntoEdit, 0, fillIntoEdit.length());
                    mContentsView.mMatchContentsWidth =
                            tp.measureText(suggestedQuery, 0, suggestedQuery.length());

                    // Update the max text widths values in SuggestionList. These will be passed to
                    // the contents view on layout.
                    mSuggestionDelegate.onTextWidthsUpdated(
                            mContentsView.mRequiredWidth, mContentsView.mMatchContentsWidth);
                }
            }
        }

        Spannable str = SpannableString.valueOf(suggestedQuery);
        if (!isUrlHighlighted) applyHighlightToMatchRegions(str, classifications);
        mContentsView.mTextLine1.setText(str, BufferType.SPANNABLE);
    }

    static int parseNumAnswerLines(List<SuggestionAnswer.TextField> textFields) {
        for (int i = 0; i < textFields.size(); i++) {
            if (textFields.get(i).hasNumLines()) {
                return Math.min(3, textFields.get(i).getNumLines());
            }
        }
        return -1;
    }

    /**
     * Sets both lines of the Omnibox suggestion based on an Answers in Suggest result.
     *
     * @param answer The answer to be displayed.
     */
    private void setAnswer(SuggestionAnswer answer) {
        float density = getResources().getDisplayMetrics().density;

        SuggestionAnswer.ImageLine firstLine = answer.getFirstLine();
        mContentsView.mTextLine1.setTextSize(AnswerTextBuilder.getMaxTextHeightSp(firstLine));
        Spannable firstLineText = AnswerTextBuilder.buildSpannable(
                firstLine, mContentsView.mTextLine1.getPaint().getFontMetrics(), density);
        mContentsView.mTextLine1.setText(firstLineText);

        SuggestionAnswer.ImageLine secondLine = answer.getSecondLine();
        mContentsView.mTextLine2.setTextSize(AnswerTextBuilder.getMaxTextHeightSp(secondLine));
        Spannable secondLineText = AnswerTextBuilder.buildSpannable(
                secondLine, mContentsView.mTextLine2.getPaint().getFontMetrics(), density);
        mContentsView.mTextLine2.setText(secondLineText);
        mNumAnswerLines = parseNumAnswerLines(secondLine.getTextFields());
        if (mNumAnswerLines == -1) mNumAnswerLines = 1;
        if (mNumAnswerLines == 1) {
            mContentsView.mTextLine2.setEllipsize(null);
            mContentsView.mTextLine2.setSingleLine();
        } else {
            mContentsView.mTextLine2.setSingleLine(false);
            mContentsView.mTextLine2.setEllipsize(TextUtils.TruncateAt.END);
            mContentsView.mTextLine2.setMaxLines(mNumAnswerLines);
        }

        if (secondLine.hasImage()) {
            mContentsView.mAnswerImage.setVisibility(VISIBLE);

            float textSize = mContentsView.mTextLine2.getTextSize();
            int imageSize = (int) (textSize * ANSWER_IMAGE_SCALING_FACTOR);
            mContentsView.mAnswerImage.getLayoutParams().height = imageSize;
            mContentsView.mAnswerImage.getLayoutParams().width = imageSize;
            mContentsView.mAnswerImageMaxSize = imageSize;

            String url = "https:" + secondLine.getImage().replace("\\/", "/");
            AnswersImage.requestAnswersImage(
                    mLocationBar.getCurrentTab().getProfile(),
                    url,
                    new AnswersImage.AnswersImageObserver() {
                        @Override
                        public void onAnswersImageChanged(Bitmap bitmap) {
                            mContentsView.mAnswerImage.setImageBitmap(bitmap);
                        }
                    });
        }
    }

    /**
     * Handles triggering a selection request for the suggestion rendered by this view.
     */
    private class PerformSelectSuggestion implements Runnable {
        @Override
        public void run() {
            mSuggestionDelegate.onSelection(mSuggestion, mPosition);
        }
    }

    /**
     * Handles triggering a refine request for the suggestion rendered by this view.
     */
    private class PerformRefineSuggestion implements Runnable {
        @Override
        public void run() {
            mSuggestionDelegate.onRefineSuggestion(mSuggestion);
        }
    }

    /**
     * Container view for the contents of the suggestion (the search query, URL, and suggestion type
     * icon).
     */
    private class SuggestionContentsContainer extends ViewGroup implements OnLayoutChangeListener {
        private int mSuggestionIconLeft = Integer.MIN_VALUE;
        private int mTextLeft = Integer.MIN_VALUE;
        private int mTextRight = Integer.MIN_VALUE;
        private Drawable mSuggestionIcon;
        @SuggestionIcon
        private int mSuggestionIconType = SUGGESTION_ICON_UNDEFINED;

        private final TextView mTextLine1;
        private final TextView mTextLine2;
        private final ImageView mAnswerImage;

        private int mAnswerImageMaxSize;  // getMaxWidth() is API 16+, so store it locally.
        private float mRequiredWidth;
        private float mMatchContentsWidth;
        private boolean mForceIsFocused;

        private final Runnable mRelayoutRunnable = new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        };

        @SuppressLint("InlinedApi")
        SuggestionContentsContainer(Context context, Drawable backgroundDrawable) {
            super(context);

            ApiCompatibilityUtils.setLayoutDirection(this, View.LAYOUT_DIRECTION_INHERIT);

            setBackground(backgroundDrawable);
            setClickable(true);
            setFocusable(true);
            setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, mSuggestionHeight));
            setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Post the selection action to the end of the UI thread to allow the suggestion
                    // view a chance to update their background selection state.
                    PerformSelectSuggestion performSelection = new PerformSelectSuggestion();
                    if (!post(performSelection)) performSelection.run();
                }
            });
            setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    RecordUserAction.record("MobileOmniboxDeleteGesture");
                    if (!mSuggestion.isDeletable()) return true;

                    AlertDialog.Builder b =
                            new AlertDialog.Builder(getContext(), R.style.AlertDialogTheme);
                    b.setTitle(mSuggestion.getDisplayText());
                    b.setMessage(R.string.omnibox_confirm_delete);
                    DialogInterface.OnClickListener okListener =
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    RecordUserAction.record("MobileOmniboxDeleteRequested");
                                    mSuggestionDelegate.onDeleteSuggestion(mPosition);
                                }
                            };
                    b.setPositiveButton(android.R.string.ok, okListener);
                    DialogInterface.OnClickListener cancelListener =
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                }
                            };
                    b.setNegativeButton(android.R.string.cancel, cancelListener);

                    AlertDialog dialog = b.create();
                    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            mSuggestionDelegate.onHideModal();
                        }
                    });

                    mSuggestionDelegate.onShowModal();
                    dialog.show();
                    return true;
                }
            });

            mTextLine1 = new TextView(context);
            mTextLine1.setLayoutParams(
                    new LayoutParams(LayoutParams.WRAP_CONTENT, mSuggestionHeight));
            mTextLine1.setSingleLine();
            mTextLine1.setTextColor(getStandardFontColor());
            ApiCompatibilityUtils.setTextAlignment(mTextLine1, TEXT_ALIGNMENT_VIEW_START);
            addView(mTextLine1);

            mTextLine2 = new TextView(context);
            mTextLine2.setLayoutParams(
                    new LayoutParams(LayoutParams.WRAP_CONTENT, mSuggestionHeight));
            mTextLine2.setSingleLine();
            mTextLine2.setVisibility(INVISIBLE);
            ApiCompatibilityUtils.setTextAlignment(mTextLine2, TEXT_ALIGNMENT_VIEW_START);
            addView(mTextLine2);

            mAnswerImage = new ImageView(context);
            mAnswerImage.setVisibility(GONE);
            mAnswerImage.setScaleType(ImageView.ScaleType.FIT_CENTER);
            mAnswerImage.setLayoutParams(new LayoutParams(0, 0));
            mAnswerImageMaxSize = 0;
            addView(mAnswerImage);
        }

        private void resetTextWidths() {
            mRequiredWidth = 0;
            mMatchContentsWidth = 0;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            if (DeviceFormFactor.isTablet(getContext())) {
                // Use the same image transform matrix as the navigation icon to ensure the same
                // scaling, which requires centering vertically based on the height of the
                // navigation icon view and not the image itself.
                canvas.save();
                mSuggestionIconLeft = getSuggestionIconLeftPosition();
                canvas.translate(
                        mSuggestionIconLeft,
                        (getMeasuredHeight() - mNavigationButton.getMeasuredHeight()) / 2f);
                canvas.concat(mNavigationButton.getImageMatrix());
                mSuggestionIcon.draw(canvas);
                canvas.restore();
            }
        }

        @Override
        protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
            if (child != mTextLine1 && child != mTextLine2 && child != mAnswerImage) {
                return super.drawChild(canvas, child, drawingTime);
            }

            int height = getMeasuredHeight();
            int line1Height = mTextLine1.getMeasuredHeight();
            int line2Height = mTextLine2.getVisibility() == VISIBLE
                    ? mTextLine2.getMeasuredHeight() : 0;

            int verticalOffset = 0;
            if (line1Height + line2Height > height) {
                // The text lines total height is larger than this view, snap them to the top and
                // bottom of the view.
                if (child != mTextLine1) {
                    verticalOffset = height - line2Height;
                }
            } else {
                // The text lines fit comfortably, so vertically center them.
                verticalOffset = (height - line1Height - line2Height) / 2;
                if (child == mTextLine2) {
                    verticalOffset += line1Height;
                    if (mSuggestion.hasAnswer()
                            && mSuggestion.getAnswer().getSecondLine().hasImage()) {
                        verticalOffset += getResources().getDimensionPixelOffset(
                                R.dimen.omnibox_suggestion_answer_line2_vertical_spacing);
                    }
                }
                // When one line is larger than the other, it contains extra vertical padding. This
                // produces more apparent whitespace above or below the text lines.  Add a small
                // offset to compensate.
                if (line1Height != line2Height) {
                    verticalOffset += (line2Height - line1Height) / 10;
                }

                // The image is positioned vertically aligned with the second text line but
                // requires a small additional offset to align with the ascent of the text instead
                // of the top of the text which includes some whitespace.
                if (child == mAnswerImage) {
                    verticalOffset += getResources().getDimensionPixelOffset(
                            R.dimen.omnibox_suggestion_answer_image_vertical_spacing);
                }

                if (child != mTextLine1 && verticalOffset + line2Height > height) {
                    verticalOffset = height - line2Height;
                }
            }

            canvas.save();
            canvas.translate(0, verticalOffset);
            boolean retVal = super.drawChild(canvas, child, drawingTime);
            canvas.restore();
            return retVal;
        }

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            View locationBarView = mLocationBar.getContainerView();
            if (mUrlBar == null) {
                mUrlBar = (UrlBar) locationBarView.findViewById(R.id.url_bar);
                mUrlBar.addOnLayoutChangeListener(this);
            }
            if (mNavigationButton == null) {
                mNavigationButton =
                        (ImageView) locationBarView.findViewById(R.id.navigation_button);
                mNavigationButton.addOnLayoutChangeListener(this);
            }

            // Align the text to be pixel perfectly aligned with the text in the url bar.
            mTextLeft = getSuggestionTextLeftPosition();
            mTextRight = getSuggestionTextRightPosition();
            boolean isRTL = ApiCompatibilityUtils.isLayoutRtl(this);
            if (DeviceFormFactor.isTablet(getContext())) {
                int textWidth = isRTL ? mTextRight : (r - l - mTextLeft);
                final float maxRequiredWidth = mSuggestionDelegate.getMaxRequiredWidth();
                final float maxMatchContentsWidth = mSuggestionDelegate.getMaxMatchContentsWidth();
                float paddingStart = (textWidth > maxRequiredWidth)
                        ? (mRequiredWidth - mMatchContentsWidth)
                        : Math.max(textWidth - maxMatchContentsWidth, 0);
                ApiCompatibilityUtils.setPaddingRelative(
                        mTextLine1, (int) paddingStart, mTextLine1.getPaddingTop(),
                        0, // TODO(skanuj) : Change to ApiCompatibilityUtils.getPaddingEnd(...).
                        mTextLine1.getPaddingBottom());
            }

            int imageWidth = mAnswerImageMaxSize;
            int imageSpacing = 0;
            if (mAnswerImage.getVisibility() == VISIBLE && imageWidth > 0) {
                imageSpacing = getResources().getDimensionPixelOffset(
                        R.dimen.omnibox_suggestion_answer_image_horizontal_spacing);
            }
            if (isRTL) {
                mTextLine1.layout(0, t, mTextRight, b);
                mAnswerImage.layout(mTextRight - imageWidth , t, mTextRight, b);
                mTextLine2.layout(0, t, mTextRight - (imageWidth + imageSpacing), b);
            } else {
                mTextLine1.layout(mTextLeft, t, r - l, b);
                mAnswerImage.layout(mTextLeft, t, mTextLeft + imageWidth, b);
                mTextLine2.layout(mTextLeft + imageWidth + imageSpacing, t, r - l, b);
            }

            int suggestionIconPosition = getSuggestionIconLeftPosition();
            if (mSuggestionIconLeft != suggestionIconPosition
                    && mSuggestionIconLeft != Integer.MIN_VALUE) {
                mContentsView.postInvalidateOnAnimation();
            }
            mSuggestionIconLeft = suggestionIconPosition;
        }

        private int getUrlBarLeftOffset() {
            if (DeviceFormFactor.isTablet(getContext())) {
                mUrlBar.getLocationInWindow(mViewPositionHolder);
                return mViewPositionHolder[0];
            } else {
                return ApiCompatibilityUtils.isLayoutRtl(this) ? mPhoneUrlBarLeftOffsetRtlPx
                        : mPhoneUrlBarLeftOffsetPx;
            }
        }

        /**
         * @return The left offset for the suggestion text.
         */
        private int getSuggestionTextLeftPosition() {
            if (mLocationBar == null) return 0;

            int leftOffset = getUrlBarLeftOffset();
            getLocationInWindow(mViewPositionHolder);
            return leftOffset + mUrlBar.getPaddingLeft() - mViewPositionHolder[0];
        }

        /**
         * @return The right offset for the suggestion text.
         */
        private int getSuggestionTextRightPosition() {
            if (mLocationBar == null) return 0;

            int leftOffset = getUrlBarLeftOffset();
            getLocationInWindow(mViewPositionHolder);
            return leftOffset + mUrlBar.getWidth() - mUrlBar.getPaddingRight()
                    - mViewPositionHolder[0];
        }

        /**
         * @return The left offset for the suggestion type icon that aligns it with the url bar.
         */
        private int getSuggestionIconLeftPosition() {
            if (mNavigationButton == null) return 0;

            // Ensure the suggestion icon matches the location of the navigation icon in the omnibox
            // perfectly.
            mNavigationButton.getLocationOnScreen(mViewPositionHolder);
            int navButtonXPosition = mViewPositionHolder[0] + mNavigationButton.getPaddingLeft();

            getLocationOnScreen(mViewPositionHolder);

            return navButtonXPosition - mViewPositionHolder[0];
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);

            if (mTextLine1.getMeasuredWidth() != width
                    || mTextLine1.getMeasuredHeight() != height) {
                mTextLine1.measure(
                        MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST),
                        MeasureSpec.makeMeasureSpec(mSuggestionHeight, MeasureSpec.AT_MOST));
            }

            if (mTextLine2.getMeasuredWidth() != width
                    || mTextLine2.getMeasuredHeight() != height) {
                mTextLine2.measure(
                        MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST),
                        MeasureSpec.makeMeasureSpec(mSuggestionHeight, MeasureSpec.AT_MOST));
            }
            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
                int desiredHeight = mTextLine1.getMeasuredHeight() + mTextLine2.getMeasuredHeight();
                int additionalPadding = (int) getResources().getDimension(
                        R.dimen.omnibox_suggestion_text_vertical_padding);
                if (mSuggestion.hasAnswer()) {
                    additionalPadding += (int) getResources().getDimension(
                            R.dimen.omnibox_suggestion_multiline_text_vertical_padding);
                }
                desiredHeight += additionalPadding;
                desiredHeight = Math.min(MeasureSpec.getSize(heightMeasureSpec), desiredHeight);
                super.onMeasure(widthMeasureSpec,
                        MeasureSpec.makeMeasureSpec(desiredHeight, MeasureSpec.EXACTLY));
            } else {
                assert MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        }

        @Override
        public void invalidate() {
            if (getSuggestionTextLeftPosition() != mTextLeft
                    || getSuggestionTextRightPosition() != mTextRight) {
                // When the text position is changed, it typically is caused by the suggestions
                // appearing while the URL bar on the phone is gaining focus (if you trigger an
                // intent that will result in suggestions being shown before focusing the omnibox).
                // Triggering a relayout will cause any animations to stutter, so we continually
                // push the relayout to end of the UI queue until the animation is complete.
                removeCallbacks(mRelayoutRunnable);
                postDelayed(mRelayoutRunnable, RELAYOUT_DELAY_MS);
            } else {
                super.invalidate();
            }
        }

        @Override
        public boolean isFocused() {
            return mForceIsFocused || super.isFocused();
        }

        @Override
        protected int[] onCreateDrawableState(int extraSpace) {
            // When creating the drawable states, treat selected as focused to get the proper
            // highlight when in non-touch mode (i.e. physical keyboard).  This is because only
            // a single view in a window can have focus, and these will only appear if
            // the omnibox has focus, so we trick the drawable state into believing it has it.
            mForceIsFocused = isSelected() && !isInTouchMode();
            int[] drawableState = super.onCreateDrawableState(extraSpace);
            mForceIsFocused = false;
            return drawableState;
        }

        private void setSuggestionIcon(@SuggestionIcon int type, boolean invalidateCurrentIcon) {
            if (mSuggestionIconType == type && !invalidateCurrentIcon) return;
            assert type != SUGGESTION_ICON_UNDEFINED;

            int drawableId = R.drawable.ic_omnibox_page;
            switch (type) {
                case SUGGESTION_ICON_BOOKMARK:
                    drawableId = R.drawable.btn_star;
                    break;
                case SUGGESTION_ICON_MAGNIFIER:
                    drawableId = R.drawable.ic_suggestion_magnifier;
                    break;
                case SUGGESTION_ICON_HISTORY:
                    drawableId = R.drawable.ic_suggestion_history;
                    break;
                case SUGGESTION_ICON_VOICE:
                    drawableId = R.drawable.btn_mic;
                    break;
                default:
                    break;
            }
            mSuggestionIcon = ApiCompatibilityUtils.getDrawable(getResources(), drawableId);
            mSuggestionIcon.setColorFilter(mUseDarkColors
                    ? ApiCompatibilityUtils.getColor(getResources(), R.color.light_normal_color)
                    : Color.WHITE, PorterDuff.Mode.SRC_IN);
            mSuggestionIcon.setBounds(
                    0, 0,
                    mSuggestionIcon.getIntrinsicWidth(),
                    mSuggestionIcon.getIntrinsicHeight());
            mSuggestionIconType = type;
            invalidate();
        }

        @Override
        public void onLayoutChange(
                View v, int left, int top, int right, int bottom, int oldLeft,
                int oldTop, int oldRight, int oldBottom) {
            boolean needsInvalidate = false;
            if (v == mNavigationButton) {
                if (mSuggestionIconLeft != getSuggestionIconLeftPosition()
                        && mSuggestionIconLeft != Integer.MIN_VALUE) {
                    needsInvalidate = true;
                }
            } else {
                if (mTextLeft != getSuggestionTextLeftPosition()
                        && mTextLeft != Integer.MIN_VALUE) {
                    needsInvalidate = true;
                }
                if (mTextRight != getSuggestionTextRightPosition()
                        && mTextRight != Integer.MIN_VALUE) {
                    needsInvalidate = true;
                }
            }
            if (needsInvalidate) {
                removeCallbacks(mRelayoutRunnable);
                postDelayed(mRelayoutRunnable, RELAYOUT_DELAY_MS);
            }
        }

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            if (mNavigationButton != null) mNavigationButton.addOnLayoutChangeListener(this);
            if (mUrlBar != null) mUrlBar.addOnLayoutChangeListener(this);
            if (mLocationBar != null) {
                mLocationBar.getContainerView().addOnLayoutChangeListener(this);
            }
            getRootView().addOnLayoutChangeListener(this);
        }

        @Override
        protected void onDetachedFromWindow() {
            if (mNavigationButton != null) mNavigationButton.removeOnLayoutChangeListener(this);
            if (mUrlBar != null) mUrlBar.removeOnLayoutChangeListener(this);
            if (mLocationBar != null) {
                mLocationBar.getContainerView().removeOnLayoutChangeListener(this);
            }
            getRootView().removeOnLayoutChangeListener(this);

            super.onDetachedFromWindow();
        }
    }
}


text:
*This is legacy documentation. It will either be updated or replaced in the future.*

[Submit Apache Cordova Applications to the Apple App Store & Google Play](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/)

## Prepare Your Environment

```
npm install -g cordova
cordova platform add ios --save
cordova platform add android --save
npm install -g code-push-cli
```

## Run the App in an iOS Emulator

You need an OSX machine with XCode installed

```
cordova build ios
cordova run ios
```

## Run the App in an Android Emulator

You need JDK + Android SDK + emulator images installed

```
cordova build android
cordova run android
```

For other platforms, replace ios for the platform name.

## Prepare a release binary

```
cordova build --release android
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore tick-trade-key.keystore ./platforms/android/build/outputs/apk/android-release-unsigned.apk TickTrade
~/Library/Android/sdk/build-tools/24.0.0/zipalign -v 4 ./platforms/android/build/outputs/apk/android-release-unsigned.apk ./platforms/android/build/outputs/apk/android-release-aligned.apk
```

## Publish an Update

#### Login to code-push

```
code-push login
```

#### List apps

```
code-push app ls
```

#### Publish update
```
code-push release-cordova binary-next-gen-android android
code-push release-cordova binary-next-gen-ios ios
```

## Deploy app to app store and google play.

To deploy or submit your app to an app store , some configurations are necessary . These are a one time settings that would be stored on your device once configure.

### Submit .ipa to the app store

Once you are satisfied with your changes and is ready to submit a release to ios app store. You need to run the command

`$ cordova build --release ios`

The above command update the .xcodeproj located in your `project-root-folder/platforms/ios/Binary.com.xcodeproj`

Next , you would need an ios distributing certificate .The creating IOS distributing certificate requires an apple developer account so visit http://developer.apple.com/. In our case, you may need to either get invited by the admin of our apple developer account, or use the admin account to login. Once you have the admin privilege.Once you have admin privilege , you would need to sign in and

#### Creating an iOS Distribution Certificate

* Click on "Certificates Identifiers and Profiles" and then on the next screen click on "Certificates."
* Click on the "+" button on the certificates page and scroll down in the production section and choose the "App Store and Ad Hoc" option and click "Continue".
![Creating IoS distribution cert](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-1.png)

* Since we are creating a new certificate, you need to open > Keychain Access from your mac .The easiest way to do this is in your Mac click on the search bar in the top right and search for "Keychain Access" and open this application, Click on Keychain Access in the menu in the top left, and in the dropdown hover over "Certificate Assistant" and choose "Request a Certificate From a Certificate Authority".

![Key Chain](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-2.png)

* This will open up a modal which you can then fill out the e-mail address with your developer account e-mail and then a common name which can usually just be the same of your organisation. After you have filled these out choose the "Save to disk" option and save the certificate to wherever you want on your computer.

![Certificate of Authority](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-3.png)

* After we do this back in our developer account we will click "Continue" again and on the next page we will upload the CSR file we just created and saved to our computer. Attach the file via the "Choose file…" button, attach the file and click the "Generate" button.

![IOS certificate](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-4.png)

* In the next screen you will be able to download the generated file (which is an iOS distribution .cer file) by clicking on the "Download" button. Download this file and save it somewhere on your computer (probably the "Downloads" folder).

![IOS File](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-5.png)

* After this, we need to again open up the "Keychain Access" application and we need to drag and drop this certificate into the section in the top left of the "Keychain Access" window called "logins." Note that this information is also present on the download screen we were just at in the Developer Center.

That is all that we need to do for creating an iOS Distribution Certificate. This tutorial is taken from [9bitstudio](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/) . You can refer [9bitstudios](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/) for better explanation

#### Creating an App ID in Developer Center

Once you have created an IOS Distribution Cert, what comes next is App ID .  The App ID is a unique identifier key that the App Store will use to differentiate it from other apps. Example, on our app store we have ticktrade and many more mobile apps. Each and every one of this apps have a unique Id or identifier on the store . This identifier is created once and this have been created for next-gen . You don't need to create another one.

#### Creating an iOS Provisioning Profile in Developer Center

provisioning profile is very important in IOS submission without which an ipa cannot be submitted to the store.

You may not need to recreate this step for one has been created. You need to download a the existing provision profile though or where not available , create one as detailed below.

* Back in the developer center, Under the "Provisioning Profiles" section in the "Certificates, Identifiers & Profiles" screen click on "Distribution." Click on the "+" button to create a new provisioning profile. In the next section scroll down and choose "App Store" to create a distribution provisioning profile to submit your app to the App Store and click on "Continue".

![Provisioning prof 1](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-6.png)

* Next you can create a name for the profile. You can put whatever you want in here, the name of your organization or the name of your application.

![Prov prof 2](http://www.9bitstudios.com/wp-content/uploads/iOS-submission-7.png)

* After you have chosen something click on the "Generate" button. This will take you to a screen where you can download your iOS Provisioning Profile. Download this .mobileprovision file and save it somewhere on your computer.
* Now go to the location where you downloaded this provisioning profile. Double click on it and choose the "Add to Library" option to add this profile to the iPhone configuration utility.

Note:  This tut is taken from [9bitstudios](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/)

#### Configuring & Packaging Project in Xcode

After going through the above stages, its time to configure and package your .ipa in xcode. There is a clear detail on how this on [9bit studios](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/). To summarised the steps,

* Adding a distribution configuration under the project tab.
* Setting code signing identity for both project and deployment target.
* Select the Target > General tab > Deployment Info. Check Hide status bar, Requires fullscreen . For device orientations , select Portrait, upside down for universal and iphone devices. Select all the four options for ipad device .
* Select 'Generic IOS Device' as your destination. And then finally.
* Select Product from the Menu > Then 'Archive' .

A more detailed explanation of this step with shots is available at [9bitstudios](http://www.9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/)

Note: You would be prompted with message asking if you want to sign using your key. Select the right key and click ok.

## Build new desktop app version

We use [Electron](http://electron.atom.io/) to run as desktop app.

`
npm i electron-prebuilt -g
brew install gnu-tar libicns graphicsmagick
electron
`

Note: To build new windows installer on MAC you must have mono, wine installed using the commands below.

`brew install wine --without-x11
brew install mono`

Note: To build new linux installer on MAC you must have gnu-tar, libicns, graphicsmagick, xz installed. Please run the command below.

`brew install gnu-tar libicns graphicsmagick xz`

For better explanation , please refer [here](https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build)

### Build .dmg and squirrel windows installer

After you prepare your machine from the explanation above, its time to build the windows, linux and mac installers. to achieve this, simply run

`npm run dist `

The above command generate the desired .dmg , .exe etc in their respective folders. Check inside the dist folder and you would have access to these files. Alternatively , you can run

`npm run all ` which generate the electron releases and the mobile builds.


text:
<?php
// autogenerated file 30.09.2013 15:20
// $Id: $
// $Log: $
//
//
require_once 'CharityStatusCodeType.php';
require_once 'EbatNs_ComplexType.php';
require_once 'NonProfitSocialAddressType.php';
require_once 'NonProfitAddressType.php';

/**
 * Type defining the <b>Charity</b> container, which consists of all detailsrelated
 * to a nonprofit charity organization.
 *
 * @link http://developer.ebay.com/DevZone/XML/docs/Reference/eBay/types/CharityInfoType.html
 *
 */
class CharityInfoType extends EbatNs_ComplexType
{
	/**
	 * @var string
	 */
	protected $Name;
	/**
	 * @var string
	 */
	protected $Mission;
	/**
	 * @var anyURI
	 */
	protected $LogoURL;
	/**
	 * @var CharityStatusCodeType
	 */
	protected $Status;
	/**
	 * @var string
	 */
	protected $SearchableString;
	/**
	 * @var int
	 */
	protected $CharityRegion;
	/**
	 * @var int
	 */
	protected $CharityDomain;
	/**
	 * @var string
	 */
	protected $CharityID;
	/**
	 * @var anyURI
	 */
	protected $LogoURLSelling;
	/**
	 * @var boolean
	 */
	protected $DisplayLogoSelling;
	/**
	 * @var boolean
	 */
	protected $DisplayNameInCheckout;
	/**
	 * @var string
	 */
	protected $Description;
	/**
	 * @var boolean
	 */
	protected $ShowMultipleDonationAmountInCheckout;
	/**
	 * @var string
	 */
	protected $ExternalID;
	/**
	 * @var int
	 */
	protected $PopularityIndex;
	/**
	 * @var string
	 */
	protected $EIN;
	/**
	 * @var string
	 */
	protected $NonProfitSecondName;
	/**
	 * @var NonProfitAddressType
	 */
	protected $NonProfitAddress;
	/**
	 * @var NonProfitSocialAddressType
	 */
	protected $NonProfitSocialAddress;

	/**
	 * @return string
	 */
	function getName()
	{
		return $this->Name;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setName($value)
	{
		$this->Name = $value;
	}
	/**
	 * @return string
	 */
	function getMission()
	{
		return $this->Mission;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setMission($value)
	{
		$this->Mission = $value;
	}
	/**
	 * @return anyURI
	 */
	function getLogoURL()
	{
		return $this->LogoURL;
	}
	/**
	 * @return void
	 * @param anyURI $value
	 */
	function setLogoURL($value)
	{
		$this->LogoURL = $value;
	}
	/**
	 * @return CharityStatusCodeType
	 */
	function getStatus()
	{
		return $this->Status;
	}
	/**
	 * @return void
	 * @param CharityStatusCodeType $value
	 */
	function setStatus($value)
	{
		$this->Status = $value;
	}
	/**
	 * @return string
	 */
	function getSearchableString()
	{
		return $this->SearchableString;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setSearchableString($value)
	{
		$this->SearchableString = $value;
	}
	/**
	 * @return int
	 */
	function getCharityRegion()
	{
		return $this->CharityRegion;
	}
	/**
	 * @return void
	 * @param int $value
	 */
	function setCharityRegion($value)
	{
		$this->CharityRegion = $value;
	}
	/**
	 * @return int
	 * @param integer $index
	 */
	function getCharityDomain($index = null)
	{
		if ($index !== null) {
			return $this->CharityDomain[$index];
		} else {
			return $this->CharityDomain;
		}
	}
	/**
	 * @return void
	 * @param int $value
	 * @param  $index
	 */
	function setCharityDomain($value, $index = null)
	{
		if ($index !== null) {
			$this->CharityDomain[$index] = $value;
		} else {
			$this->CharityDomain = $value;
		}
	}
	/**
	 * @return void
	 * @param int $value
	 */
	function addCharityDomain($value)
	{
		$this->CharityDomain[] = $value;
	}
	/**
	 * @return string
	 */
	function getCharityID()
	{
		return $this->CharityID;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setCharityID($value)
	{
		$this->CharityID = $value;
	}
	/**
	 * @return anyURI
	 */
	function getLogoURLSelling()
	{
		return $this->LogoURLSelling;
	}
	/**
	 * @return void
	 * @param anyURI $value
	 */
	function setLogoURLSelling($value)
	{
		$this->LogoURLSelling = $value;
	}
	/**
	 * @return boolean
	 */
	function getDisplayLogoSelling()
	{
		return $this->DisplayLogoSelling;
	}
	/**
	 * @return void
	 * @param boolean $value
	 */
	function setDisplayLogoSelling($value)
	{
		$this->DisplayLogoSelling = $value;
	}
	/**
	 * @return boolean
	 */
	function getDisplayNameInCheckout()
	{
		return $this->DisplayNameInCheckout;
	}
	/**
	 * @return void
	 * @param boolean $value
	 */
	function setDisplayNameInCheckout($value)
	{
		$this->DisplayNameInCheckout = $value;
	}
	/**
	 * @return string
	 */
	function getDescription()
	{
		return $this->Description;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setDescription($value)
	{
		$this->Description = $value;
	}
	/**
	 * @return boolean
	 */
	function getShowMultipleDonationAmountInCheckout()
	{
		return $this->ShowMultipleDonationAmountInCheckout;
	}
	/**
	 * @return void
	 * @param boolean $value
	 */
	function setShowMultipleDonationAmountInCheckout($value)
	{
		$this->ShowMultipleDonationAmountInCheckout = $value;
	}
	/**
	 * @return string
	 */
	function getExternalID()
	{
		return $this->ExternalID;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setExternalID($value)
	{
		$this->ExternalID = $value;
	}
	/**
	 * @return int
	 */
	function getPopularityIndex()
	{
		return $this->PopularityIndex;
	}
	/**
	 * @return void
	 * @param int $value
	 */
	function setPopularityIndex($value)
	{
		$this->PopularityIndex = $value;
	}
	/**
	 * @return string
	 */
	function getEIN()
	{
		return $this->EIN;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setEIN($value)
	{
		$this->EIN = $value;
	}
	/**
	 * @return string
	 */
	function getNonProfitSecondName()
	{
		return $this->NonProfitSecondName;
	}
	/**
	 * @return void
	 * @param string $value
	 */
	function setNonProfitSecondName($value)
	{
		$this->NonProfitSecondName = $value;
	}
	/**
	 * @return NonProfitAddressType
	 * @param integer $index
	 */
	function getNonProfitAddress($index = null)
	{
		if ($index !== null) {
			return $this->NonProfitAddress[$index];
		} else {
			return $this->NonProfitAddress;
		}
	}
	/**
	 * @return void
	 * @param NonProfitAddressType $value
	 * @param  $index
	 */
	function setNonProfitAddress($value, $index = null)
	{
		if ($index !== null) {
			$this->NonProfitAddress[$index] = $value;
		} else {
			$this->NonProfitAddress = $value;
		}
	}
	/**
	 * @return void
	 * @param NonProfitAddressType $value
	 */
	function addNonProfitAddress($value)
	{
		$this->NonProfitAddress[] = $value;
	}
	/**
	 * @return NonProfitSocialAddressType
	 * @param integer $index
	 */
	function getNonProfitSocialAddress($index = null)
	{
		if ($index !== null) {
			return $this->NonProfitSocialAddress[$index];
		} else {
			return $this->NonProfitSocialAddress;
		}
	}
	/**
	 * @return void
	 * @param NonProfitSocialAddressType $value
	 * @param  $index
	 */
	function setNonProfitSocialAddress($value, $index = null)
	{
		if ($index !== null) {
			$this->NonProfitSocialAddress[$index] = $value;
		} else {
			$this->NonProfitSocialAddress = $value;
		}
	}
	/**
	 * @return void
	 * @param NonProfitSocialAddressType $value
	 */
	function addNonProfitSocialAddress($value)
	{
		$this->NonProfitSocialAddress[] = $value;
	}
	/**
	 * @return
	 */
	function __construct()
	{
		parent::__construct('CharityInfoType', 'http://www.w3.org/2001/XMLSchema');
		if (!isset(self::$_elements[__CLASS__]))
				self::$_elements[__CLASS__] = array_merge(self::$_elements[get_parent_class()],
				array(
					'Name' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'Mission' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'LogoURL' =>
					array(
						'required' => false,
						'type' => 'anyURI',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'Status' =>
					array(
						'required' => false,
						'type' => 'CharityStatusCodeType',
						'nsURI' => 'urn:ebay:apis:eBLBaseComponents',
						'array' => false,
						'cardinality' => '0..1'
					),
					'SearchableString' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'CharityRegion' =>
					array(
						'required' => false,
						'type' => 'int',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'CharityDomain' =>
					array(
						'required' => false,
						'type' => 'int',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => true,
						'cardinality' => '0..3'
					),
					'CharityID' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'LogoURLSelling' =>
					array(
						'required' => false,
						'type' => 'anyURI',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'DisplayLogoSelling' =>
					array(
						'required' => false,
						'type' => 'boolean',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'DisplayNameInCheckout' =>
					array(
						'required' => false,
						'type' => 'boolean',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'Description' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'ShowMultipleDonationAmountInCheckout' =>
					array(
						'required' => false,
						'type' => 'boolean',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'ExternalID' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'PopularityIndex' =>
					array(
						'required' => false,
						'type' => 'int',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'EIN' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'NonProfitSecondName' =>
					array(
						'required' => false,
						'type' => 'string',
						'nsURI' => 'http://www.w3.org/2001/XMLSchema',
						'array' => false,
						'cardinality' => '0..1'
					),
					'NonProfitAddress' =>
					array(
						'required' => false,
						'type' => 'NonProfitAddressType',
						'nsURI' => 'urn:ebay:apis:eBLBaseComponents',
						'array' => true,
						'cardinality' => '0..*'
					),
					'NonProfitSocialAddress' =>
					array(
						'required' => false,
						'type' => 'NonProfitSocialAddressType',
						'nsURI' => 'urn:ebay:apis:eBLBaseComponents',
						'array' => true,
						'cardinality' => '0..*'
					)
				));	$this->_attributes = array_merge($this->_attributes,
		array(
			'id' =>
			array(
				'name' => 'id',
				'type' => 'string',
				'use' => 'required'
			)
		));

	}
}
?>


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">zapperbot</string>
</resources>


text:
package fake

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"testing"

	"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog"
	_ "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/install"
	"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/testapi"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

const (
	ns1   = "ns1"
	ns2   = "ns2"
	tipe1 = "tipe1"
	name1 = "name1"
	name2 = "name2"
	name3 = "name3"
)

//Helpers
func createSingleItemStorage() NamespacedStorage {
	storage := make(NamespacedStorage)
	storage.Set(ns1, tipe1, name1, &servicecatalog.ServiceBroker{})
	return storage
}

func createMultipleItemStorage() NamespacedStorage {
	storage := make(NamespacedStorage)
	storage.Set(ns1, tipe1, name1, &servicecatalog.ServiceBroker{})
	storage.Set(ns1, tipe1, name2, &servicecatalog.ServiceBroker{})
	storage.Set(ns1, tipe1, name3, &servicecatalog.ServiceBroker{})

	storage.Set(ns2, tipe1, name1, &servicecatalog.ServiceBroker{})
	storage.Set(ns2, tipe1, name2, &servicecatalog.ServiceBroker{})

	return storage

}

func TestNamespacedStorageSetDelete(t *testing.T) {
	storage := make(NamespacedStorage)

	if nil != storage.Get(ns1, tipe1, name1) {
		t.Fatal("Expected no results from an empty storage")
	}

	storage = createSingleItemStorage()

	if storage.Get(ns1, tipe1, name1) == nil {
		t.Fatal("Expected a object to be stored")
	}

	storage.Delete(ns1, tipe1, name1)
	if nil != storage.Get(ns1, tipe1, name1) {
		t.Fatal("Expected the object to be deleted")
	}
}

func TestNamespacedStorageGetList(t *testing.T) {
	storage := createMultipleItemStorage()

	objects := storage.GetList(ns1, tipe1)
	if count := len(objects); count != 3 {
		t.Fatal("Expected ", 3, "got", count)
	}

	objects = storage.GetList(ns2, tipe1)
	if count := len(objects); count != 2 {
		t.Fatal("Expected ", 2, "got", count)
	}
}

func TestResponseWriter(t *testing.T) {
	rw := newResponseWriter()
	length, err := rw.Write([]byte{0, 0, 0})
	if err != nil {
		t.Fatal("Error writing response", err)
	}

	if length != 3 {
		t.Fatal("Expected length", 3, "got", length)
	}
}

func TestResponseWriterGetResponsePanic(t *testing.T) {
	rw := newResponseWriter()
	// no hearder status set should panic
	defer func() {
		if r := recover(); r == nil {
			t.Fatal("Expected a panic")
		}
	}()
	rw.getResponse()
}

func TestResponseWriterGetResponse(t *testing.T) {
	rw := newResponseWriter()
	rw.WriteHeader(http.StatusFound)

	if response := rw.getResponse(); response.StatusCode != http.StatusFound {
		t.Fatal("Expected", 0, "got", response.StatusCode)
	}
}

func TestGetItem(t *testing.T) {
	testCases := []struct {
		name           string
		storage        NamespacedStorage
		watcher        *Watcher
		rw             *responseWriter
		url            string
		expectedStatus int
	}{
		{"Empty Storage", make(NamespacedStorage), NewWatcher(), newResponseWriter(), fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%s/%s/%s", ns1, tipe1, name1), http.StatusNotFound},
		{"One Item in storage", createSingleItemStorage(), NewWatcher(), newResponseWriter(), fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%s/%s/%s", ns1, tipe1, name1), http.StatusOK},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			request, err := http.NewRequest("GET", tc.url, nil)
			if err != nil {
				t.Fatal(err)
			}

			router := getRouter(tc.storage, tc.watcher, func() runtime.Object {
				return &servicecatalog.ServiceInstance{}
			})

			router.ServeHTTP(tc.rw, request)

			body, err := ioutil.ReadAll(tc.rw.getResponse().Body)
			if err != nil {
				t.Error("Could not read response.", err)
			}

			if tc.rw.getResponse().StatusCode != tc.expectedStatus && tc.rw.headerSet {
				t.Error("Expected Status", tc.expectedStatus, "got", tc.rw.getResponse().StatusCode)
				t.Error("Http error:", string(body))
			}
			if err != nil {
				t.Fatal(err)
			}
		})
	}
}

func TestGetItems(t *testing.T) {
	testCases := []struct {
		name           string
		storage        NamespacedStorage
		watcher        *Watcher
		rw             *responseWriter
		url            string
		expectedStatus int
	}{
		{"Empty Storage", make(NamespacedStorage), NewWatcher(), newResponseWriter(), fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%v/servicebrokers", ns1), http.StatusOK},
		{"Multiple Items", createMultipleItemStorage(), NewWatcher(), newResponseWriter(), fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%v/servicebrokers", ns1), http.StatusOK},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			request, err := http.NewRequest("GET", tc.url, nil)
			if err != nil {
				t.Fatal(err)
			}

			router := getRouter(tc.storage, tc.watcher, func() runtime.Object {
				return &servicecatalog.ServiceInstance{}
			})

			router.ServeHTTP(tc.rw, request)

			body, err := ioutil.ReadAll(tc.rw.getResponse().Body)
			if err != nil {
				t.Error("Could not read response.", err)
			}

			if tc.rw.getResponse().StatusCode != tc.expectedStatus && tc.rw.headerSet {
				t.Error("Expected Status", tc.expectedStatus, "got", tc.rw.getResponse().StatusCode)
				t.Error("Http error:", string(body))
			}
			if err != nil {
				t.Fatal(err)
			}
		})
	}

}

func TestCreateItem(t *testing.T) {
	testCases := []struct {
		name                  string
		storage               NamespacedStorage
		watcher               *Watcher
		rw                    *responseWriter
		url                   string
		item                  runtime.Object
		expectedStatus        int
		expectedStorageLength int
	}{
		{
			"Create Item (empty storage)",
			make(NamespacedStorage), NewWatcher(),
			newResponseWriter(),
			fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%s/%s", ns1, tipe1),
			&servicecatalog.ServiceBroker{ObjectMeta: metav1.ObjectMeta{Name: name1}, TypeMeta: metav1.TypeMeta{Kind: "ServiceBroker", APIVersion: "servicecatalog.k8s.io/v1alpha1"}},
			http.StatusCreated,
			1,
		},
		{
			"Create misformed item(no Kind)",
			make(NamespacedStorage),
			NewWatcher(),
			newResponseWriter(),
			fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%s/%s", ns1, tipe1),
			&servicecatalog.ServiceBroker{}, http.StatusInternalServerError,
			0,
		},
		{
			"Create Item(non-empty storage)",
			createMultipleItemStorage(),
			NewWatcher(),
			newResponseWriter(),
			fmt.Sprintf("/apis/servicecatalog.k8s.io/v1alpha1/namespaces/%s/%s", ns1, tipe1), &servicecatalog.ServiceBroker{TypeMeta: metav1.TypeMeta{Kind: "ServiceBroker", APIVersion: "servicecatalog.k8s.io/v1alpha1"}},
			http.StatusCreated,
			2,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			codec, err := testapi.GetCodecForObject(tc.item)
			if err != nil {
				t.Fatalf("error getting a codec for %#v (%s)", tc.item, err)
			}
			bodyBytes, err := runtime.Encode(codec, tc.item)
			if err != nil {
				t.Fatalf("error getting a encoding %#v (%s)", tc.item, err)
			}
			request, err := http.NewRequest("POST", tc.url, bytes.NewReader(bodyBytes))
			if err != nil {
				t.Fatal(err)
			}

			router := getRouter(tc.storage, tc.watcher, func() runtime.Object {
				return tc.item
			})

			router.ServeHTTP(tc.rw, request)

			body, err := ioutil.ReadAll(tc.rw.getResponse().Body)
			if err != nil {
				t.Error("Could not read response.", err)
			}

			if tc.rw.getResponse().StatusCode != tc.expectedStatus && tc.rw.headerSet {
				t.Error("Expected Status", tc.expectedStatus, "got", tc.rw.getResponse().StatusCode)
				t.Error("Http error:", string(body))
			}
			if len(tc.storage) != tc.expectedStorageLength {
				t.Error("Expected the length of the storage to be", tc.expectedStorageLength, "got", len(tc.storage))
			}
		})
	}
}


text:
TARGET_DIR=$(cd $(dirname $0) && pwd)

AGENT_TYPES_ARRAY=("Heap Stats Thread")
AGENT_PID_ARRAY=""

# Dont kick off right away
# Ruby might get picked as the process to watch rather than java or node-js, as the server is yet to start....
WAIT_INTERVAL_BEFORE_KICKOFF=30

function startAgent {
  type=$1

  completeAgent=dump${type}Agent

  agentLog=${completeAgent}.log
  agentScript=${completeAgent}.sh

  $TARGET_DIR/${agentScript}   $WAIT_INTERVAL_BEFORE_KICKOFF  2>&1  >  $TARGET_DIR/${agentLog}   &
  pid=$!
  echo Kicked off $type Agent with pid: $pid with output going to $TARGET_DIR/${agentLog}
  case "$type" in
     "Heap") heapAgentPid=$pid;;
     "Stats") statsAgentPid=$pid;;
     "Thread") threadAgentPid=$pid;;
  esac
}

function checkAgent {
  type=$1
  pid=$2

  ps -p $pid 2>&1 >/dev/null;
  status=$?
  if [ "$status" != "0" ]; then
    startAgent $type
  fi
}

function checkAllAgents {

  index=0
  for type in `echo ${AGENT_TYPES_ARRAY}`
  do
    #echo "Checking ${AGENT_TYPES_ARRAY[${index}]}Agent with pid: ${AGENT_PID_ARRAY[${index}]} "
    checkAgent $type ${AGENT_PID_ARRAY[${index}]}
    AGENT_PID_ARRAY[${index}]=$pid
    index=$((index+1))
  done
}

function startAllAgents
{
  for type in `echo ${AGENT_TYPES_ARRAY}`
  do
    startAgent $type
    AGENT_PID_LIST+=" $pid";
  done
  #echo $AGENT_PID_LIST

  AGENT_PID_ARRAY=($AGENT_PID_LIST)
}

function signalChildren {
  for var in `echo ${AGENT_PID_ARRAY}`
  do
    if ps -p $var > /dev/null
    then
      echo "sending $1 to $var"
      kill -s $1 $var
    fi
  done
}

startAllAgents
while ( test 1 )
do
  sleep 60
  checkAllAgents
done

# Use this for simple kick off agents without monitoring/restarts...
#$TARGET_DIR/dumpHeapAgent.sh   $WAIT_INTERVAL_BEFORE_KICKOFF  2>&1  >  $TARGET_DIR/dumpHeapAgent.log   &
#$TARGET_DIR/dumpStatsAgent.sh  $WAIT_INTERVAL_BEFORE_KICKOFF  2>&1  >  $TARGET_DIR/dumpStatsAgent.log  &
#$TARGET_DIR/dumpThreadAgent.sh $WAIT_INTERVAL_BEFORE_KICKOFF  2>&1  >  $TARGET_DIR/dumpThreadAgent.log &


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:background="#4caf50">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textSize="20sp"
        android:id="@+id/marker_name"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:gravity="center_horizontal" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textSize="20sp"
        android:id="@+id/marker_desc"
        android:layout_alignParentTop="true"
        android:layout_marginTop="30dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:gravity="center_horizontal" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textSize="20sp"
        android:id="@+id/marker_type"
        android:layout_alignParentTop="true"
        android:layout_marginTop="60dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:gravity="center_horizontal" />
</RelativeLayout>