asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xi...@apache.org
Subject asterixdb git commit: Fix uniontype compatibility issue in TweetParser
Date Fri, 02 Jun 2017 21:26:25 GMT
Repository: asterixdb
Updated Branches:
  refs/heads/master 1be612a8e -> 46518babd


Fix uniontype compatibility issue in TweetParser

1. Fix compatibility issue of UnionType in TweetParser.
2. Add unit test for TweetParser, covering missing attribute record
   filtering.

Change-Id: Id7e316d20f929236b3fa17618bb8f87d28ac7efc
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1786
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
BAD: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Steven Jacobs <sjaco002@ucr.edu>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/46518bab
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/46518bab
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/46518bab

Branch: refs/heads/master
Commit: 46518babd57147b66c4016cea520687ccfaf60c1
Parents: 1be612a
Author: Xikui Wang <xkkwww@gmail.com>
Authored: Mon May 29 22:55:51 2017 -0700
Committer: Xikui Wang <xkkwww@gmail.com>
Committed: Fri Jun 2 14:25:37 2017 -0700

----------------------------------------------------------------------
 asterixdb/asterix-external-data/pom.xml         |   1 +
 .../asterix/external/parser/TweetParser.java    |  45 +++++---
 .../external/parser/test/TweetParserTest.java   | 109 +++++++++++++++++++
 .../src/test/resources/test_tweets.txt          |   6 +
 4 files changed, 145 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/pom.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-external-data/pom.xml b/asterixdb/asterix-external-data/pom.xml
index ff9fcb0..460f57d 100644
--- a/asterixdb/asterix-external-data/pom.xml
+++ b/asterixdb/asterix-external-data/pom.xml
@@ -170,6 +170,7 @@
             <exclude>src/test/resources/classad/**</exclude> <!-- HTCondor
(license in LICENSE file) -->
             <exclude>src/test/resources/record.json</exclude> <!-- https://issues.apache.org/jira/browse/ASTERIXDB-1850
-->
             <exclude>src/test/resources/change_feed.csv</exclude>
+            <exclude>src/test/resources/test_tweets.txt</exclude>
           </excludes>
         </configuration>
       </plugin>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
index 1b29c887..be49863 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/TweetParser.java
@@ -24,16 +24,16 @@ import org.apache.asterix.builders.AbvsBuilderFactory;
 import org.apache.asterix.builders.IARecordBuilder;
 import org.apache.asterix.builders.IAsterixListBuilder;
 import org.apache.asterix.builders.ListBuilderFactory;
+import org.apache.asterix.builders.OrderedListBuilder;
 import org.apache.asterix.builders.RecordBuilderFactory;
-import org.apache.asterix.builders.UnorderedListBuilder;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.asterix.external.api.IRawRecord;
 import org.apache.asterix.external.api.IRecordDataParser;
-import org.apache.asterix.om.base.AMutablePoint;
 import org.apache.asterix.om.base.ANull;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.om.util.container.IObjectPool;
@@ -59,25 +59,28 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
 
     public TweetParser(ARecordType recordType) {
         this.recordType = recordType;
-        aPoint = new AMutablePoint(0, 0);
     }
 
-    private void parseUnorderedList(JsonNode jArray, DataOutput output) throws IOException
{
+    private void parseArrayList(JsonNode jArray, DataOutput output) throws IOException {
         ArrayBackedValueStorage itemBuffer = getTempBuffer();
-        UnorderedListBuilder unorderedListBuilder = (UnorderedListBuilder) getUnorderedListBuilder();
+        OrderedListBuilder arrayBuilder = (OrderedListBuilder) getArrayBuilder();
 
-        unorderedListBuilder.reset(null);
+        arrayBuilder.reset(null);
         for (int iter1 = 0; iter1 < jArray.size(); iter1++) {
             itemBuffer.reset();
             if (writeField(jArray.get(iter1), null, itemBuffer.getDataOutput())) {
-                unorderedListBuilder.addItem(itemBuffer);
+                arrayBuilder.addItem(itemBuffer);
             }
         }
-        unorderedListBuilder.write(output, true);
+        arrayBuilder.write(output, true);
     }
 
-    private boolean writeField(JsonNode fieldObj, IAType fieldType, DataOutput out) throws
IOException {
+    private boolean writeField(JsonNode fieldObj, IAType originalFieldType, DataOutput out)
throws IOException {
         boolean writeResult = true;
+        IAType fieldType = originalFieldType;
+        if (originalFieldType instanceof AUnionType) {
+            fieldType = ((AUnionType) originalFieldType).getActualType();
+        }
         if (fieldType != null) {
             switch (fieldType.getTypeTag()) {
                 case STRING:
@@ -103,6 +106,9 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
                 case OBJECT:
                     writeRecord(fieldObj, out, (ARecordType) fieldType);
                     break;
+                case ARRAY:
+                    parseArrayList(fieldObj, out);
+                    break;
                 default:
                     writeResult = false;
             }
@@ -126,7 +132,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
                 utf8Writer.writeUTF8(fieldObj.asText(), out);
             } else if (fieldObj.isArray()) {
                 if ((fieldObj).size() != 0) {
-                    parseUnorderedList(fieldObj, out);
+                    parseArrayList(fieldObj, out);
                 } else {
                     writeResult = false;
                 }
@@ -159,6 +165,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
         String[] curFNames = null;
         int fieldN;
         int attrIdx;
+        int expectedFieldsCount = 0;
 
         ArrayBackedValueStorage fieldValueBuffer = getTempBuffer();
         ArrayBackedValueStorage fieldNameBuffer = getTempBuffer();
@@ -167,6 +174,11 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
         if (curRecType != null) {
             curTypes = curRecType.getFieldTypes();
             curFNames = curRecType.getFieldNames();
+            for (IAType curType : curTypes) {
+                if (!(curType instanceof AUnionType)) {
+                    expectedFieldsCount++;
+                }
+            }
         }
 
         recBuilder.reset(curRecType);
@@ -178,10 +190,11 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
             for (int iter1 = 0; iter1 < fieldN; iter1++) {
                 fieldValueBuffer.reset();
                 DataOutput fieldOutput = fieldValueBuffer.getDataOutput();
-                if (obj.get(curFNames[iter1]).isNull()) {
+                if (obj.get(curFNames[iter1]).isNull() && !(curTypes[iter1] instanceof
AUnionType)) {
                     if (curRecType.isClosedField(curFNames[iter1])) {
                         throw new RuntimeDataException(ErrorCode.PARSER_TWEET_PARSER_CLOSED_FIELD_NULL,
-                                curFNames[iter1]);                    } else {
+                                curFNames[iter1]);
+                    } else {
                         continue;
                     }
                 } else {
@@ -198,7 +211,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
             Iterator<String> iter = obj.fieldNames();
             while (iter.hasNext()) {
                 attrName = iter.next();
-                if (obj.get(attrName).isNull() || obj.size() == 0) {
+                if (obj.get(attrName) == null || obj.get(attrName).isNull() || obj.size()
== 0) {
                     continue;
                 }
                 attrIdx = checkAttrNameIdx(curFNames, attrName);
@@ -219,7 +232,7 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
                     }
                 }
             }
-            if (curRecType != null && closedFieldCount < curFNames.length) {
+            if (curRecType != null && closedFieldCount < expectedFieldsCount)
{
                 throw new HyracksDataException("Non-null field is null");
             }
         }
@@ -230,8 +243,8 @@ public class TweetParser extends AbstractDataParser implements IRecordDataParser
         return recordBuilderPool.allocate(ATypeTag.OBJECT);
     }
 
-    private IAsterixListBuilder getUnorderedListBuilder() {
-        return listBuilderPool.allocate(ATypeTag.MULTISET);
+    private IAsterixListBuilder getArrayBuilder() {
+        return listBuilderPool.allocate(ATypeTag.ARRAY);
     }
 
     private ArrayBackedValueStorage getTempBuffer() {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
new file mode 100644
index 0000000..5389310
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/TweetParserTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.external.parser.test;
+
+import static org.apache.asterix.om.types.BuiltinType.AFLOAT;
+import static org.apache.asterix.om.types.BuiltinType.AINT64;
+import static org.apache.asterix.om.types.BuiltinType.AMISSING;
+import static org.apache.asterix.om.types.BuiltinType.ANULL;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.external.input.record.GenericRecord;
+import org.apache.asterix.external.parser.TweetParser;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import junit.extensions.PA;
+
+public class TweetParserTest {
+
+    @Test
+    public void openRecordTypeTest() throws IOException, URISyntaxException {
+        String[] ids = { "720549057849114629", "668950503552864257", "668945640186101761",
"263602997047730177",
+                "668948268605403136", "741701526859567104" };
+        // contruct type
+        IAType geoFieldType = new ARecordType("GeoType", new String[] { "coordinates" },
+                new IAType[] { new AOrderedListType(AFLOAT, "point") }, true);
+        List<IAType> unionTypeList = new ArrayList<>();
+        unionTypeList.add(geoFieldType);
+        unionTypeList.add(ANULL);
+        unionTypeList.add(AMISSING);
+        IAType geoUnionType = new AUnionType(unionTypeList, "GeoType?");
+        ARecordType tweetRecordType = new ARecordType("TweetType", new String[] { "id", "geo"
},
+                new IAType[] { AINT64, geoUnionType }, true);
+
+        TweetParser parser = new TweetParser(tweetRecordType);
+
+        List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("/test_tweets.txt").toURI()));
+        ByteArrayOutputStream is = new ByteArrayOutputStream();
+        DataOutput output = new DataOutputStream(is);
+        for (int iter1 = 0; iter1 < lines.size(); iter1++) {
+            GenericRecord<String> record = new GenericRecord<>();
+            record.set(lines.get(iter1));
+            try {
+                parser.parse(record, output);
+            } catch (HyracksDataException e) {
+                e.printStackTrace();
+                Assert.fail("Unexpected failure in parser.");
+            }
+            Assert.assertTrue((PA.getValue(parser, "aInt64")).toString().equals(ids[iter1]));
+        }
+    }
+
+    @Test
+    public void closedRecordTypeTest() throws IOException, URISyntaxException {
+        // contruct type
+        IAType geoFieldType = new ARecordType("GeoType", new String[] { "coordinates" },
+                new IAType[] { new AOrderedListType(AFLOAT, "point") }, true);
+        ARecordType tweetRecordType = new ARecordType("TweetType", new String[] { "id", "geo"
},
+                new IAType[] { AINT64, geoFieldType }, true);
+
+        TweetParser parser = new TweetParser(tweetRecordType);
+        List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("/test_tweets.txt").toURI()));
+        ByteArrayOutputStream is = new ByteArrayOutputStream();
+        DataOutput output = new DataOutputStream(is);
+        int regularCount = 0;
+        for (int iter1 = 0; iter1 < lines.size(); iter1++) {
+            GenericRecord<String> record = new GenericRecord<>();
+            record.set(lines.get(iter1));
+            try {
+                parser.parse(record, output);
+                regularCount++;
+            } catch (HyracksDataException e) {
+                Assert.assertTrue(e.toString().contains("Non-null") && (iter1 ==
0 || iter1 == 1));
+            }
+        }
+        Assert.assertTrue(regularCount == 4);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/46518bab/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt b/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt
new file mode 100644
index 0000000..ed8869a
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/test/resources/test_tweets.txt
@@ -0,0 +1,6 @@
+{"created_at":"Thu Apr 14 09:47:37 +0000 2016","id":720549057849114629,"id_str":"720549057849114629","text":"Pumpins
and mother lovin humpins! https:\/\/t.co\/UFY2ptZEDE","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\"
rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":22718875,"id_str":"22718875","name":"Austin
Ireland","screen_name":"fastirish","location":"GaageBox2.0","url":null,"description":"CrossFit,
raising elite offspring and tattoos. O, and tiny dogs!! #garagebox2.0 #unaffiliated","protected":false,"verified":false,"followers_count":206,"friends_count":336,"listed_count":10,"favourites_count":888,"statuses_count":1775,"created_at":"Wed
Mar 04 02:14:49 +0000 2009","utc_offset":-14400,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enab
 led":false,"is_translator":false,"profile_background_color":"352726","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_tile":false,"profile_link_color":"D02B55","profile_sidebar_border_color":"829D5E","profile_sidebar_fill_color":"99CC33","profile_text_color":"3E4415","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/712092320099868672\/YUUcDgwG_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/712092320099868672\/YUUcDgwG_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/22718875\/1458315357","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":{"id":"07d9d0f1fd482001","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/07d9d0f1fd4
 82001.json","place_type":"poi","name":"Steeplechase","full_name":"Steeplechase","country_code":"US","country":"United
States","bounding_box":{"type":"Polygon","coordinates":[[[-75.655008,38.355629],[-75.655008,38.355629],[-75.655008,38.355629],[-75.655008,38.355629]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[],"symbols":[],"media":[{"id":720549047702986752,"id_str":"720549047702986752","indices":[34,57],"media_url":"http:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","url":"https:\/\/t.co\/UFY2ptZEDE","display_url":"pic.twitter.com\/UFY2ptZEDE","expanded_url":"http:\/\/twitter.com\/fastirish\/status\/720549057849114629\/photo\/1","type":"photo","sizes":{"small":{"w":340,"h":453,"resize":"fit"},"large":{"w":960,"h":1280,"resize":"fit"},"medium":{"w":600,"h":800,"resize":"fit"},"thumb":{"w":150,"h":150,"r
 esize":"crop"}}}]},"extended_entities":{"media":[{"id":720549047702986752,"id_str":"720549047702986752","indices":[34,57],"media_url":"http:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/Cf_nio-VIAAd6wB.jpg","url":"https:\/\/t.co\/UFY2ptZEDE","display_url":"pic.twitter.com\/UFY2ptZEDE","expanded_url":"http:\/\/twitter.com\/fastirish\/status\/720549057849114629\/photo\/1","type":"photo","sizes":{"small":{"w":340,"h":453,"resize":"fit"},"large":{"w":960,"h":1280,"resize":"fit"},"medium":{"w":600,"h":800,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"}}}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1460627257202"}
+{"created_at":"Tue Nov 24 00:33:23 +0000 2015","id":668950503552864257,"id_str":"668950503552864257","text":"@K_Jenkins22
I know it could always be worse, lol I could always be a saints fan \ud83d\ude02","source":"\u003ca
href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":668949646656593920,"in_reply_to_status_id_str":"668949646656593920","in_reply_to_user_id":322358152,"in_reply_to_user_id_str":"322358152","in_reply_to_screen_name":"K_Jenkins22","user":{"id":375920299,"id_str":"375920299","name":"Taylor
Casey","screen_name":"TeeCasey11","location":"Louisville Ky","url":null,"description":"I cant
drown my demons they know how to swim","protected":false,"verified":false,"followers_count":614,"friends_count":327,"listed_count":1,"favourites_count":1518,"statuses_count":25058,"created_at":"Mon
Sep 19 00:06:07 +0000 2011","utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabl
 ed":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/650694639981363200\/baMfTh4z_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/650694639981363200\/baMfTh4z_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/375920299\/1395204592","default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":{"id":"000df0c11a2783f2","url":"https:\/\/api
 .twitter.com\/1.1\/geo\/id\/000df0c11a2783f2.json","place_type":"city","name":"Hillview","full_name":"Hillview,
KY","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-85.710047,38.029300],[-85.710047,38.086251],[-85.608063,38.086251],[-85.608063,38.029300]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"K_Jenkins22","name":"Kirsty
Jenkins","id":322358152,"id_str":"322358152","indices":[0,12]}],"symbols":[]},"favorited":false,"retweeted":false,"filter_level":"low","lang":"en","timestamp_ms":"1448325203203"}
+{"created_at":"Tue Nov 24 00:14:03 +0000 2015","id":668945640186101761,"id_str":"668945640186101761","text":"Just
posted a photo @ Campus Martius Park https:\/\/t.co\/5Ax4E2CdWZ","source":"\u003ca href=\"http:\/\/instagram.com\"
rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":48121888,"id_str":"48121888","name":"Kevin
McKague","screen_name":"KevinOfMI","location":"Davison, Michigan","url":"http:\/\/KevinMcKague.wordpress.com","description":"I
need to ride my bike until my brain shuts up and my muscles are screaming.\u00a0\nRight after
these donuts. Dad of 3.\n Visit my blog 18 Wheels and a 12-Speed Bike.","protected":false,"verified":false,"followers_count":1178,"friends_count":1780,"listed_count":50,"favourites_count":2319,"statuses_count":22263,"created_at":"Wed
Jun 17 21:24:03 +0000 2009","utc_offset"
 :-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"EBF5ED","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/378800000153875492\/VrUNrXXF.jpeg","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/378800000153875492\/VrUNrXXF.jpeg","profile_background_tile":true,"profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDFFCC","profile_text_color":"333333","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/646097130977890304\/izCl0tCD_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/646097130977890304\/izCl0tCD_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/48121888\/1441581344","default_profile":false,"default_profile_image":false,"following":null,"follow_reques
 t_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[42.33170228,-83.04647491]},"coordinates":{"type":"Point","coordinates":[-83.04647491,42.33170228]},"place":{"id":"b463d3bd6064861b","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/b463d3bd6064861b.json","place_type":"city","name":"Detroit","full_name":"Detroit,
MI","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-83.288056,42.255085],[-83.288056,42.450488],[-82.910520,42.450488],[-82.910520,42.255085]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/5Ax4E2CdWZ","expanded_url":"https:\/\/instagram.com\/p\/-cnH0kFL_g\/","display_url":"instagram.com\/p\/-cnH0kFL_g\/","indices":[42,65]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1448324043686"}
+{"contributors":null,"text":"@Thaynalhul qosjaosjoa e tu nem viu","geo":{"type":"Point","coordinates":[-29.9460537,-50.99058655]},"retweeted":false,"in_reply_to_screen_name":"Thaynalhul","truncated":false,"entities":{"urls":[],"hashtags":[],"user_mentions":[{"id":157459005,"name":"Thayná
Lhul","indices":[0,11],"screen_name":"Thaynalhul","id_str":"157459005"}]},"in_reply_to_status_id_str":"263602825592979456","id":263602997047730177,"in_reply_to_user_id_str":"157459005","source":"<a
href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>","favorited":false,"in_reply_to_status_id":263602825592979456,"in_reply_to_user_id":157459005,"retweet_count":0,"created_at":"Wed
Oct 31 11:27:06 +0000 2012","id_str":"263602997047730177","place":{"id":"66a72011ed6d4853","bounding_box":{"type":"Polygon","coordinates":[[[-51.1012029,-30.0156525],[-50.8114625,-30.0156525],[-50.8114625,-29.765777],[-51.1012029,-29.765777]]]},"place_type":"city","name":"Gravataí","attribute
 s":{},"country_code":"BR","url":"http://api.twitter.com/1/geo/id/66a72011ed6d4853.json","full_name":"Gravataí,
Rio Grande do Sul","country":"Brasil"},"user":{"location":"","default_profile":false,"profile_background_tile":true,"statuses_count":26476,"lang":"pt","profile_link_color":"0099CC","profile_banner_url":"https://si0.twimg.com/profile_banners/338399662/1351549264","id":338399662,"following":null,"protected":false,"favourites_count":247,"profile_text_color":"333333","contributors_enabled":false,"verified":false,"description":"\u201cPorque
a vida só dá pra quem se deu, pra quem amou, pra quem chorou, pra quem sofreu.\u201d #Belieber
","name":"beatriz ","profile_sidebar_border_color":"fff","profile_background_color":"FFF04D","created_at":"Tue
Jul 19 14:39:45 +0000 2011","default_profile_image":false,"followers_count":998,"profile_image_url_https":"https://si0.twimg.com/profile_images/2778405459/f682a9eadbbe5ed9bc37c9e8e5a1d33b_normal.jpeg","geo_enabled":true,"profile_backgrou
 nd_image_url":"http://a0.twimg.com/profile_background_images/697292787/7156609856becbed318bffd052449fc8.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/697292787/7156609856becbed318bffd052449fc8.jpeg","follow_request_sent":null,"url":"http://ask.fm/soudaviuscka","utc_offset":-14400,"time_zone":"Santiago","notifications":null,"profile_use_background_image":true,"friends_count":277,"profile_sidebar_fill_color":"E6F6F9","screen_name":"bewexell","id_str":"338399662","profile_image_url":"http://a0.twimg.com/profile_images/2778405459/f682a9eadbbe5ed9bc37c9e8e5a1d33b_normal.jpeg","is_translator":false,"listed_count":3},"coordinates":{"type":"Point","coordinates":[-50.99058655,-29.9460537]}}
+{"created_at":"Tue Nov 24 00:24:30 +0000 2015","id":668948268605403136,"id_str":"668948268605403136","text":"\u26a1\ufe0fFeed
me energy, I'll feed it back\/Spread love\/ Be the energy. It's more to opening your eyes.
After\u2026 https:\/\/t.co\/SYWXANPYxI","source":"\u003ca href=\"http:\/\/instagram.com\"
rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":35392759,"id_str":"35392759","name":"See-Oh-Be-Uh","screen_name":"ItsSeobia","location":"Exploring","url":null,"description":"Lifestyle
over everything. We might take a break, but we don't quit. #Active #MovementSpeaksLouderThanYourTweets
#EarnYourStripes","protected":false,"verified":false,"followers_count":951,"friends_count":471,"listed_count":28,"favourites_count":690,"statuses_count":49387,"created_at":"Sun
Apr 26 03:38:50 +0000 2009","utc_offset":-21
 600,"time_zone":"Central Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"A336F7","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/215051616\/purple_flower.jpg","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/215051616\/purple_flower.jpg","profile_background_tile":true,"profile_link_color":"05FF22","profile_sidebar_border_color":"099FF0","profile_sidebar_fill_color":"030003","profile_text_color":"8911B8","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/574735896752308225\/EDeXr2-5_normal.png","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/574735896752308225\/EDeXr2-5_normal.png","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/35392759\/1428866329","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"
 notifications":null},"geo":{"type":"Point","coordinates":[41.8,-87.59]},"coordinates":{"type":"Point","coordinates":[-87.59,41.8]},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/SYWXANPYxI","expanded_url":"https:\/\/instagram.com\/p\/-coUG4GMYI\/","display_url":"instagram.com\/p\/-coUG4GMYI\/","indices":[103,126]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1448324670350"}
+{"created_at":"Sat Jun 11 18:39:58 +0000 2016","id":741701526859567104,"id_str":"741701526859567104","text":"Jazz
Age Lawn Party #jalp2016 #governorsisland @ Governors Island https:\/\/t.co\/kj4dLzdngB","source":"\u003ca
href=\"http:\/\/instagram.com\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":17816081,"id_str":"17816081","name":"Paul
Herrera","screen_name":"pherrera","location":"New York, NY","url":"http:\/\/www.pherrera.com","description":"The
Michael Jordan of something","protected":false,"verified":false,"followers_count":479,"friends_count":443,"listed_count":36,"favourites_count":40,"statuses_count":12911,"created_at":"Tue
Dec 02 19:36:06 +0000 2008","utc_offset":-14400,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"
 profile_background_color":"352726","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme5\/bg.gif","profile_background_tile":false,"profile_link_color":"D02B55","profile_sidebar_border_color":"829D5E","profile_sidebar_fill_color":"99CC33","profile_text_color":"3E4415","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/719606026153144321\/JrfcfLdP_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/719606026153144321\/JrfcfLdP_normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/17816081\/1354488949","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[40.69138889,-74.01611111]},"coordinates":{"type":"Point","coordinates":[-74.01611111,40.69138889]},"place":{"id":"01a9a
 39529b27f36","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/01a9a39529b27f36.json","place_type":"city","name":"Manhattan","full_name":"Manhattan,
NY","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-74.026675,40.683935],[-74.026675,40.877483],[-73.910408,40.877483],[-73.910408,40.683935]]]},"attributes":{}},"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"jalp2016","indices":[20,29]},{"text":"governorsisland","indices":[30,46]}],"urls":[{"url":"https:\/\/t.co\/kj4dLzdngB","expanded_url":"https:\/\/www.instagram.com\/p\/BGhkqneIg8O\/","display_url":"instagram.com\/p\/BGhkqneIg8O\/","indices":[66,89]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1465670398808"}
\ No newline at end of file


Mime
View raw message