Initial
This commit is contained in:
commit
1eddb4eb81
73
build.xml
Normal file
73
build.xml
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="VkDialogSaver" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project VkDialogSaver.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar: JAR building
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="VkDialogSaver-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
49
config.txt
Normal file
49
config.txt
Normal file
@ -0,0 +1,49 @@
|
||||
###################
|
||||
# общие настройки #
|
||||
###################
|
||||
|
||||
# рабочая директория, куда будут положены файлы сообщений
|
||||
# и откуда они будут читаться при генерировании html
|
||||
workDir = tmp/
|
||||
|
||||
# id Вашего приложения вк
|
||||
appId =
|
||||
|
||||
# токен доступа. Если оставить пустым, будет
|
||||
# открыта страница для его получения
|
||||
accessToken =
|
||||
|
||||
# режим:
|
||||
# get - получение диалогов
|
||||
# generate - генерирование html
|
||||
mode = get
|
||||
|
||||
|
||||
############################
|
||||
# настройки для режима get #
|
||||
############################
|
||||
|
||||
## id собеседника
|
||||
dialogId = 1
|
||||
|
||||
## с какой по какую позиции получать сообщения
|
||||
fromOffset = 0
|
||||
toOffset = 3000
|
||||
|
||||
|
||||
#################################
|
||||
# настройки для режима generate #
|
||||
#################################
|
||||
|
||||
## с какого по какой год генерировать
|
||||
## html-страницы из полученных ранее сообщений
|
||||
fromYear = 2015
|
||||
toYear = 2017
|
||||
|
||||
## имя отправителя, то есть Ваше имя
|
||||
outName = Я
|
||||
|
||||
## список имён пользователей и их id
|
||||
1 = Паша Дуров
|
||||
yy = Имя Отчество
|
||||
zz = Кто-то неизвестный
|
1640
nbproject/build-impl.xml
Normal file
1640
nbproject/build-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
8
nbproject/genfiles.properties
Normal file
8
nbproject/genfiles.properties
Normal file
@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=1f1ee2ea
|
||||
build.xml.script.CRC32=77c87077
|
||||
build.xml.stylesheet.CRC32=8064a381@1.75.0.48
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=1f1ee2ea
|
||||
nbproject/build-impl.xml.script.CRC32=0106952b
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=bd492785@1.85.0.48
|
0
nbproject/private/config.properties
Normal file
0
nbproject/private/config.properties
Normal file
6
nbproject/private/private.properties
Normal file
6
nbproject/private/private.properties
Normal file
@ -0,0 +1,6 @@
|
||||
compile.on.save=true
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
user.properties.file=C:\\Users\\aNNiMON\\AppData\\Roaming\\NetBeans\\dev\\build.properties
|
12
nbproject/private/private.xml
Normal file
12
nbproject/private/private.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group>
|
||||
<file>file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_Java%20SE/VkDialogSaver/src/com/annimon/vkdialogsaver/Config.java</file>
|
||||
<file>file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_Java%20SE/VkDialogSaver/src/com/annimon/vkdialogsaver/MessageParser.java</file>
|
||||
<file>file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_Java%20SE/VkDialogSaver/src/com/annimon/vkdialogsaver/Main.java</file>
|
||||
<file>file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_Java%20SE/VkDialogSaver/src/com/annimon/vkdialogsaver/VkDialog.java</file>
|
||||
</group>
|
||||
</open-files>
|
||||
</project-private>
|
86
nbproject/project.properties
Normal file
86
nbproject/project.properties
Normal file
@ -0,0 +1,86 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=
|
||||
annotation.processing.run.all.processors=true
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=VkDialogSaver
|
||||
application.vendor=aNNiMON
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.modulepath=\
|
||||
${run.modulepath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
debug.test.modulepath=\
|
||||
${run.test.modulepath}
|
||||
# Files in build.classes.dir which should be excluded from distribution jar
|
||||
dist.archive.excludes=
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/VkDialogSaver.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.modulepath=
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.8
|
||||
javac.target=1.8
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
javac.test.modulepath=\
|
||||
${javac.modulepath}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
main.class=com.annimon.vkdialogsaver.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project.
|
||||
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
|
||||
# To set system properties for unit tests define test-sys-prop.name=value:
|
||||
run.jvmargs=
|
||||
run.modulepath=\
|
||||
${javac.modulepath}:\
|
||||
${build.classes.dir}
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
run.test.modulepath=\
|
||||
${javac.test.modulepath}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
13
nbproject/project.xml
Normal file
13
nbproject/project.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>VkDialogSaver</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots/>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
113
src/com/annimon/vkdialogsaver/AlphanumComparator.java
Normal file
113
src/com/annimon/vkdialogsaver/AlphanumComparator.java
Normal file
@ -0,0 +1,113 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
/*
|
||||
* The Alphanum Algorithm is an improved sorting algorithm for strings
|
||||
* containing numbers. Instead of sorting numbers in ASCII order like
|
||||
* a standard sort, this algorithm sorts numbers in numeric order.
|
||||
*
|
||||
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* This is an updated version with enhancements made by Daniel Migowski,
|
||||
* Andre Bogus, and David Koelle
|
||||
*
|
||||
* To convert to use Templates (Java 1.5+):
|
||||
* - Change "implements Comparator" to "implements Comparator<String>"
|
||||
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
|
||||
* - Remove the type checking and casting in compare().
|
||||
*
|
||||
* To use this class:
|
||||
* Use the static "sort" method from the java.util.Collections class:
|
||||
* Collections.sort(your list, new AlphanumComparator());
|
||||
*/
|
||||
public class AlphanumComparator implements Comparator<Path> {
|
||||
|
||||
/**
|
||||
* Length of string is passed in for improved efficiency (only need to calculate it once) *
|
||||
*/
|
||||
private String getChunk(String s, int slength, int marker) {
|
||||
StringBuilder chunk = new StringBuilder();
|
||||
char c = s.charAt(marker);
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
if (Character.isDigit(c)) {
|
||||
while (marker < slength) {
|
||||
c = s.charAt(marker);
|
||||
if (!Character.isDigit(c))
|
||||
break;
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
}
|
||||
} else {
|
||||
while (marker < slength) {
|
||||
c = s.charAt(marker);
|
||||
if (Character.isDigit(c))
|
||||
break;
|
||||
chunk.append(c);
|
||||
marker++;
|
||||
}
|
||||
}
|
||||
return chunk.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Path p1, Path p2) {
|
||||
String s1 = p1.getFileName().toString();
|
||||
String s2 = p2.getFileName().toString();
|
||||
int thisMarker = 0;
|
||||
int thatMarker = 0;
|
||||
int s1Length = s1.length();
|
||||
int s2Length = s2.length();
|
||||
|
||||
while (thisMarker < s1Length && thatMarker < s2Length) {
|
||||
String thisChunk = getChunk(s1, s1Length, thisMarker);
|
||||
thisMarker += thisChunk.length();
|
||||
|
||||
String thatChunk = getChunk(s2, s2Length, thatMarker);
|
||||
thatMarker += thatChunk.length();
|
||||
|
||||
// If both chunks contain numeric characters, sort them numerically
|
||||
int result = 0;
|
||||
if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
|
||||
// Simple chunk comparison by length.
|
||||
int thisChunkLength = thisChunk.length();
|
||||
result = thisChunkLength - thatChunk.length();
|
||||
// If equal, the first different number counts
|
||||
if (result == 0) {
|
||||
for (int i = 0; i < thisChunkLength; i++) {
|
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = thisChunk.compareTo(thatChunk);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
return s1Length - s2Length;
|
||||
}
|
||||
}
|
120
src/com/annimon/vkdialogsaver/Config.java
Normal file
120
src/com/annimon/vkdialogsaver/Config.java
Normal file
@ -0,0 +1,120 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class Config {
|
||||
|
||||
public static Config load() throws IOException {
|
||||
final Map<String, String> data = Files.lines(Paths.get("config.txt"))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.filter(s -> !s.startsWith("#"))
|
||||
.map(s -> s.split("="))
|
||||
.map(arr -> new String[] {
|
||||
arr[0].trim().toLowerCase(),
|
||||
arr.length > 1 ? arr[1].trim() : ""
|
||||
})
|
||||
.collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
|
||||
|
||||
final Base base = new Base();
|
||||
base.appId = data.getOrDefault("appid", ""); // 4422363
|
||||
base.accessToken = data.getOrDefault("accesstoken", "");
|
||||
base.workDir = data.getOrDefault("workdir", "");
|
||||
base.mode = data.getOrDefault("mode", "");
|
||||
|
||||
final Get get = new Get();
|
||||
get.dialogId = data.getOrDefault("dialogid", "");
|
||||
get.fromOffset = Integer.parseInt(data.getOrDefault("fromoffset", "0"));
|
||||
get.toOffset = Integer.parseInt(data.getOrDefault("tooffset", "300"));
|
||||
|
||||
final Generate gen = new Generate();
|
||||
gen.fromYear = Integer.parseInt(data.getOrDefault("fromyear", "2013"));
|
||||
gen.toYear = Integer.parseInt(data.getOrDefault("toyear", "2017"));
|
||||
gen.outName = data.getOrDefault("outname", "Я");
|
||||
|
||||
final Map<Integer, String> users = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, String> e : data.entrySet()) {
|
||||
try {
|
||||
int id = Integer.parseInt(e.getKey().trim());
|
||||
users.put(id, e.getValue());
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
return new Config(base, get, gen, users);
|
||||
}
|
||||
|
||||
private static class Base {
|
||||
String workDir, appId, accessToken;
|
||||
String mode;
|
||||
}
|
||||
|
||||
private static class Get {
|
||||
String dialogId;
|
||||
int fromOffset, toOffset;
|
||||
}
|
||||
|
||||
private static class Generate {
|
||||
int fromYear, toYear;
|
||||
String outName;
|
||||
}
|
||||
|
||||
private final Base base;
|
||||
private final Get get;
|
||||
private final Generate gen;
|
||||
private final Map<Integer, String> users;
|
||||
|
||||
private Config(Base base, Get get, Generate gen, Map<Integer, String> users) {
|
||||
this.base = base;
|
||||
this.get = get;
|
||||
this.gen = gen;
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
public String getWorkDir() {
|
||||
return base.workDir;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return base.appId;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return base.accessToken;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return base.mode;
|
||||
}
|
||||
|
||||
public String getDialogId() {
|
||||
return get.dialogId;
|
||||
}
|
||||
|
||||
public int getFromOffset() {
|
||||
return get.fromOffset;
|
||||
}
|
||||
|
||||
public int getToOffset() {
|
||||
return get.toOffset;
|
||||
}
|
||||
|
||||
public int getFromYear() {
|
||||
return gen.fromYear;
|
||||
}
|
||||
|
||||
public int getToYear() {
|
||||
return gen.toYear;
|
||||
}
|
||||
|
||||
public String getOutName() {
|
||||
return gen.outName;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getUsers() {
|
||||
return users;
|
||||
}
|
||||
}
|
60
src/com/annimon/vkdialogsaver/Emoji.java
Normal file
60
src/com/annimon/vkdialogsaver/Emoji.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Класс вывода сообщений со смайлами.
|
||||
*/
|
||||
public final class Emoji {
|
||||
|
||||
private static final char[] emojiChars = {
|
||||
'\u203c', '\u2049', '\u2139', '\u2194', '\u2195', '\u2196', '\u2197', '\u2198', '\u2199', '\u21a9', '\u21aa',
|
||||
'\u231a', '\u231b', '\u23e9', '\u23ea', '\u23eb', '\u23ec', '\u23f0', '\u23f3', '\u24c2', '\u25aa', '\u25ab',
|
||||
'\u25b6', '\u25c0', '\u25fb', '\u25fc', '\u25fd', '\u25fe', '\u2600', '\u2601', '\u260e', '\u2611', '\u2614',
|
||||
'\u2615', '\u261d', '\u263a', '\u2648', '\u2649', '\u264a', '\u264b', '\u264c', '\u264d', '\u264e', '\u264f',
|
||||
'\u2650', '\u2651', '\u2652', '\u2653', '\u2660', '\u2663', '\u2665', '\u2666', '\u2668', '\u267b', '\u267f',
|
||||
'\u2693', '\u26a0', '\u26a1', '\u26aa', '\u26ab', '\u26bd', '\u26be', '\u26c4', '\u26c5', '\u26ce', '\u26d4',
|
||||
'\u26ea', '\u26f2', '\u26f3', '\u26f5', '\u26fa', '\u26fd', '\u2702', '\u2705', '\u2708', '\u2709', '\u270a',
|
||||
'\u270b', '\u270c', '\u270f', '\u2712', '\u2714', '\u2716', '\u2728', '\u2733', '\u2734', '\u2744', '\u2747',
|
||||
'\u274c', '\u274e', '\u2753', '\u2754', '\u2755', '\u2757', '\u2764', '\u2795', '\u2796', '\u2797', '\u27a1',
|
||||
'\u27b0', '\u27bf', '\u2934', '\u2935', '\u2b05', '\u2b06', '\u2b07', '\u2b1b', '\u2b1c', '\u2b50', '\u2b55',
|
||||
'\u3030', '\u303d', '\u3297', '\u3299'
|
||||
};
|
||||
|
||||
public static CharSequence printEmoji(final CharSequence message) {
|
||||
if (message == null || message.length() == 0) {
|
||||
return message;
|
||||
}
|
||||
|
||||
long n = 0;
|
||||
for (int i = 0; i < message.length(); ++i) {
|
||||
final char ch = message.charAt(i);
|
||||
if (ch == '\ud83c' || ch == '\ud83d' || (n != 0 && (0xFFFFFFFF00000000L & n) == 0 && ch >= '\udde6' && ch <= '\uddfa')) {
|
||||
n = (n << 16 | ch);
|
||||
} else if (n > 0 && ('\uf000' & ch) == '\ud000') {
|
||||
Emoji.printImage(n << 16 | ch);
|
||||
n = 0;
|
||||
} else if (ch == '\u20e3') {
|
||||
if (i > 0) {
|
||||
// Смайлы с цифрами 0..9 и #, на сайте для них нет картинок.
|
||||
final char prev = message.charAt(i - 1);
|
||||
if ((prev >= '0' && prev <= '9') || prev == '#') {
|
||||
System.out.print("<"+prev+">");
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
} else if (Arrays.binarySearch(emojiChars, ch) != -1) {
|
||||
Emoji.printImage((long)ch);
|
||||
} else {
|
||||
System.out.print(ch);
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private static void printImage(long val) {
|
||||
String emoji = String.format("%8X", val).trim();
|
||||
System.out.print(" <img src='http://vk.com/images/emoji/" + emoji + ".png' /> ");
|
||||
}
|
||||
}
|
24
src/com/annimon/vkdialogsaver/Main.java
Normal file
24
src/com/annimon/vkdialogsaver/Main.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
final Config config = Config.load();
|
||||
switch (config.getMode()) {
|
||||
case "get":
|
||||
VkDialog.setConfig(config);
|
||||
VkDialog.save(config.getDialogId(), config.getFromOffset(), config.getToOffset());
|
||||
return;
|
||||
|
||||
case "generate":
|
||||
MessageParser.setConfig(config);
|
||||
MessageParser.parse();
|
||||
return;
|
||||
|
||||
default:
|
||||
System.out.println("Ошибка! Неверный режим.");
|
||||
}
|
||||
}
|
||||
}
|
161
src/com/annimon/vkdialogsaver/MessageParser.java
Normal file
161
src/com/annimon/vkdialogsaver/MessageParser.java
Normal file
@ -0,0 +1,161 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import com.vk.sdk.api.model.VKApiMessage;
|
||||
import com.vk.sdk.api.model.VKAttachments;
|
||||
import com.vk.sdk.api.model.VKList;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class MessageParser {
|
||||
|
||||
private static Config config;
|
||||
|
||||
public static void setConfig(Config config) {
|
||||
MessageParser.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Пакетный парсинг файлов в папке
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void parse() throws IOException {
|
||||
VKList<VKApiMessage> messages = new VKList<>();
|
||||
Files.list(Paths.get(config.getWorkDir()))
|
||||
.filter(p -> p.toString().endsWith(".txt"))
|
||||
.sorted(new AlphanumComparator())
|
||||
.forEach(p -> messages.addAll(readMessages(p)));
|
||||
|
||||
for (int year = config.getFromYear(); year <= config.getToYear(); year++) {
|
||||
LocalDateTime from = LocalDateTime.of(year, Month.JANUARY, 1, 0, 0);
|
||||
LocalDateTime to = from.plusYears(1);
|
||||
VKList<VKApiMessage> query = new VKList<>(messages.stream()
|
||||
.filter(msg -> getDateTime(msg.date).isAfter(from)
|
||||
&& getDateTime(msg.date).isBefore(to))
|
||||
.collect(Collectors.toList()));
|
||||
generate(query, String.valueOf(year));
|
||||
}
|
||||
/*VKList<VKApiMessage> query = new VKList<>(messages.stream()
|
||||
.filter(msg -> hasAttachment(msg.attachments, VKAttachments.TYPE_AUDIO))
|
||||
.collect(Collectors.toList()));
|
||||
generate(query, "audio_");*/
|
||||
}
|
||||
|
||||
private static boolean hasAttachment(VKAttachments attachments, String type) {
|
||||
return attachments.stream().anyMatch(a -> a.getType().equals(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Парсинг одного конкретного файла
|
||||
* @param filename
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void parse(String filename) throws IOException {
|
||||
final String fullPath = config.getWorkDir() + filename;
|
||||
VKList<VKApiMessage> messages = readMessages(Paths.get(fullPath));
|
||||
generate(messages, filename);
|
||||
}
|
||||
|
||||
private static VKList<VKApiMessage> readMessages(Path fullPath) {
|
||||
try {
|
||||
final String content = new String(Files.readAllBytes(fullPath), "UTF-8");
|
||||
|
||||
JSONObject jsonObject = new JSONObject(content);
|
||||
return new VKList<>(jsonObject, VKApiMessage.class);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return new VKList<>();
|
||||
}
|
||||
|
||||
private static void generate(VKList<VKApiMessage> messages, String outFilename) throws IOException {
|
||||
final String outPath = config.getWorkDir() + outFilename + ".html";
|
||||
final File file = new File(outPath);
|
||||
System.setOut(new PrintStream(file));
|
||||
generate(messages);
|
||||
Desktop.getDesktop().browse(file.toURI());
|
||||
}
|
||||
|
||||
private static void generate(VKList<VKApiMessage> messages) throws IOException {
|
||||
System.out.println("<html>");
|
||||
System.out.println("<head><link rel='stylesheet' type='text/css' href='styles/main.css'></head>");
|
||||
messages.stream().forEach(new MessageConsumer());
|
||||
System.out.println("</html>");
|
||||
}
|
||||
|
||||
private static class MessageConsumer implements Consumer<VKApiMessage> {
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd MMMM uuuu", Locale.getDefault());
|
||||
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm", Locale.getDefault());
|
||||
|
||||
@Override
|
||||
public void accept(VKApiMessage message) {
|
||||
println(String.format("<span class='im_log_author'>%s</span>", getName(message.user_id, message.out)));
|
||||
final LocalDateTime dateTime = getDateTime(message.date);
|
||||
String date = dateTime.format(DATE_FORMATTER) + " " + dateTime.format(TIME_FORMATTER);
|
||||
println(String.format("<span class='im_date_link'>%s</span>", date));
|
||||
if (!message.body.isEmpty()) {
|
||||
message.body = replaceHtml(message.body);
|
||||
if (message.emoji) {
|
||||
Emoji.printEmoji(message.body);
|
||||
println();
|
||||
} else println(message.body);
|
||||
}
|
||||
if (!message.fwd_messages.isEmpty()) {
|
||||
System.out.println("<div class='wall'>");
|
||||
message.fwd_messages.forEach(new MessageConsumer());
|
||||
System.out.println("</div>");
|
||||
}
|
||||
if (!message.attachments.isEmpty()) {
|
||||
System.out.println("<div class='hr'>");
|
||||
message.attachments.forEach((attachment) -> {
|
||||
println(attachment.toHtml());
|
||||
});
|
||||
System.out.println("</div>");
|
||||
}
|
||||
println();
|
||||
}
|
||||
|
||||
private String getName(int id, boolean out) {
|
||||
if (out) return config.getOutName();
|
||||
return config.getUsers().getOrDefault(id, Integer.toString(id));
|
||||
}
|
||||
}
|
||||
|
||||
private static String replaceHtml(String in) {
|
||||
return in.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("\n", "<br/>");
|
||||
}
|
||||
|
||||
private static LocalDateTime getDateTime(long timestamp) {
|
||||
return LocalDateTime.ofEpochSecond(timestamp, 0, ZoneOffset.ofHours(+3));
|
||||
}
|
||||
|
||||
private static void println(Object text) {
|
||||
System.out.print(text);
|
||||
System.out.println("<br/>");
|
||||
}
|
||||
|
||||
private static void println() {
|
||||
System.out.println("<br/>");
|
||||
}
|
||||
}
|
127
src/com/annimon/vkdialogsaver/VkApi.java
Normal file
127
src/com/annimon/vkdialogsaver/VkApi.java
Normal file
@ -0,0 +1,127 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* VK API sample implementation for Java 8.
|
||||
* @see https://github.com/liosha2007/vkontakte-api
|
||||
* @author liosha2007
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class VkApi {
|
||||
|
||||
private static final String API_VERSION = "5.21";
|
||||
|
||||
private static final String AUTH_URL = "https://oauth.vk.com/authorize"
|
||||
+ "?client_id={APP_ID}"
|
||||
+ "&scope={PERMISSIONS}"
|
||||
+ "&redirect_uri={REDIRECT_URI}"
|
||||
+ "&display={DISPLAY}"
|
||||
+ "&v={API_VERSION}"
|
||||
+ "&response_type=token";
|
||||
|
||||
private static final String API_REQUEST = "https://api.vk.com/method/{METHOD_NAME}"
|
||||
+ "?{PARAMETERS}"
|
||||
+ "&access_token={ACCESS_TOKEN}"
|
||||
+ "&v=" + API_VERSION;
|
||||
|
||||
public static VkApi with(String appId, String accessToken) throws IOException {
|
||||
return new VkApi(appId, accessToken);
|
||||
}
|
||||
|
||||
private final String accessToken;
|
||||
|
||||
private VkApi(String appId, String accessToken) throws IOException {
|
||||
this.accessToken = accessToken;
|
||||
if (accessToken == null || accessToken.isEmpty()) {
|
||||
auth(appId);
|
||||
throw new Error("Need access token");
|
||||
}
|
||||
}
|
||||
|
||||
private void auth(String appId) throws IOException {
|
||||
String reqUrl = AUTH_URL
|
||||
.replace("{APP_ID}", appId)
|
||||
.replace("{PERMISSIONS}", "photos,messages")
|
||||
.replace("{REDIRECT_URI}", "https://oauth.vk.com/blank.html")
|
||||
.replace("{DISPLAY}", "page")
|
||||
.replace("{API_VERSION}", API_VERSION);
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URL(reqUrl).toURI());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDialogs() throws IOException {
|
||||
return invokeApi("messages.getDialogs", null);
|
||||
}
|
||||
|
||||
public String getHistory(String userId, int offset, int count, boolean rev) throws IOException {
|
||||
return invokeApi("messages.getHistory", Params.create()
|
||||
.add("user_id", userId)
|
||||
.add("offset", String.valueOf(offset))
|
||||
.add("count", String.valueOf(count))
|
||||
.add("rev", rev ? "1" : "0"));
|
||||
}
|
||||
|
||||
public String getAlbums(String userId) throws IOException {
|
||||
return invokeApi("photos.getAlbums", Params.create()
|
||||
.add("owner_id", userId)
|
||||
.add("photo_sizes", "1")
|
||||
.add("thumb_src", "1"));
|
||||
}
|
||||
|
||||
private String invokeApi(String method, Params params) throws IOException {
|
||||
final String parameters = (params == null) ? "" : params.build();
|
||||
String reqUrl = API_REQUEST
|
||||
.replace("{METHOD_NAME}", method)
|
||||
.replace("{ACCESS_TOKEN}", accessToken)
|
||||
.replace("{PARAMETERS}&", parameters);
|
||||
return invokeApi(reqUrl);
|
||||
}
|
||||
|
||||
private static String invokeApi(String requestUrl) throws IOException {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
final URL url = new URL(requestUrl);
|
||||
try (InputStream is = url.openStream()) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
reader.lines().forEach(result::append);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static class Params {
|
||||
|
||||
public static Params create() {
|
||||
return new Params();
|
||||
}
|
||||
|
||||
private final HashMap<String, String> params;
|
||||
|
||||
private Params() {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
|
||||
public Params add(String key, String value) {
|
||||
params.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String build() {
|
||||
if (params.isEmpty()) return "";
|
||||
final StringBuilder result = new StringBuilder();
|
||||
params.keySet().stream().forEach(key -> {
|
||||
result.append(key).append('=').append(params.get(key)).append('&');
|
||||
});
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
52
src/com/annimon/vkdialogsaver/VkDialog.java
Normal file
52
src/com/annimon/vkdialogsaver/VkDialog.java
Normal file
@ -0,0 +1,52 @@
|
||||
package com.annimon.vkdialogsaver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* Бекап сообщений Вконтакте.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class VkDialog {
|
||||
|
||||
private static Config config;
|
||||
|
||||
public static void setConfig(Config config) {
|
||||
VkDialog.config = config;
|
||||
}
|
||||
|
||||
public static void save(String userId, int from, int to) throws IOException {
|
||||
VkApi vkApi = VkApi.with(config.getAppId(), config.getAccessToken());
|
||||
|
||||
final int count = 200;
|
||||
int offset = from;
|
||||
while (offset < to) {
|
||||
System.out.println(offset);
|
||||
String text;
|
||||
while (true) {
|
||||
text = vkApi.getHistory(userId, offset, count, true);
|
||||
if (!text.contains("Too many requests per second")) break;
|
||||
System.out.println("Wait 1 second");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
write(offset, text);
|
||||
offset += count;
|
||||
}
|
||||
}
|
||||
|
||||
private static void write(int offset, String text) throws IOException {
|
||||
File file = new File(config.getWorkDir() + offset + ".txt");
|
||||
try (OutputStream os = new FileOutputStream(file)) {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
|
||||
writer.write(text);
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
}
|
42
src/com/vk/sdk/api/model/Identifiable.java
Normal file
42
src/com/vk/sdk/api/model/Identifiable.java
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* identifiable.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 06.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
/**
|
||||
* Describes objects that contains an "id" field.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Identifiable {
|
||||
|
||||
/**
|
||||
* Returns unique identifier of this object(usually it's value of JSON field "id").
|
||||
*/
|
||||
int getId();
|
||||
|
||||
}
|
251
src/com/vk/sdk/api/model/ParseUtils.java
Normal file
251
src/com/vk/sdk/api/model/ParseUtils.java
Normal file
@ -0,0 +1,251 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* Collection of helpers to parse server responses.
|
||||
*/
|
||||
class ParseUtils {
|
||||
|
||||
private ParseUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse boolean from server response.
|
||||
*
|
||||
* @param from server response like this format: {@code response: 1}
|
||||
* @throws JSONException if server response is not valid
|
||||
*/
|
||||
public static boolean parseBoolean(String from) throws JSONException {
|
||||
return new JSONObject(from).optInt("response", 0) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse boolean from JSONObject with given name.
|
||||
*
|
||||
* @param from server response like this format: {@code field: 1}
|
||||
* @param name name of field to read
|
||||
*/
|
||||
public static boolean parseBoolean(JSONObject from, String name) {
|
||||
return from != null && from.optInt(name, 0) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse int from JSONObject with given name.
|
||||
*
|
||||
* @param from server response like this format: {@code field: 34}
|
||||
* @param name name of field to read
|
||||
*/
|
||||
public static int parseInt(JSONObject from, String name) {
|
||||
if (from == null) return 0;
|
||||
return from.optInt(name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse int from server response.
|
||||
*
|
||||
* @param from server response like this format: {@code response: 34}
|
||||
* @throws JSONException if server response is not valid
|
||||
*/
|
||||
public static int parseInt(String from) throws JSONException {
|
||||
if (from == null) return 0;
|
||||
return new JSONObject(from).optInt("response");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse long from JSONObject with given name.
|
||||
*
|
||||
* @param from server response like this format: {@code field: 34}
|
||||
* @param name name of field to read
|
||||
*/
|
||||
public static long parseLong(JSONObject from, String name) {
|
||||
if (from == null) return 0;
|
||||
return from.optLong(name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse int array from JSONObject with given name.
|
||||
*
|
||||
* @param from int JSON array like this one {@code {11, 34, 42}}
|
||||
*/
|
||||
public static int[] parseIntArray(JSONArray from) {
|
||||
int[] result = new int[from.length()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = from.optInt(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns root JSONObject from server response
|
||||
*
|
||||
* @param source standart VK server response
|
||||
* @throws JSONException if source is not valid
|
||||
*/
|
||||
public static JSONObject rootJSONObject(String source) throws JSONException {
|
||||
return new JSONObject(source).getJSONObject("response");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns root JSONArray from server response
|
||||
*
|
||||
* @param source standart VK server response
|
||||
* @throws JSONException if source is not valid
|
||||
*/
|
||||
public static JSONArray rootJSONArray(String source) throws JSONException {
|
||||
return new JSONObject(source).getJSONArray("response");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses object with follow rules:
|
||||
*
|
||||
* 1. All fields should had a public access.
|
||||
* 2. The name of the filed should be fully equal to name of JSONObject key.
|
||||
* 3. Supports parse of all Java primitives, all {@link java.lang.String},
|
||||
* arrays of primitive types, {@link java.lang.String}s and {@link com.vk.sdk.api.model.VKApiModel}s,
|
||||
* list implementation line {@link com.vk.sdk.api.model.VKList}, {@link com.vk.sdk.api.model.VKAttachments.VKAttachment} or {@link com.vk.sdk.api.model.VKPhotoSizes},
|
||||
* {@link com.vk.sdk.api.model.VKApiModel}s.
|
||||
*
|
||||
* 4. Boolean fields defines by vk_int == 1 expression.
|
||||
*
|
||||
* @param object object to initialize
|
||||
* @param source data to read values
|
||||
* @param <T> type of result
|
||||
* @return initialized according with given data object
|
||||
* @throws JSONException if source object structure is invalid
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static <T> T parseViaReflection(T object, JSONObject source) throws JSONException {
|
||||
if (source.has("response")) {
|
||||
source = source.optJSONObject("response");
|
||||
}
|
||||
if (source == null) {
|
||||
return object;
|
||||
}
|
||||
for (Field field : object.getClass().getFields()) {
|
||||
field.setAccessible(true);
|
||||
String fieldName = field.getName();
|
||||
Class<?> fieldType = field.getType();
|
||||
|
||||
Object value = source.opt(fieldName);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (fieldType.isPrimitive() && value instanceof Number) {
|
||||
Number number = (Number) value;
|
||||
if (fieldType.equals(int.class)) {
|
||||
field.setInt(object, number.intValue());
|
||||
} else if (fieldType.equals(long.class)) {
|
||||
field.setLong(object, number.longValue());
|
||||
} else if (fieldType.equals(float.class)) {
|
||||
field.setFloat(object, number.floatValue());
|
||||
} else if (fieldType.equals(double.class)) {
|
||||
field.setDouble(object, number.doubleValue());
|
||||
} else if (fieldType.equals(boolean.class)) {
|
||||
field.setBoolean(object, number.intValue() == 1);
|
||||
} else if (fieldType.equals(short.class)) {
|
||||
field.setShort(object, number.shortValue());
|
||||
} else if (fieldType.equals(byte.class)) {
|
||||
field.setByte(object, number.byteValue());
|
||||
}
|
||||
} else {
|
||||
Object result = field.get(object);
|
||||
if (value.getClass().equals(fieldType)) {
|
||||
result = value;
|
||||
} else if (fieldType.isArray() && value instanceof JSONArray) {
|
||||
result = parseArrayViaReflection((JSONArray) value, fieldType);
|
||||
} else if(VKPhotoSizes.class.isAssignableFrom(fieldType) && value instanceof JSONArray) {
|
||||
Constructor<?> constructor = fieldType.getConstructor(JSONArray.class);
|
||||
result = constructor.newInstance((JSONArray) value);
|
||||
} else if(VKAttachments.class.isAssignableFrom(fieldType) && value instanceof JSONArray) {
|
||||
Constructor<?> constructor = fieldType.getConstructor(JSONArray.class);
|
||||
result = constructor.newInstance((JSONArray) value);
|
||||
} else if(VKList.class.equals(fieldType)) {
|
||||
ParameterizedType genericTypes = (ParameterizedType) field.getGenericType();
|
||||
Class<?> genericType = (Class<?>) genericTypes.getActualTypeArguments()[0];
|
||||
if(VKApiModel.class.isAssignableFrom(genericType) && Identifiable.class.isAssignableFrom(genericType)) {
|
||||
if(value instanceof JSONArray) {
|
||||
result = new VKList((JSONArray) value, genericType);
|
||||
} else if(value instanceof JSONObject) {
|
||||
result = new VKList((JSONObject) value, genericType);
|
||||
}
|
||||
}
|
||||
} else if (VKApiModel.class.isAssignableFrom(fieldType) && value instanceof JSONObject) {
|
||||
result = ((VKApiModel) fieldType.newInstance()).parse((JSONObject) value);
|
||||
}
|
||||
field.set(object, result);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (NoSuchMethodError e) {
|
||||
// Примечание Виталия:
|
||||
// Вы не поверите, но у некоторых вендоров getFields() вызывает ВОТ ЭТО.
|
||||
// Иногда я всерьез задумываюсь, правильно ли я поступил, выбрав Android в качестве платформы разработки.
|
||||
throw new JSONException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses array from given JSONArray.
|
||||
* Supports parsing of primitive types and {@link com.vk.sdk.api.model.VKApiModel} instances.
|
||||
* @param array JSONArray to parse
|
||||
* @param arrayClass type of array field in class.
|
||||
* @return object to set to array field in class
|
||||
* @throws JSONException if given array have incompatible type with given field.
|
||||
*/
|
||||
private static Object parseArrayViaReflection(JSONArray array, Class arrayClass) throws JSONException {
|
||||
Object result = Array.newInstance(arrayClass.getComponentType(), array.length());
|
||||
Class<?> subType = arrayClass.getComponentType();
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
try {
|
||||
Object item = array.opt(i);
|
||||
if(VKApiModel.class.isAssignableFrom(subType) && item instanceof JSONObject) {
|
||||
VKApiModel model = (VKApiModel) subType.newInstance();
|
||||
item = model.parse((JSONObject) item);
|
||||
}
|
||||
Array.set(result, i, item);
|
||||
} catch (InstantiationException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new JSONException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
26
src/com/vk/sdk/api/model/TextUtils.java
Normal file
26
src/com/vk/sdk/api/model/TextUtils.java
Normal file
@ -0,0 +1,26 @@
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
class TextUtils {
|
||||
|
||||
static boolean isEmpty(CharSequence text) {
|
||||
return (text == null) || (text.length() == 0);
|
||||
}
|
||||
|
||||
static String formatDuration(int duration) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int hours = (duration / 3600);
|
||||
if (hours != 0) sb.append(formatNumber(hours)).append(':');
|
||||
final int minutes = duration % 3600 / 60;
|
||||
final int seconds = duration % 60;
|
||||
sb.append(formatNumber(minutes)).append(':').append(formatNumber(seconds));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String formatNumber(int number) {
|
||||
return String.format("%02d", number);
|
||||
}
|
||||
}
|
82
src/com/vk/sdk/api/model/VKApiApplicationContent.java
Normal file
82
src/com/vk/sdk/api/model/VKApiApplicationContent.java
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* AppInfo.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* Describes information about application in the post.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiApplicationContent extends VKApiAttachment {
|
||||
|
||||
/**
|
||||
* ID of the application that posted on the wall;
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Application name
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Image URL for preview with maximum width in 130px
|
||||
*/
|
||||
public String photo_130;
|
||||
|
||||
/**
|
||||
* Image URL for preview with maximum width in 130px
|
||||
*/
|
||||
public String photo_604;
|
||||
|
||||
/**
|
||||
* Image URL for preview;
|
||||
*/
|
||||
public VKPhotoSizes photo = new VKPhotoSizes();
|
||||
|
||||
/**
|
||||
* Fills an ApplicationContent instance from JSONObject.
|
||||
*/
|
||||
public VKApiApplicationContent parse(JSONObject source) {
|
||||
id = source.optInt("id");
|
||||
name = source.optString("name");
|
||||
photo_130 = source.optString("photo_130");
|
||||
if(!TextUtils.isEmpty(photo_130)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_130, 130));
|
||||
}
|
||||
photo_604 = source.optString("photo_604");
|
||||
if(!TextUtils.isEmpty(photo_604)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_604, 604));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty ApplicationContent instance.
|
||||
*/
|
||||
public VKApiApplicationContent() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
throw new UnsupportedOperationException("Attaching app info is not supported by VK.com API");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_APP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
85
src/com/vk/sdk/api/model/VKApiArray.java
Normal file
85
src/com/vk/sdk/api/model/VKApiArray.java
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base class for VK API arrays
|
||||
*/
|
||||
public abstract class VKApiArray<T extends VKApiModel> extends VKApiModel {
|
||||
private List<T> items;
|
||||
private int count;
|
||||
|
||||
@Override
|
||||
public VKApiModel parse(JSONObject object) {
|
||||
try {
|
||||
JSONArray jsonArray;
|
||||
if ((jsonArray = object.optJSONArray("response")) == null)
|
||||
{
|
||||
object = object.getJSONObject("response");
|
||||
count = object.getInt("count");
|
||||
jsonArray = object.getJSONArray("items");
|
||||
}
|
||||
parse(jsonArray);
|
||||
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
fields = object;
|
||||
return this;
|
||||
}
|
||||
public void parse(JSONArray jsonArray) {
|
||||
items = new ArrayList<T>(jsonArray.length());
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
try {
|
||||
items.add(parseNextObject(jsonArray.getJSONObject(i)));
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
}
|
||||
if (count == 0)
|
||||
count = items.size();
|
||||
}
|
||||
|
||||
protected T parseNextObject(JSONObject object) {
|
||||
try {
|
||||
T model = createObject();
|
||||
model.parse(object);
|
||||
return model;
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
protected abstract T createObject();
|
||||
|
||||
public T get(int index) {
|
||||
if (items == null) return null;
|
||||
return items.get(index);
|
||||
}
|
||||
|
||||
public int size() { return count; }
|
||||
}
|
170
src/com/vk/sdk/api/model/VKApiAudio.java
Normal file
170
src/com/vk/sdk/api/model/VKApiAudio.java
Normal file
@ -0,0 +1,170 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Audio.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* An audio object describes an audio file and contains the following fields.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiAudio extends VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Audio ID.
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Audio owner ID.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Artist name.
|
||||
*/
|
||||
public String artist;
|
||||
|
||||
/**
|
||||
* Audio file title.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Duration (in seconds).
|
||||
*/
|
||||
public int duration;
|
||||
|
||||
/**
|
||||
* Link to mp3.
|
||||
*/
|
||||
public String url;
|
||||
|
||||
/**
|
||||
* ID of the lyrics (if available) of the audio file.
|
||||
*/
|
||||
public int lyrics_id;
|
||||
|
||||
/**
|
||||
* ID of the album containing the audio file (if assigned).
|
||||
*/
|
||||
public int album_id;
|
||||
|
||||
/**
|
||||
* Genre ID. See the list of audio genres.
|
||||
*/
|
||||
public int genre;
|
||||
|
||||
/**
|
||||
* An access key using for get information about hidden objects.
|
||||
*/
|
||||
public String access_key;
|
||||
|
||||
/**
|
||||
* Fills an Audio instance from JSONObject.
|
||||
*/
|
||||
public VKApiAudio parse(JSONObject from) {
|
||||
id = from.optInt("id");
|
||||
owner_id = from.optInt("owner_id");
|
||||
artist = from.optString("artist");
|
||||
title = from.optString("title");
|
||||
duration = from.optInt("duration");
|
||||
url = from.optString("url");
|
||||
lyrics_id = from.optInt("lyrics_id");
|
||||
album_id = from.optInt("album_id");
|
||||
genre = from.optInt("genre_id");
|
||||
access_key = from.optString("access_key");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Audio instance.
|
||||
*/
|
||||
public VKApiAudio() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
StringBuilder result = new StringBuilder(TYPE_AUDIO).append(owner_id).append('_').append(id);
|
||||
if(!TextUtils.isEmpty(access_key)) {
|
||||
result.append('_');
|
||||
result.append(access_key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
String d = TextUtils.formatDuration(duration);
|
||||
return String.format("<div class='play_new'></div><div class='audio'>%s - %s (%s)</div><br/>", artist, title, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_AUDIO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio object genres.
|
||||
*/
|
||||
public final static class Genre {
|
||||
|
||||
private Genre() {}
|
||||
|
||||
public final static int ROCK = 1;
|
||||
public final static int POP = 2;
|
||||
public final static int RAP_AND_HIPHOP = 3;
|
||||
public final static int EASY_LISTENING = 4;
|
||||
public final static int DANCE_AND_HOUSE = 5;
|
||||
public final static int INSTRUMENTAL = 6;
|
||||
public final static int METAL = 7;
|
||||
public final static int DUBSTEP = 8;
|
||||
public final static int JAZZ_AND_BLUES = 9;
|
||||
public final static int DRUM_AND_BASS = 10;
|
||||
public final static int TRANCE = 11;
|
||||
public final static int CHANSON = 12;
|
||||
public final static int ETHNIC = 13;
|
||||
public final static int ACOUSTIC_AND_VOCAL = 14;
|
||||
public final static int REGGAE = 15;
|
||||
public final static int CLASSICAL = 16;
|
||||
public final static int INDIE_POP = 17;
|
||||
public final static int OTHER = 18;
|
||||
public final static int SPEECH = 19;
|
||||
public final static int ALTERNATIVE = 21;
|
||||
public final static int ELECTROPOP_AND_DISCO = 22;
|
||||
}
|
||||
|
||||
}
|
165
src/com/vk/sdk/api/model/VKApiDocument.java
Normal file
165
src/com/vk/sdk/api/model/VKApiDocument.java
Normal file
@ -0,0 +1,165 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* A document object describes a document file.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiDocument extends VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Document ID.
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* ID of the user or group who uploaded the document.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Document title.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Document size (in bytes).
|
||||
*/
|
||||
public long size;
|
||||
|
||||
/**
|
||||
* Document extension.
|
||||
*/
|
||||
public String ext;
|
||||
|
||||
/**
|
||||
* Document URL for downloading.
|
||||
*/
|
||||
public String url;
|
||||
|
||||
/**
|
||||
* URL of the 100x75px image (if the file is graphical).
|
||||
*/
|
||||
public String photo_100;
|
||||
|
||||
/**
|
||||
* URL of the 130x100px image (if the file is graphical).
|
||||
*/
|
||||
public String photo_130;
|
||||
|
||||
/**
|
||||
* Array of all photos.
|
||||
*/
|
||||
public VKPhotoSizes photo = new VKPhotoSizes();
|
||||
|
||||
/**
|
||||
* An access key using for get information about hidden objects.
|
||||
*/
|
||||
public String access_key;
|
||||
|
||||
private boolean mIsGif;
|
||||
private boolean mIsImage;
|
||||
|
||||
/**
|
||||
* Fills a Doc instance from JSONObject.
|
||||
*/
|
||||
public VKApiDocument parse(JSONObject jo) {
|
||||
id = jo.optInt("id");
|
||||
owner_id = jo.optInt("owner_id");
|
||||
title = jo.optString("title");
|
||||
size = jo.optLong("size");
|
||||
ext = jo.optString("ext");
|
||||
url = jo.optString("url");
|
||||
access_key = jo.optString("access_key");
|
||||
|
||||
photo_100 = jo.optString("photo_100");
|
||||
if(!TextUtils.isEmpty(photo_100)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_100, 100, 75));
|
||||
}
|
||||
photo_130 = jo.optString("photo_130");
|
||||
if(!TextUtils.isEmpty(photo_130)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_130, 130, 100));
|
||||
}
|
||||
photo.sort();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Doc instance.
|
||||
*/
|
||||
public VKApiDocument() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isImage() {
|
||||
mIsImage = mIsImage ||
|
||||
"jpg".equals(ext) ||
|
||||
"jpeg".equals(ext) ||
|
||||
"png".equals(ext) ||
|
||||
"bmp".equals(ext);
|
||||
return mIsImage;
|
||||
}
|
||||
|
||||
public boolean isGif() {
|
||||
mIsGif = mIsGif || "gif".equals(ext);
|
||||
return mIsGif;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
StringBuilder result = new StringBuilder(TYPE_DOC).append(owner_id).append('_').append(id);
|
||||
if(!TextUtils.isEmpty(access_key)) {
|
||||
result.append('_');
|
||||
result.append(access_key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
if (isGif() || isImage()) {
|
||||
String preview = photo.get(photo.size() - 1).src;
|
||||
return String.format("<a href='%s'><img src='%s'/></a>", url, preview);
|
||||
} else {
|
||||
return String.format("<a href='%s'>%s</a>", url, title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_DOC;
|
||||
}
|
||||
}
|
113
src/com/vk/sdk/api/model/VKApiLink.java
Normal file
113
src/com/vk/sdk/api/model/VKApiLink.java
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Link.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* A link object describes a link attachment
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiLink extends VKAttachments.VKApiAttachment {
|
||||
|
||||
/**
|
||||
* Link URL
|
||||
*/
|
||||
public String url;
|
||||
|
||||
/**
|
||||
* Link title
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Link description;
|
||||
*/
|
||||
public String description;
|
||||
|
||||
/**
|
||||
* Image preview URL for the link (if any).
|
||||
*/
|
||||
public String image_src;
|
||||
|
||||
/**
|
||||
* ID wiki page with content for the preview of the page contents
|
||||
* ID is returned as "ownerid_pageid".
|
||||
*/
|
||||
public String preview_page;
|
||||
|
||||
/**
|
||||
* Creates link attachment to attach it to the post
|
||||
* @param url full URL of link
|
||||
*/
|
||||
public VKApiLink(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills a Link instance from JSONObject.
|
||||
*/
|
||||
public VKApiLink parse(JSONObject source) {
|
||||
url = source.optString("url");
|
||||
title = source.optString("title");
|
||||
description = source.optString("description");
|
||||
image_src = source.optString("image_src");
|
||||
preview_page = source.optString("preview_page");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Link instance.
|
||||
*/
|
||||
public VKApiLink() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
String preview = (TextUtils.isEmpty(image_src)) ? String.format("<br/><img src='%s'/>", image_src) : "";
|
||||
return String.format("<a href='%s'>%s %s</a>", url, title, preview);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_LINK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0;
|
||||
}
|
||||
}
|
124
src/com/vk/sdk/api/model/VKApiMessage.java
Normal file
124
src/com/vk/sdk/api/model/VKApiMessage.java
Normal file
@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Message.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* A message object describes a private message
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiMessage extends VKApiModel implements Identifiable {
|
||||
|
||||
/**
|
||||
* Message ID. (Not returned for forwarded messages), positive number
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* For an incoming message, the user ID of the author. For an outgoing message, the user ID of the receiver.
|
||||
*/
|
||||
public int user_id;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) when the message was sent.
|
||||
*/
|
||||
public long date;
|
||||
|
||||
/**
|
||||
* Message status (false — not read, true — read). (Not returned for forwarded messages.)
|
||||
*/
|
||||
public boolean read_state;
|
||||
|
||||
/**
|
||||
* Message type (false — received, true — sent). (Not returned for forwarded messages.)
|
||||
*/
|
||||
public boolean out;
|
||||
|
||||
/**
|
||||
* Title of message or chat.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Body of the message.
|
||||
*/
|
||||
public String body;
|
||||
|
||||
/**
|
||||
* List of media-attachments;
|
||||
*/
|
||||
public VKAttachments attachments = new VKAttachments();
|
||||
|
||||
/**
|
||||
* Array of forwarded messages (if any).
|
||||
*/
|
||||
public VKList<VKApiMessage> fwd_messages;
|
||||
|
||||
/**
|
||||
* Whether the message contains smiles (false — no, true — yes).
|
||||
*/
|
||||
public boolean emoji;
|
||||
|
||||
/**
|
||||
* Whether the message is deleted (false — no, true — yes).
|
||||
*/
|
||||
public boolean deleted;
|
||||
|
||||
/**
|
||||
* Fills a Message instance from JSONObject.
|
||||
*/
|
||||
public VKApiMessage parse(JSONObject source) throws JSONException {
|
||||
id = source.optInt("id");
|
||||
user_id = source.optInt("user_id");
|
||||
date = source.optLong("date");
|
||||
read_state = ParseUtils.parseBoolean(source, "read_state");
|
||||
out = ParseUtils.parseBoolean(source, "out");
|
||||
title = source.optString("title");
|
||||
body = source.optString("body");
|
||||
attachments .fill(source.optJSONArray("attachments"));
|
||||
fwd_messages = new VKList<VKApiMessage>(source.optJSONArray("fwd_messages"), VKApiMessage.class);
|
||||
emoji = ParseUtils.parseBoolean(source, "emoji");
|
||||
deleted = ParseUtils.parseBoolean(source, "deleted");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Country instance.
|
||||
*/
|
||||
public VKApiMessage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
85
src/com/vk/sdk/api/model/VKApiModel.java
Normal file
85
src/com/vk/sdk/api/model/VKApiModel.java
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* BaseModel.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 06.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Root class for all VK models.
|
||||
* Any VK model supports Parcelable interface so you can pass it as extra.
|
||||
*
|
||||
* VK model is also allows you to store some object inside as a tag.
|
||||
* These objects are retained by hard links,
|
||||
* and never will be saved during parcelization.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class VKApiModel {
|
||||
|
||||
public JSONObject fields;
|
||||
/**
|
||||
* The model's tag.
|
||||
*/
|
||||
private Object mTag;
|
||||
|
||||
/**
|
||||
* Returns this model's tag.
|
||||
*
|
||||
* @return the Object stored in this model as a tag
|
||||
*
|
||||
* @see #setTag(Object)
|
||||
* @see #getTag(int)
|
||||
*/
|
||||
public Object getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag associated with this model. A tag can be used to store
|
||||
* data within a model without resorting to another data structure.
|
||||
*
|
||||
* @param tag an Object to tag the model with
|
||||
*
|
||||
* @see #getTag()
|
||||
* @see #setTag(int, Object)
|
||||
*/
|
||||
public void setTag(Object tag) {
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses object from source.
|
||||
* @param response server API object.
|
||||
* @return this object.
|
||||
* @throws JSONException if any critical error occurred while parsing.
|
||||
*/
|
||||
public VKApiModel parse(JSONObject response) throws JSONException {
|
||||
return ParseUtils.parseViaReflection(this, response);
|
||||
}
|
||||
}
|
110
src/com/vk/sdk/api/model/VKApiNote.java
Normal file
110
src/com/vk/sdk/api/model/VKApiNote.java
Normal file
@ -0,0 +1,110 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Note.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* A note object describes a note.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiNote extends VKAttachments.VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Note ID, positive number
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Note owner ID.
|
||||
*/
|
||||
public int user_id;
|
||||
|
||||
/**
|
||||
* Note title.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Note text.
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) when the note was created.
|
||||
*/
|
||||
public long date;
|
||||
|
||||
/**
|
||||
* Number of comments.
|
||||
*/
|
||||
public int comments;
|
||||
|
||||
/**
|
||||
* Number of read comments (only if owner_id is the current user).
|
||||
*/
|
||||
public int read_comments;
|
||||
|
||||
/**
|
||||
* Fills a Note instance from JSONObject.
|
||||
*/
|
||||
public VKApiNote parse(JSONObject source) {
|
||||
id = source.optInt("id");
|
||||
user_id = source.optInt("user_id");
|
||||
title = source.optString("title");
|
||||
text = source.optString("text");
|
||||
date = source.optLong("date");
|
||||
comments = source.optInt("comments");
|
||||
read_comments = source.optInt("read_comments");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Note instance.
|
||||
*/
|
||||
public VKApiNote() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
return new StringBuilder(TYPE_NOTE).append(user_id).append('_').append(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_NOTE;
|
||||
}
|
||||
}
|
227
src/com/vk/sdk/api/model/VKApiPhoto.java
Normal file
227
src/com/vk/sdk/api/model/VKApiPhoto.java
Normal file
@ -0,0 +1,227 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import static com.vk.sdk.api.model.ParseUtils.parseBoolean;
|
||||
import static com.vk.sdk.api.model.ParseUtils.parseInt;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* Describes a photo object from VK.
|
||||
*/
|
||||
public class VKApiPhoto extends VKAttachments.VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Photo ID, positive number
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Photo album ID.
|
||||
*/
|
||||
public int album_id;
|
||||
|
||||
/**
|
||||
* ID of the user or community that owns the photo.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Width (in pixels) of the original photo.
|
||||
*/
|
||||
public int width;
|
||||
|
||||
/**
|
||||
* Height (in pixels) of the original photo.
|
||||
*/
|
||||
public int height;
|
||||
|
||||
/**
|
||||
* Text describing the photo.
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) the photo was added.
|
||||
*/
|
||||
public long date;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 75x75px.
|
||||
*/
|
||||
public String photo_75;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 130x130px.
|
||||
*/
|
||||
public String photo_130;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 604x604px.
|
||||
*/
|
||||
public String photo_604;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 807x807px.
|
||||
*/
|
||||
public String photo_807;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 1280x1024px.
|
||||
*/
|
||||
public String photo_1280;
|
||||
|
||||
/**
|
||||
* URL of image with maximum size 2560x2048px.
|
||||
*/
|
||||
public String photo_2560;
|
||||
|
||||
/**
|
||||
* All photo thumbs in photo sizes.
|
||||
* It has data even if server returned them without {@code PhotoSizes} format.
|
||||
*/
|
||||
public VKPhotoSizes src = new VKPhotoSizes();
|
||||
|
||||
/**
|
||||
* Information whether the current user liked the photo.
|
||||
*/
|
||||
public boolean user_likes;
|
||||
|
||||
/**
|
||||
* Whether the current user can comment on the photo
|
||||
*/
|
||||
public boolean can_comment;
|
||||
|
||||
/**
|
||||
* Number of likes on the photo.
|
||||
*/
|
||||
public int likes;
|
||||
|
||||
/**
|
||||
* Number of comments on the photo.
|
||||
*/
|
||||
public int comments;
|
||||
|
||||
/**
|
||||
* Number of tags on the photo.
|
||||
*/
|
||||
public int tags;
|
||||
|
||||
/**
|
||||
* An access key using for get information about hidden objects.
|
||||
*/
|
||||
public String access_key;
|
||||
|
||||
/**
|
||||
* Fills a Photo instance from JSONObject.
|
||||
*/
|
||||
public VKApiPhoto parse(JSONObject from) {
|
||||
album_id = from.optInt("album_id");
|
||||
date = from.optLong("date");
|
||||
height = from.optInt("height");
|
||||
width = from.optInt("width");
|
||||
owner_id = from.optInt("owner_id");
|
||||
id = from.optInt("id");
|
||||
text = from.optString("text");
|
||||
access_key = from.optString("access_key");
|
||||
|
||||
photo_75 = from.optString("photo_75");
|
||||
photo_130 = from.optString("photo_130");
|
||||
photo_604 = from.optString("photo_604");
|
||||
photo_807 = from.optString("photo_807");
|
||||
photo_1280 = from.optString("photo_1280");
|
||||
photo_2560 = from.optString("photo_2560");
|
||||
|
||||
JSONObject likes = from.optJSONObject("likes");
|
||||
this.likes = ParseUtils.parseInt(likes, "count");
|
||||
this.user_likes = ParseUtils.parseBoolean(likes, "user_likes");
|
||||
comments = parseInt(from.optJSONObject("comments"), "count");
|
||||
tags = parseInt(from.optJSONObject("tags"), "count");
|
||||
can_comment = parseBoolean(from, "can_comment");
|
||||
|
||||
src.setOriginalDimension(width, height);
|
||||
JSONArray photo_sizes = from.optJSONArray("sizes");
|
||||
if(photo_sizes != null) {
|
||||
src.fill(photo_sizes);
|
||||
} else {
|
||||
if(!TextUtils.isEmpty(photo_75)) {
|
||||
src.add(VKApiPhotoSize.create(photo_75, VKApiPhotoSize.S, width, height));
|
||||
}
|
||||
if(!TextUtils.isEmpty(photo_130)) {
|
||||
src.add(VKApiPhotoSize.create(photo_130, VKApiPhotoSize.M, width, height));
|
||||
}
|
||||
if(!TextUtils.isEmpty(photo_604)) {
|
||||
src.add(VKApiPhotoSize.create(photo_604, VKApiPhotoSize.X, width, height));
|
||||
}
|
||||
if(!TextUtils.isEmpty(photo_807)) {
|
||||
src.add(VKApiPhotoSize.create(photo_807, VKApiPhotoSize.Y, width, height));
|
||||
}
|
||||
if(!TextUtils.isEmpty(photo_1280)) {
|
||||
src.add(VKApiPhotoSize.create(photo_1280, VKApiPhotoSize.Z, width, height));
|
||||
}
|
||||
if(!TextUtils.isEmpty(photo_2560)) {
|
||||
src.add(VKApiPhotoSize.create(photo_2560, VKApiPhotoSize.W, width, height));
|
||||
}
|
||||
src.sort();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Photo instance.
|
||||
*/
|
||||
public VKApiPhoto() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
StringBuilder result = new StringBuilder(TYPE_PHOTO).append(owner_id).append('_').append(id);
|
||||
if(!TextUtils.isEmpty(access_key)) {
|
||||
result.append('_');
|
||||
result.append(access_key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
final int size = src.size();
|
||||
VKApiPhotoSize small = src.get(0);
|
||||
if (size > 1) small = src.get(1);
|
||||
VKApiPhotoSize big = src.get(size - 1);
|
||||
return String.format("<a href='%s'><img src='%s'/></a>", big.src, small.src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_PHOTO;
|
||||
}
|
||||
}
|
170
src/com/vk/sdk/api/model/VKApiPhotoAlbum.java
Normal file
170
src/com/vk/sdk/api/model/VKApiPhotoAlbum.java
Normal file
@ -0,0 +1,170 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* Describes a photo album
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiPhotoAlbum extends VKAttachments.VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* URL for empty album cover with max width at 75px
|
||||
*/
|
||||
public final static String COVER_S = "http://vk.com/images/s_noalbum.png";
|
||||
|
||||
/**
|
||||
* URL of empty album cover with max width at 130px
|
||||
*/
|
||||
public final static String COVER_M = "http://vk.com/images/m_noalbum.png";
|
||||
|
||||
/**
|
||||
* URL of empty album cover with max width at 604px
|
||||
*/
|
||||
public final static String COVER_X = "http://vk.com/images/x_noalbum.png";
|
||||
|
||||
/**
|
||||
* Album ID.
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Album title.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Number of photos in the album.
|
||||
*/
|
||||
public int size;
|
||||
|
||||
/**
|
||||
* Privacy settings for the album.
|
||||
*/
|
||||
public int privacy;
|
||||
|
||||
/**
|
||||
* Album description.
|
||||
*/
|
||||
public String description;
|
||||
|
||||
/**
|
||||
* ID of the user or community that owns the album.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Whether a user can upload photos to this album(false — cannot, true — can).
|
||||
*/
|
||||
public boolean can_upload;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) the album was last updated.
|
||||
*/
|
||||
public long updated;
|
||||
|
||||
/**
|
||||
* Album creation date (in Unix time).
|
||||
*/
|
||||
public long created;
|
||||
|
||||
/**
|
||||
* ID of the photo which is the cover.
|
||||
*/
|
||||
public int thumb_id;
|
||||
|
||||
/**
|
||||
* Link to album cover photo.
|
||||
*/
|
||||
public String thumb_src;
|
||||
|
||||
/**
|
||||
* Links to to cover photo.
|
||||
*/
|
||||
public VKPhotoSizes photo = new VKPhotoSizes();
|
||||
|
||||
/**
|
||||
* Creates a PhotoAlbum instance from JSONObject.
|
||||
*/
|
||||
public VKApiPhotoAlbum parse(JSONObject from) {
|
||||
id = from.optInt("id");
|
||||
thumb_id = from.optInt("thumb_id");
|
||||
owner_id = from.optInt("owner_id");
|
||||
title = from.optString("title");
|
||||
description = from.optString("description");
|
||||
created = from.optLong("created");
|
||||
updated = from.optLong("updated");
|
||||
size = from.optInt("size");
|
||||
can_upload = ParseUtils.parseBoolean(from, "can_upload");
|
||||
thumb_src = from.optString("thumb_src");
|
||||
if(from.has("privacy")) {
|
||||
privacy = from.optInt("privacy");
|
||||
} else {
|
||||
privacy = VKPrivacy.parsePrivacy(from.optJSONObject("privacy_view"));
|
||||
}
|
||||
JSONArray sizes = from.optJSONArray("sizes");
|
||||
if(sizes != null) {
|
||||
photo.fill(sizes);
|
||||
} else {
|
||||
photo.add(VKApiPhotoSize.create(COVER_S, 75, 55));
|
||||
photo.add(VKApiPhotoSize.create(COVER_M, 130, 97));
|
||||
photo.add(VKApiPhotoSize.create(COVER_X, 432, 249));
|
||||
photo.sort();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty PhotoAlbum instance.
|
||||
*/
|
||||
public VKApiPhotoAlbum() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return privacy != VKPrivacy.PRIVACY_ALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
return new StringBuilder(TYPE_ALBUM).append(owner_id).append('_').append(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_ALBUM;
|
||||
}
|
||||
}
|
322
src/com/vk/sdk/api/model/VKApiPhotoSize.java
Normal file
322
src/com/vk/sdk/api/model/VKApiPhotoSize.java
Normal file
@ -0,0 +1,322 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* PhotoSize.java
|
||||
* VK Dev
|
||||
*
|
||||
* Created by Babichev Vitaly on 03.10.13.
|
||||
* Copyright (c) 2013 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Describes an photo info in <a href="http://vk.com/dev/photo_sizes">special format<a/>.
|
||||
*
|
||||
* Some methods returns information about copies of the original image in different sizes,
|
||||
* Represented as an array of sizes, containing a description of the objects of this class.
|
||||
*
|
||||
* <b>Sizes value example:</b>
|
||||
*
|
||||
* Original photo — https://pp.vk.me/c323930/v323930021/53fb/1VrEC2eSkZQ.jpg,1280x856px,
|
||||
* "width/height" ratio is 1.495327102803738
|
||||
*
|
||||
* <code>
|
||||
sizes: [{
|
||||
src: http://cs323930.vk.me/v323930021/53f7/OwV0l2YFJ7s.jpg
|
||||
width: 75,
|
||||
height: 50,
|
||||
type: 's'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53f8/qX8MRNyUPqg.jpg,
|
||||
width: 130,
|
||||
height: 87,
|
||||
type: 'm'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53f9/7fBJyr9OHMA.jpg,
|
||||
width: 604,
|
||||
height: 404,
|
||||
type: 'x'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53fa/bskHpsuH6sM.jpg,
|
||||
width: 807,
|
||||
height: 540,
|
||||
type: 'y'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53fb/1VrEC2eSkZQ.jpg,
|
||||
width: 1280,
|
||||
height: 856,
|
||||
type: 'z'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53fc/iAl-TIHfRDY.jpg,
|
||||
width: 130,
|
||||
height: 87,
|
||||
type: 'o'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53fd/qjD0fbHkgmI.jpg,
|
||||
width: 200,
|
||||
height: 134,
|
||||
type: 'p'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53fe/3d2nCvvKQfw.jpg,
|
||||
width: 320,
|
||||
height: 214,
|
||||
type: 'q'
|
||||
}, {
|
||||
src: http://cs323930.vk.me/v323930021/53ff/uK_Nj34SIY8.jpg,
|
||||
width: 510,
|
||||
height: 341,
|
||||
type: 'r'
|
||||
}]
|
||||
* </code>
|
||||
*
|
||||
*/
|
||||
public class VKApiPhotoSize extends VKApiModel implements Comparable<VKApiPhotoSize>, Identifiable {
|
||||
|
||||
/**
|
||||
* Proportional copy with 75px max width
|
||||
*/
|
||||
public final static char S = 's';
|
||||
|
||||
/**
|
||||
* Proportional copy with 130px max width
|
||||
*/
|
||||
public final static char M = 'm';
|
||||
|
||||
/**
|
||||
* Proportional copy with 604px max width
|
||||
*/
|
||||
public final static char X = 'x';
|
||||
|
||||
/**
|
||||
* Proportional copy with 807px max width
|
||||
*/
|
||||
public final static char Y = 'y';
|
||||
|
||||
/**
|
||||
* If original image's "width/height" ratio is less or equal to 3:2, then proportional
|
||||
* copy with 130px max width. If original image's "width/height" ratio is more than 3:2,
|
||||
* then copy of cropped by left side image with 130px max width and 3:2 sides ratio.
|
||||
*/
|
||||
public final static char O = 'o';
|
||||
|
||||
/**
|
||||
* If original image's "width/height" ratio is less or equal to 3:2, then proportional
|
||||
* copy with 200px max width. If original image's "width/height" ratio is more than 3:2,
|
||||
* then copy of cropped by left side image with 200px max width and 3:2 sides ratio.
|
||||
*/
|
||||
public final static char P = 'p';
|
||||
|
||||
/**
|
||||
* If original image's "width/height" ratio is less or equal to 3:2, then proportional
|
||||
* copy with 320px max width. If original image's "width/height" ratio is more than 3:2,
|
||||
* then copy of cropped by left side image with 320px max width and 3:2 sides ratio.
|
||||
*/
|
||||
public final static char Q = 'q';
|
||||
|
||||
/**
|
||||
* Proportional copy with 1280x1024px max size
|
||||
*/
|
||||
public final static char Z = 'z';
|
||||
|
||||
/**
|
||||
* Proportional copy with 2560x2048px max size
|
||||
*/
|
||||
public final static char W = 'w';
|
||||
|
||||
/**
|
||||
* Url of image
|
||||
*/
|
||||
public String src;
|
||||
|
||||
/**
|
||||
* Width of image in pixels
|
||||
*/
|
||||
public int width;
|
||||
|
||||
/**
|
||||
* Height of image in pixels
|
||||
*/
|
||||
public int height;
|
||||
|
||||
/**
|
||||
* Designation of size and proportions copy, @see {{@link #S}, {@link #M}, {@link #X}, {@link #O}, {@link #P}, {@link #Q}, {@link #Y}, {@link #Z}, {@link #W}}
|
||||
*/
|
||||
public char type;
|
||||
|
||||
private VKApiPhotoSize() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(VKApiPhotoSize another) {
|
||||
// Так как основной превалирующий элемент в фотографиях именно ширина и все фотографии пропорциональны,
|
||||
// то сравниваем именно по ней
|
||||
return this.width < another.width ? -1 : (this.width == another.width ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dimension from {@code source}. Used in parsing.
|
||||
* If size is not specified copies calculates them based on internal algorithms.
|
||||
* @param source object in format, returned VK API, which is generated from the dimension
|
||||
* @param originalWidth original image width in pixels
|
||||
* @param originalHeight original image height in pixels
|
||||
*/
|
||||
public static VKApiPhotoSize parse(JSONObject source, int originalWidth, int originalHeight) {
|
||||
VKApiPhotoSize result = new VKApiPhotoSize();
|
||||
result.src = source.optString("src");
|
||||
result.width = source.optInt("width");
|
||||
result.height = source.optInt("height");
|
||||
String type = source.optString("type");
|
||||
if(!TextUtils.isEmpty(type)) {
|
||||
result.type = type.charAt(0);
|
||||
}
|
||||
// Казалось бы, теперь можно с чистой советью закончить метод.
|
||||
// Но нет, оказывается, width и height не просчитывается на некоторых серверах ВК.
|
||||
// Приходится гадать на кофейной гуще.
|
||||
if(result.width == 0 || result.height == 0) {
|
||||
fillDimensions(result, originalWidth, originalHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Устанавливает размерность исходя из размеров оригинала и типа изображения.
|
||||
*/
|
||||
private static void fillDimensions(VKApiPhotoSize result, int originalWidth, int originalHeight) {
|
||||
float ratio = (float) originalWidth / originalHeight;
|
||||
switch (result.type) {
|
||||
case S: {
|
||||
fillDimensionSMXY(result, ratio, Math.min(originalWidth, 75));
|
||||
} break;
|
||||
case M: {
|
||||
fillDimensionSMXY(result, ratio, Math.min(originalWidth, 130));
|
||||
} break;
|
||||
case X: {
|
||||
fillDimensionSMXY(result, ratio, Math.min(originalWidth, 604));
|
||||
} break;
|
||||
case Y: {
|
||||
fillDimensionSMXY(result, ratio, Math.min(originalWidth, 807));
|
||||
} break;
|
||||
case O: {
|
||||
fillDimensionOPQ(result, ratio, Math.min(originalWidth, 130));
|
||||
} break;
|
||||
case P: {
|
||||
fillDimensionOPQ(result, ratio, Math.min(originalWidth, 200));
|
||||
} break;
|
||||
case Q: {
|
||||
fillDimensionOPQ(result, ratio, Math.min(originalWidth, 320));
|
||||
} break;
|
||||
case Z: {
|
||||
fillDimensionZW(result, ratio, Math.min(originalWidth, 1280), Math.min(originalHeight, 1024));
|
||||
} break;
|
||||
case W: {
|
||||
fillDimensionZW(result, ratio, Math.min(originalWidth, 2560), Math.min(originalHeight, 2048));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Про S, M, X, Y известно, про копия обязательно пропорциональна, а ширина не должна превышать заданную.
|
||||
* Это значит, что для всех случаев(кроме тех, когда ширина картинки меньше указанной) соотношения
|
||||
* сторон картинка впишется пропорционально по ширине.
|
||||
*/
|
||||
private static void fillDimensionSMXY(VKApiPhotoSize result, float ratio, int width) {
|
||||
result.width = width;
|
||||
result.height = (int) Math.ceil(result.width / ratio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Пропорциональная ширина. В принципе, все, что было сказано к предыдущему, верно и здесь,
|
||||
* за исключением того, что высота здесь не может превышать ширину * 1,5f
|
||||
*/
|
||||
private static void fillDimensionOPQ(VKApiPhotoSize result, float ratio, int width) {
|
||||
fillDimensionSMXY(result, Math.min(1.5f, ratio), width);
|
||||
}
|
||||
|
||||
/*
|
||||
* А здесь просто берем одну сторону за фактическую и исходя из нее вычисляем другую.
|
||||
*/
|
||||
private static void fillDimensionZW(VKApiPhotoSize result, float ratio, int allowedWidth, int allowedHeight) {
|
||||
if(ratio > 1) { // ширина больше высоты
|
||||
result.width = allowedWidth;
|
||||
result.height = (int) (result.width / ratio);
|
||||
} else {
|
||||
result.height = allowedHeight;
|
||||
result.width = (int) (result.height * ratio);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dimension with explicit dimensions.
|
||||
* Can be helpful if the dimensions are exactly known.
|
||||
*/
|
||||
public static VKApiPhotoSize create(String url, int width, int height) {
|
||||
VKApiPhotoSize result = new VKApiPhotoSize();
|
||||
result.src = url;
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
float ratio = width / (float) height ;
|
||||
if(width <= 75) {
|
||||
result.type = S;
|
||||
} else if(width <= 130) {
|
||||
result.type = ratio <= 1.5f ? O : M;
|
||||
} else if(width <= 200 && ratio <= 1.5f) {
|
||||
result.type = P;
|
||||
} else if(width <= 320 && ratio <= 1.5f) {
|
||||
result.type = Q;
|
||||
} else if(width <= 604 ) {
|
||||
result.type = X;
|
||||
} else if(width <= 807) {
|
||||
result.type = Y;
|
||||
} else if(width <= 1280 && height <= 1024) {
|
||||
result.type = Z;
|
||||
} else if(width <= 2560 && height <= 2048) {
|
||||
result.type = W;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dimension type and size of the original.
|
||||
*/
|
||||
public static VKApiPhotoSize create(String url, char type, int originalWidth, int originalHeight) {
|
||||
VKApiPhotoSize result = new VKApiPhotoSize();
|
||||
result.src = url;
|
||||
result.type = type;
|
||||
fillDimensions(result, originalWidth, originalHeight);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a square dimension type and size of the original.
|
||||
*/
|
||||
public static VKApiPhotoSize create(String url, int dimension) {
|
||||
return create(url, dimension, dimension);
|
||||
}
|
||||
}
|
149
src/com/vk/sdk/api/model/VKApiPoll.java
Normal file
149
src/com/vk/sdk/api/model/VKApiPoll.java
Normal file
@ -0,0 +1,149 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* PollAttachment.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* Describes poll on the wall on board.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiPoll extends VKAttachments.VKApiAttachment {
|
||||
|
||||
/**
|
||||
* Poll ID to get information about it using polls.getById method;
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* ID of the user or community that owns this poll.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) the poll was created.
|
||||
*/
|
||||
public long created;
|
||||
|
||||
/**
|
||||
* Question in the poll.
|
||||
*/
|
||||
public String question;
|
||||
|
||||
/**
|
||||
* The total number of users answered.
|
||||
*/
|
||||
public int votes;
|
||||
|
||||
/**
|
||||
* Response ID of the current user(if the current user has not yet posted in this poll, it contains 0)
|
||||
*/
|
||||
public int answer_id;
|
||||
|
||||
/**
|
||||
* Array of answers for this question.
|
||||
*/
|
||||
public VKList<Answer> answers;
|
||||
|
||||
/**
|
||||
* Fills a Poll instance from JSONObject.
|
||||
*/
|
||||
public VKApiPoll parse(JSONObject source) {
|
||||
id = source.optInt("id");
|
||||
owner_id = source.optInt("owner_id");
|
||||
created = source.optLong("created");
|
||||
question = source.optString("question");
|
||||
votes = source.optInt("votes");
|
||||
answer_id = source.optInt("answer_id");
|
||||
answers = new VKList<Answer>(source.optJSONArray("answers"), Answer.class);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Country instance.
|
||||
*/
|
||||
public VKApiPoll() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents answer for the poll
|
||||
*/
|
||||
public final static class Answer extends VKApiModel implements Identifiable {
|
||||
|
||||
/**
|
||||
* ID of the answer for the question
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Text of the answer
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* Number of users that voted for this answer
|
||||
*/
|
||||
public int votes;
|
||||
|
||||
/**
|
||||
* Rate of this answer in percent
|
||||
*/
|
||||
public double rate;
|
||||
|
||||
public Answer parse(JSONObject source) {
|
||||
id = source.optInt("id");
|
||||
text = source.optString("text");
|
||||
votes = source.optInt("votes");
|
||||
rate = source.optDouble("rate");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
209
src/com/vk/sdk/api/model/VKApiPost.java
Normal file
209
src/com/vk/sdk/api/model/VKApiPost.java
Normal file
@ -0,0 +1,209 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Post.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* A post object describes a wall post.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiPost extends VKAttachments.VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Post ID on the wall, positive number
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Wall owner ID.
|
||||
*/
|
||||
public int to_id;
|
||||
|
||||
/**
|
||||
* ID of the user who posted.
|
||||
*/
|
||||
public int from_id;
|
||||
|
||||
/**
|
||||
* Date (in Unix time) the post was added.
|
||||
*/
|
||||
public long date;
|
||||
|
||||
/**
|
||||
* Text of the post.
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* ID of the wall owner the post to which the reply is addressed (if the post is a reply to another wall post).
|
||||
*/
|
||||
public int reply_owner_id;
|
||||
|
||||
/**
|
||||
* ID of the wall post to which the reply is addressed (if the post is a reply to another wall post).
|
||||
*/
|
||||
public int reply_post_id;
|
||||
|
||||
/**
|
||||
* True, if the post was created with "Friends only" option.
|
||||
*/
|
||||
public boolean friends_only;
|
||||
|
||||
/**
|
||||
* Number of comments.
|
||||
*/
|
||||
public int comments_count;
|
||||
|
||||
/**
|
||||
* Whether the current user can leave comments to the post (false — cannot, true — can)
|
||||
*/
|
||||
public boolean can_post_comment;
|
||||
|
||||
/**
|
||||
* Number of users who liked the post.
|
||||
*/
|
||||
public int likes_count;
|
||||
|
||||
/**
|
||||
* Whether the user liked the post (false — not liked, true — liked)
|
||||
*/
|
||||
public boolean user_likes;
|
||||
|
||||
/**
|
||||
* Whether the user can like the post (false — cannot, true — can).
|
||||
*/
|
||||
public boolean can_like;
|
||||
|
||||
/**
|
||||
* Whether the user can repost (false — cannot, true — can).
|
||||
*/
|
||||
public boolean can_publish;
|
||||
|
||||
/**
|
||||
* Number of users who copied the post.
|
||||
*/
|
||||
public int reposts_count;
|
||||
|
||||
/**
|
||||
* Whether the user reposted the post (false — not reposted, true — reposted).
|
||||
*/
|
||||
public boolean user_reposted;
|
||||
|
||||
/**
|
||||
* Type of the post, can be: post, copy, reply, postpone, suggest.
|
||||
*/
|
||||
public String post_type;
|
||||
|
||||
/**
|
||||
* Information about attachments to the post (photos, links, etc.), if any;
|
||||
*/
|
||||
public VKAttachments attachments = new VKAttachments();
|
||||
|
||||
/**
|
||||
* ID of the author (if the post was published by a community and signed by a user).
|
||||
*/
|
||||
public int signer_id;
|
||||
|
||||
/**
|
||||
* List of history of the reposts.
|
||||
*/
|
||||
public VKList<VKApiPost> copy_history;
|
||||
|
||||
/**
|
||||
* Fills a Post instance from JSONObject.
|
||||
*/
|
||||
public VKApiPost parse(JSONObject source) throws JSONException {
|
||||
id = source.optInt("id");
|
||||
to_id = source.optInt("to_id");
|
||||
from_id = source.optInt("from_id");
|
||||
date = source.optLong("date");
|
||||
text = source.optString("text");
|
||||
reply_owner_id = source.optInt("reply_owner_id");
|
||||
reply_post_id = source.optInt("reply_post_id");
|
||||
friends_only = ParseUtils.parseBoolean(source, "friends_only");
|
||||
JSONObject comments = source.optJSONObject("comments");
|
||||
if(comments != null) {
|
||||
comments_count = comments.optInt("count");
|
||||
can_post_comment = ParseUtils.parseBoolean(comments, "can_post");
|
||||
}
|
||||
JSONObject likes = source.optJSONObject("likes");
|
||||
if(likes != null) {
|
||||
likes_count = likes.optInt("count");
|
||||
user_likes = ParseUtils.parseBoolean(likes, "user_likes");
|
||||
can_like = ParseUtils.parseBoolean(likes, "can_like");
|
||||
can_publish = ParseUtils.parseBoolean(likes, "can_publish");
|
||||
}
|
||||
JSONObject reposts = source.optJSONObject("reposts");
|
||||
if(reposts != null) {
|
||||
reposts_count = reposts.optInt("count");
|
||||
user_reposted = ParseUtils.parseBoolean(reposts, "user_reposted");
|
||||
}
|
||||
post_type = source.optString("post_type");
|
||||
attachments.fill(source.optJSONArray("attachments"));
|
||||
signer_id = source.optInt("signer_id");
|
||||
copy_history = new VKList<VKApiPost>(source.optJSONArray("copy_history"), VKApiPost.class);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Post instance.
|
||||
*/
|
||||
public VKApiPost() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
return new StringBuilder(VKAttachments.TYPE_POST).append(to_id).append('_').append(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
String url = "http://vk.com/" + VKAttachments.TYPE_POST + to_id + "_" + id;
|
||||
StringBuilder att = new StringBuilder();
|
||||
att.append("<div class='hr'>");
|
||||
attachments.forEach(p -> att.append(p.toHtml()));
|
||||
att.append("</div>");
|
||||
return String.format("<div class='wall'>"
|
||||
+ "<a href='%s'>Запись на стене</a><br/>"
|
||||
+ "%s\n%s</div>", url, text, att);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return VKAttachments.TYPE_POST;
|
||||
}
|
||||
}
|
59
src/com/vk/sdk/api/model/VKApiPostedPhoto.java
Normal file
59
src/com/vk/sdk/api/model/VKApiPostedPhoto.java
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* PostdPhoto.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 19.01.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* Subclass to directly uploaded wall photo.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiPostedPhoto extends VKApiPhoto {
|
||||
|
||||
/**
|
||||
* Fills a PostedPhoto instance from JSONObject.
|
||||
*/
|
||||
public VKApiPostedPhoto parse(JSONObject from) {
|
||||
super.parse(from);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty PostedPhoto instance.
|
||||
*/
|
||||
public VKApiPostedPhoto() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_POSTED_PHOTO;
|
||||
}
|
||||
}
|
280
src/com/vk/sdk/api/model/VKApiVideo.java
Normal file
280
src/com/vk/sdk/api/model/VKApiVideo.java
Normal file
@ -0,0 +1,280 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Video.java
|
||||
* VK Dev
|
||||
*
|
||||
* Created by Babichev Vitaly on 29.09.13.
|
||||
* Copyright (c) 2013 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import static com.vk.sdk.api.model.ParseUtils.parseBoolean;
|
||||
import static com.vk.sdk.api.model.VKAttachments.*;
|
||||
|
||||
/**
|
||||
* A video object describes an video file.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKApiVideo extends VKAttachments.VKApiAttachment implements Identifiable {
|
||||
|
||||
/**
|
||||
* Video ID.
|
||||
*/
|
||||
public int id;
|
||||
|
||||
/**
|
||||
* Video owner ID.
|
||||
*/
|
||||
public int owner_id;
|
||||
|
||||
/**
|
||||
* Video album ID.
|
||||
*/
|
||||
public int album_id;
|
||||
|
||||
/**
|
||||
* Video title.
|
||||
*/
|
||||
public String title;
|
||||
|
||||
/**
|
||||
* Text describing video.
|
||||
*/
|
||||
public String description;
|
||||
|
||||
/**
|
||||
* Duration of the video in seconds.
|
||||
*/
|
||||
public int duration;
|
||||
|
||||
/**
|
||||
* String with video+vid key.
|
||||
*/
|
||||
public String link;
|
||||
|
||||
/**
|
||||
* Date when the video was added, as unixtime.
|
||||
*/
|
||||
public long date;
|
||||
|
||||
/**
|
||||
* Number of views of the video.
|
||||
*/
|
||||
public int views;
|
||||
|
||||
/**
|
||||
* URL of the page with a player that can be used to play a video in the browser.
|
||||
* Flash and HTML5 video players are supported; the player is always zoomed to fit
|
||||
* the window size.
|
||||
*/
|
||||
public String player;
|
||||
|
||||
/**
|
||||
* URL of the video cover image with the size of 130x98px.
|
||||
*/
|
||||
public String photo_130;
|
||||
|
||||
/**
|
||||
* URL of the video cover image with the size of 320x240px.
|
||||
*/
|
||||
public String photo_320;
|
||||
|
||||
/**
|
||||
* URL of the video cover image with the size of 640x480px (if available).
|
||||
*/
|
||||
public String photo_640;
|
||||
|
||||
/**
|
||||
* Array of all photos.
|
||||
*/
|
||||
public VKPhotoSizes photo = new VKPhotoSizes();
|
||||
|
||||
/**
|
||||
* An access key using for get information about hidden objects.
|
||||
*/
|
||||
public String access_key;
|
||||
|
||||
/**
|
||||
* Number of comments on the video.
|
||||
*/
|
||||
public int comments;
|
||||
|
||||
/**
|
||||
* Whether the current user can comment on the video
|
||||
*/
|
||||
public boolean can_comment;
|
||||
|
||||
/**
|
||||
* Whether the current user can repost this video
|
||||
*/
|
||||
public boolean can_repost;
|
||||
|
||||
/**
|
||||
* Information whether the current user liked the video.
|
||||
*/
|
||||
public boolean user_likes;
|
||||
|
||||
/**
|
||||
* Information whether the the video should be repeated.
|
||||
*/
|
||||
public boolean repeat;
|
||||
|
||||
/**
|
||||
* Number of likes on the video.
|
||||
*/
|
||||
public int likes;
|
||||
|
||||
/**
|
||||
* Privacy to view of this video.
|
||||
*/
|
||||
public int privacy_view;
|
||||
|
||||
/**
|
||||
* Privacy to comment of this video.
|
||||
*/
|
||||
public int privacy_comment;
|
||||
|
||||
/**
|
||||
* URL of video with height of 240 pixels. Returns only if you use direct auth.
|
||||
*/
|
||||
public String mp4_240;
|
||||
|
||||
/**
|
||||
* URL of video with height of 360 pixels. Returns only if you use direct auth.
|
||||
*/
|
||||
public String mp4_360;
|
||||
|
||||
/**
|
||||
* URL of video with height of 480 pixels. Returns only if you use direct auth.
|
||||
*/
|
||||
public String mp4_480;
|
||||
|
||||
/**
|
||||
* URL of video with height of 720 pixels. Returns only if you use direct auth.
|
||||
*/
|
||||
public String mp4_720;
|
||||
|
||||
/**
|
||||
* URL of the external video link.
|
||||
*/
|
||||
public String external;
|
||||
|
||||
/**
|
||||
* Fills a Video instance from JSONObject.
|
||||
*/
|
||||
public VKApiVideo parse(JSONObject from) {
|
||||
id = from.optInt("id");
|
||||
owner_id = from.optInt("owner_id");
|
||||
title = from.optString("title");
|
||||
description = from.optString("description");
|
||||
duration = from.optInt("duration");
|
||||
link = from.optString("link");
|
||||
date = from.optLong("date");
|
||||
views = from.optInt("views");
|
||||
comments = from.optInt("comments");
|
||||
player = from.optString("player");
|
||||
access_key = from.optString("access_key");
|
||||
album_id = from.optInt("album_id");
|
||||
|
||||
JSONObject likes = from.optJSONObject("likes");
|
||||
if(likes != null) {
|
||||
this.likes = likes.optInt("count");
|
||||
user_likes = parseBoolean(likes, "user_likes");
|
||||
}
|
||||
can_comment = parseBoolean(from, "can_comment");
|
||||
can_repost = parseBoolean(from, "can_repost");
|
||||
repeat = parseBoolean(from, "repeat");
|
||||
|
||||
privacy_view = VKPrivacy.parsePrivacy(from.optJSONObject("privacy_view"));
|
||||
privacy_comment = VKPrivacy.parsePrivacy(from.optJSONObject("privacy_comment"));
|
||||
|
||||
JSONObject files = from.optJSONObject("files");
|
||||
if(files != null) {
|
||||
mp4_240 = files.optString("mp4_240");
|
||||
mp4_360 = files.optString("mp4_360");
|
||||
mp4_480 = files.optString("mp4_480");
|
||||
mp4_720 = files.optString("mp4_720");
|
||||
external = files.optString("external");
|
||||
}
|
||||
|
||||
photo_130 = from.optString("photo_130");
|
||||
if(!TextUtils.isEmpty(photo_130)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_130, 130));
|
||||
}
|
||||
|
||||
photo_320 = from.optString("photo_320");
|
||||
if(!TextUtils.isEmpty(photo_320)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_320, 320));
|
||||
}
|
||||
|
||||
photo_640 = from.optString("photo_640");
|
||||
if(!TextUtils.isEmpty(photo_640)) {
|
||||
photo.add(VKApiPhotoSize.create(photo_640, 640));
|
||||
}
|
||||
|
||||
photo.sort();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates empty Video instance.
|
||||
*/
|
||||
public VKApiVideo() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toAttachmentString() {
|
||||
StringBuilder result = new StringBuilder(TYPE_VIDEO).append(owner_id).append('_').append(id);
|
||||
if(!TextUtils.isEmpty(access_key)) {
|
||||
result.append('_');
|
||||
result.append(access_key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toHtml() {
|
||||
String preview = photo.get(0).src;
|
||||
String url = "http://vk.com/" + TYPE_VIDEO + owner_id + "_" + id;
|
||||
String d = TextUtils.formatDuration(duration);
|
||||
return String.format("<a href='%s'><img src='%s'/><br/>%s (%s)</a>", url, preview, title, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE_VIDEO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
}
|
209
src/com/vk/sdk/api/model/VKAttachments.java
Normal file
209
src/com/vk/sdk/api/model/VKAttachments.java
Normal file
@ -0,0 +1,209 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* VKAttachments.java
|
||||
* vk-android-sdk
|
||||
*
|
||||
* Created by Babichev Vitaly on 01.02.14.
|
||||
* Copyright (c) 2014 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A list of attachments in {@link VKApiComment}, {@link VKApiPost}, {@link VKApiMessage}
|
||||
*/
|
||||
public class VKAttachments extends VKList<VKAttachments.VKApiAttachment> {
|
||||
|
||||
/**
|
||||
* Attachment is a photo.
|
||||
* @see {@link VKApiPhoto}
|
||||
*/
|
||||
public static final String TYPE_PHOTO = "photo";
|
||||
|
||||
/**
|
||||
* Attachment is a video.
|
||||
* @see {@link VKApiVideo}
|
||||
*/
|
||||
public static final String TYPE_VIDEO = "video";
|
||||
|
||||
/**
|
||||
* Attachment is an audio.
|
||||
* @see {@link VKApiAudio}
|
||||
*/
|
||||
public static final String TYPE_AUDIO = "audio";
|
||||
|
||||
/**
|
||||
* Attachment is a document.
|
||||
* @see {@link VKApiDocument}
|
||||
*/
|
||||
public static final String TYPE_DOC = "doc";
|
||||
|
||||
/**
|
||||
* Attachment is a wall post.
|
||||
* @see {@link VKApiPost}
|
||||
*/
|
||||
public static final String TYPE_POST = "wall";
|
||||
|
||||
/**
|
||||
* Attachment is a posted photo.
|
||||
* @see {@link VKApiPostedPhoto}
|
||||
*/
|
||||
public static final String TYPE_POSTED_PHOTO = "posted_photo";
|
||||
|
||||
/**
|
||||
* Attachment is a link
|
||||
* @see {@link VKApiLink}
|
||||
*/
|
||||
public static final String TYPE_LINK = "link";
|
||||
|
||||
/**
|
||||
* Attachment is a note
|
||||
* @see {@link VKApiNote}
|
||||
*/
|
||||
public static final String TYPE_NOTE = "note";
|
||||
|
||||
/**
|
||||
* Attachment is an application content
|
||||
* @see {@link VKApiApplicationContent}
|
||||
*/
|
||||
public static final String TYPE_APP = "app";
|
||||
|
||||
/**
|
||||
* Attachment is a poll
|
||||
* @see {@link VKApiPoll}
|
||||
*/
|
||||
public static final String TYPE_POLL = "poll";
|
||||
|
||||
/**
|
||||
* Attachment is a WikiPage
|
||||
* @see {@link VKApiWikiPage}
|
||||
*/
|
||||
public static final String TYPE_WIKI_PAGE = "page";
|
||||
|
||||
/**
|
||||
* Attachment is a PhotoAlbum
|
||||
* @see {@link VKApiPhotoAlbum}
|
||||
*/
|
||||
public static final String TYPE_ALBUM = "album";
|
||||
|
||||
|
||||
public VKAttachments() {
|
||||
super();
|
||||
}
|
||||
|
||||
public VKAttachments(VKApiAttachment... data) {
|
||||
super(Arrays.asList(data));
|
||||
}
|
||||
|
||||
public VKAttachments(List<? extends VKApiAttachment> data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public VKAttachments(JSONObject from) {
|
||||
super();
|
||||
fill(from);
|
||||
}
|
||||
|
||||
public VKAttachments(JSONArray from) {
|
||||
super();
|
||||
fill(from);
|
||||
}
|
||||
|
||||
public void fill(JSONObject from) {
|
||||
super.fill(from, parser);
|
||||
}
|
||||
|
||||
public void fill(JSONArray from) {
|
||||
super.fill(from, parser);
|
||||
}
|
||||
|
||||
public String toAttachmentsString() {
|
||||
ArrayList<CharSequence> attachments = new ArrayList<>();
|
||||
this.stream().forEach((attach) -> {
|
||||
attachments.add(attach.toAttachmentString());
|
||||
});
|
||||
return String.join(",", attachments);
|
||||
}
|
||||
/**
|
||||
* Parser that's used for parsing photo sizes.
|
||||
*/
|
||||
private final Parser<VKApiAttachment> parser = new Parser<VKApiAttachment>() {
|
||||
@Override
|
||||
public VKApiAttachment parseObject(JSONObject attachment) throws Exception {
|
||||
String type = attachment.optString("type");
|
||||
if(null != type) switch (type) {
|
||||
case TYPE_PHOTO:
|
||||
return new VKApiPhoto().parse(attachment.getJSONObject(TYPE_PHOTO));
|
||||
case TYPE_VIDEO:
|
||||
return new VKApiVideo().parse(attachment.getJSONObject(TYPE_VIDEO));
|
||||
case TYPE_AUDIO:
|
||||
return new VKApiAudio().parse(attachment.getJSONObject(TYPE_AUDIO));
|
||||
case TYPE_DOC:
|
||||
return new VKApiDocument().parse(attachment.getJSONObject(TYPE_DOC));
|
||||
case TYPE_POST:
|
||||
return new VKApiPost().parse(attachment.getJSONObject(TYPE_POST));
|
||||
case TYPE_POSTED_PHOTO:
|
||||
return new VKApiPostedPhoto().parse(attachment.getJSONObject(TYPE_POSTED_PHOTO));
|
||||
case TYPE_LINK:
|
||||
return new VKApiLink().parse(attachment.getJSONObject(TYPE_LINK));
|
||||
case TYPE_NOTE:
|
||||
return new VKApiNote().parse(attachment.getJSONObject(TYPE_NOTE));
|
||||
case TYPE_APP:
|
||||
return new VKApiApplicationContent().parse(attachment.getJSONObject(TYPE_APP));
|
||||
case TYPE_POLL:
|
||||
return new VKApiPoll().parse(attachment.getJSONObject(TYPE_POLL));
|
||||
case TYPE_ALBUM:
|
||||
return new VKApiPhotoAlbum().parse(attachment.getJSONObject(TYPE_ALBUM));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An abstract class for all attachments
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract static class VKApiAttachment extends VKApiModel implements Identifiable {
|
||||
|
||||
/**
|
||||
* Convert attachment to special string to attach it to the post, message or comment.
|
||||
*/
|
||||
public abstract CharSequence toAttachmentString();
|
||||
|
||||
public CharSequence toHtml() {
|
||||
return toAttachmentString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type of this attachment
|
||||
*/
|
||||
public abstract String getType();
|
||||
}
|
||||
}
|
417
src/com/vk/sdk/api/model/VKList.java
Normal file
417
src/com/vk/sdk/api/model/VKList.java
Normal file
@ -0,0 +1,417 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Universal data list for VK API.
|
||||
* This class is not thread-safe.
|
||||
* @param <T> type of stored values.
|
||||
* @see <a href="http://vk.com/dev/list">http://vk.com/dev/list</a>
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||
public class VKList<T extends VKApiModel & Identifiable> extends VKApiModel implements java.util.List<T> {
|
||||
|
||||
/**
|
||||
* The server did not return the count field.
|
||||
*/
|
||||
private final static int NO_COUNT = -1;
|
||||
|
||||
/**
|
||||
* Decorated list
|
||||
*/
|
||||
private ArrayList<T> items = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Field {@code count} which returned by server.
|
||||
*/
|
||||
private int count = NO_COUNT;
|
||||
|
||||
/**
|
||||
* Creates empty list.
|
||||
*/
|
||||
public VKList() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with given data.
|
||||
*/
|
||||
public VKList(java.util.List<? extends T> data) {
|
||||
assert data != null;
|
||||
items = new ArrayList<T>(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with data in {@code from}.
|
||||
* @param from an object that represents a list adopted in accordance with VK API format. You can use null.
|
||||
* @param clazz class represents a model that has a public constructor with {@link org.json.JSONObject} argument.
|
||||
*/
|
||||
public VKList(JSONObject from, Class<? extends T> clazz) {
|
||||
fill(from, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with data in {@code from}.
|
||||
* @param from an array of items in the list. You can use null.
|
||||
* @param clazz class represents a model that has a public constructor with {@link org.json.JSONObject} argument.
|
||||
*/
|
||||
public VKList(JSONArray from, Class<? extends T> clazz) {
|
||||
fill(from, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with data in {@code from}.
|
||||
* @param from an object that represents a list adopted in accordance with VK API format. You can use null.
|
||||
* @param creator interface implementation to parse objects.
|
||||
*/
|
||||
public VKList(JSONObject from, Parser<T> creator) {
|
||||
|
||||
fill(from, creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with data in {@code from}.
|
||||
* @param from an array of items in the list. You can use null.
|
||||
* @param creator interface implementation to parse objects.
|
||||
*/
|
||||
public VKList(JSONArray from, Parser<T> creator) {
|
||||
|
||||
fill(from, creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills list according with data in {@code from}.
|
||||
* @param from an object that represents a list adopted in accordance with VK API format. You can use null.
|
||||
* @param clazz class represents a model that has a public constructor with {@link org.json.JSONObject} argument.
|
||||
*/
|
||||
public void fill(JSONObject from, Class<? extends T> clazz) {
|
||||
if (from.has("response")) {
|
||||
JSONArray array = from.optJSONArray("response");
|
||||
if (array != null) {
|
||||
fill(array, clazz);
|
||||
}
|
||||
else {
|
||||
fill(from.optJSONObject("response"), clazz);
|
||||
}
|
||||
} else {
|
||||
fill(from, new ReflectParser<T>(clazz));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list and fills it according with data in {@code from}.
|
||||
* @param from an array of items in the list. You can use null.
|
||||
* @param clazz class represents a model that has a public constructor with {@link org.json.JSONObject} argument.
|
||||
*/
|
||||
public void fill(JSONArray from, Class<? extends T> clazz) {
|
||||
fill(from, new ReflectParser<T>(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills list according with data in {@code from}.
|
||||
* @param from an object that represents a list adopted in accordance with VK API format. You can use null.
|
||||
* @param creator interface implementation to parse objects.
|
||||
*/
|
||||
public void fill(JSONObject from, Parser<? extends T> creator) {
|
||||
if(from != null) {
|
||||
fill(from.optJSONArray("items"), creator);
|
||||
count = from.optInt("count", count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills list according with data in {@code from}.
|
||||
* @param from an array of items in the list. You can use null.
|
||||
* @param creator interface implementation to parse objects.
|
||||
*/
|
||||
public void fill(JSONArray from, Parser<? extends T> creator) {
|
||||
if(from != null) {
|
||||
for(int i = 0; i < from.length(); i++) {
|
||||
try {
|
||||
T object = creator.parseObject(from.getJSONObject(i));
|
||||
if(object != null) {
|
||||
items.add(object);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element before the element with the specified id.
|
||||
* If an element with the specified id is not found, adds an element to the end of the list.
|
||||
* @param id element identifier to add element before it.
|
||||
* @param data element to add
|
||||
*/
|
||||
public void addBefore(int id, T data) {
|
||||
int size = size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
if(get(i).getId() > id || i == size - 1) {
|
||||
add(i, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element after the element with the specified id.
|
||||
* If an element with the specified id is not found, adds an element to the end of the list.
|
||||
* @param id element identifier to add element after it.
|
||||
* @param data element to add
|
||||
*/
|
||||
public void addAfter(int id, T data) {
|
||||
int size = size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
if(get(i).getId() > id || i == size - 1) {
|
||||
add(i + 1, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element according with id.
|
||||
* If nothing found, returns null.
|
||||
*/
|
||||
public T getById(int id) {
|
||||
for(T item: this) {
|
||||
if(item.getId() == id) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches through the list of available items. <br />
|
||||
* <br />
|
||||
* The search will be carried out not by the content of characters per line, and the content of them in separate words. <br />
|
||||
* <br />
|
||||
* Search is not case sensitive. <br />
|
||||
* <br />
|
||||
* To support search class {@code T} must have overridden method {@link #toString()},
|
||||
* search will be carried out exactly according to the result of calling this method. <br />
|
||||
* <br />
|
||||
* <br />
|
||||
* Suppose there are elements in the list of contents:
|
||||
* <code><pre>
|
||||
* - Hello world
|
||||
* - Hello test
|
||||
* </pre></code>
|
||||
* In this case, the matches will be on search phrases {@code 'Hel'}, {@code 'Hello'}, {@code 'test'}, but not on {@code 'llo'}, {@code 'llo world'}
|
||||
*
|
||||
* @param query search query can not be equal to {@code null}, but can be an empty string.
|
||||
* @return created based on the search results new list. If no matches are found, the list will be empty.
|
||||
*/
|
||||
public VKList<T> search(String query) {
|
||||
VKList<T> result = new VKList<T>();
|
||||
final Pattern pattern = Pattern.compile("(?i).*\\b" + query + ".*");
|
||||
for (T item : this) {
|
||||
if (pattern.matcher(item.toString()).find()) {
|
||||
result.add(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the return value of the field VK API {@code count}, if it has been returned, and the size of the list, if not.
|
||||
*/
|
||||
public int getCount() {
|
||||
return count != NO_COUNT ? count : size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int location, T object) {
|
||||
items.add(location, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T object) {
|
||||
return items.add(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int location, Collection<? extends T> collection) {
|
||||
return items.addAll(location, collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> collection) {
|
||||
return items.addAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
items.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object object) {
|
||||
return items.contains(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
assert collection != null;
|
||||
return items.containsAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return ((Object) this).getClass().equals(object.getClass()) && items.equals(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int location) {
|
||||
return items.get(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object object) {
|
||||
return items.indexOf(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return items.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return items.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object object) {
|
||||
return items.lastIndexOf(object);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator() {
|
||||
return items.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator(int location) {
|
||||
return items.listIterator(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int location) {
|
||||
return items.remove(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object object) {
|
||||
return items.remove(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
assert collection != null;
|
||||
return items.removeAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
return items.retainAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int location, T object) {
|
||||
return items.set(location, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<T> subList(int start, int end) {
|
||||
return items.subList(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return items.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T1> T1[] toArray(T1[] array) {
|
||||
assert array != null;
|
||||
return items.toArray(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when parsing the list objects as interator created from {@link org.json.JSONArray} a instances of items of the list.
|
||||
* @param <D> list item type.
|
||||
*/
|
||||
public static interface Parser<D> {
|
||||
|
||||
/**
|
||||
* Creates a list item of its representation return VK API from {@link org.json.JSONArray}
|
||||
* @param source representation of the object in the format returned by VK API.
|
||||
* @return created element to add to the list.
|
||||
* @throws Exception if the exception is thrown, the element iterated this method will not be added to the list.
|
||||
*/
|
||||
D parseObject(JSONObject source) throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser list items using reflection mechanism.
|
||||
* To use an object class must have a public constructor that accepts {@link org.json.JSONObject}.
|
||||
* If, during the creation of the object constructor will throw any exception, the element will not be added to the list.
|
||||
* @param <D> list item type.
|
||||
*/
|
||||
public final static class ReflectParser<D extends VKApiModel> implements Parser<D> {
|
||||
|
||||
private final Class<? extends D> clazz;
|
||||
|
||||
public ReflectParser(Class<? extends D> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public D parseObject(JSONObject source) throws Exception {
|
||||
return (D) clazz.newInstance().parse(source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKApiModel parse(JSONObject response) throws JSONException {
|
||||
throw new JSONException("Operation is not supported while class is generic");
|
||||
}
|
||||
}
|
36
src/com/vk/sdk/api/model/VKPhotoArray.java
Normal file
36
src/com/vk/sdk/api/model/VKPhotoArray.java
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Array of API photos objects
|
||||
*/
|
||||
public class VKPhotoArray extends VKList<VKApiPhoto> {
|
||||
@Override
|
||||
public VKApiModel parse(JSONObject response) throws JSONException {
|
||||
fill(response, VKApiPhoto.class);
|
||||
return this;
|
||||
}
|
||||
}
|
208
src/com/vk/sdk/api/model/VKPhotoSizes.java
Normal file
208
src/com/vk/sdk/api/model/VKPhotoSizes.java
Normal file
@ -0,0 +1,208 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Model to parse a list of photo with <a href="http://vk.com/dev/photo_sizes">photo sizes<a/> format.
|
||||
*
|
||||
* When {@code photo_sizes=1} parameter is used in methods,
|
||||
* response contains an info about original photo
|
||||
* copies with different sizes in sizes array with objects,
|
||||
* each of them contains following fields: <br />
|
||||
* <ul>
|
||||
* <li>src — url of image copy;</li>
|
||||
* <li> width — copy width, px;</li>
|
||||
* <li> height — copy height, px;</li>
|
||||
* <li>type — notation for copy size and ratio.</li>
|
||||
* </ul>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKPhotoSizes extends VKList<VKApiPhotoSize> {
|
||||
|
||||
private static float sQuality = 1.0f;
|
||||
|
||||
/**
|
||||
* Sets the quality modifier for sampling algorithm of image resolution.
|
||||
* @param quality positive number between 0.0f and 1.0f.
|
||||
*/
|
||||
public static void setQuality(float quality) {
|
||||
sQuality = quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Original width of photo in pixels.
|
||||
*/
|
||||
private int mOriginalWidth = 1;
|
||||
|
||||
/**
|
||||
* Original height of photo in pixels.
|
||||
*/
|
||||
private int mOriginalHeight = 1;
|
||||
|
||||
/**
|
||||
* URL of last image thumb for width sampling algorithm.
|
||||
*/
|
||||
private String mWidthThumb;
|
||||
/**
|
||||
* URL of last image thumb for height sampling algorithm.
|
||||
*/
|
||||
private String mHeightThumb;
|
||||
|
||||
/**
|
||||
* Width of last image thumb for width sampling algorithm.
|
||||
*/
|
||||
private int mLastWidth;
|
||||
|
||||
/**
|
||||
* Height of last image thumb for width sampling algorithm.
|
||||
*/
|
||||
private int mLastHeight;
|
||||
|
||||
/**
|
||||
* Parser that's used for parsing photo sizes.
|
||||
*/
|
||||
private final Parser<VKApiPhotoSize> parser = new Parser<VKApiPhotoSize>() {
|
||||
@Override
|
||||
public VKApiPhotoSize parseObject(JSONObject source) throws Exception {
|
||||
return VKApiPhotoSize.parse(source, mOriginalWidth, mOriginalHeight);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates empty list of photo sizes.
|
||||
*/
|
||||
public VKPhotoSizes() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and fills list of photo sizes.
|
||||
*/
|
||||
public VKPhotoSizes(JSONArray from) {
|
||||
super();
|
||||
fill(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates list of photo sizes which fill with according data.
|
||||
* @param from array of photo sizes returned by VK.
|
||||
* @param width original photo width in pixels.
|
||||
* @param height original photo height in pixels.
|
||||
*/
|
||||
public void fill(JSONArray from, int width, int height) {
|
||||
setOriginalDimension(width, height);
|
||||
fill(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill list according with given data.
|
||||
* @param from array of photo sizes returned by VK.
|
||||
*/
|
||||
public void fill(JSONArray from) {
|
||||
fill(from, parser);
|
||||
sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image according with given type of thumb.
|
||||
* @return URL of image thumb, or null if image with this thumb is not found in the list.
|
||||
*/
|
||||
public String getByType(char type) {
|
||||
for(VKApiPhotoSize size: this) {
|
||||
if(size.type == type) {
|
||||
return size.src;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets original image dimensions.
|
||||
* @param width original photo width in pixels.
|
||||
* @param height original photo height in pixels.
|
||||
*/
|
||||
public void setOriginalDimension(int width, int height) {
|
||||
if(width != 0) {
|
||||
this.mOriginalWidth = width;
|
||||
}
|
||||
if(height != 0) {
|
||||
this.mOriginalHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts thumbs according to their width.
|
||||
*/
|
||||
public void sort() {
|
||||
Collections.sort(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an image that fits perfectly into the specified dimensions.
|
||||
* Method is uses a cache of last thumbs for better performance.
|
||||
* @param width required minimum width of image in pixels.
|
||||
* @param height required minimum height of image in pixels.
|
||||
* @return URL of selected thumb or null if image with what parameters is not found.
|
||||
*/
|
||||
public String getImageForDimension(int width, int height) {
|
||||
return width >= height ? getImageForWidth(width) : getImageForHeight(height);
|
||||
}
|
||||
|
||||
private String getImageForWidth(int width) {
|
||||
if((mWidthThumb != null && mLastWidth != width) || isEmpty()) {
|
||||
return mWidthThumb;
|
||||
}
|
||||
mLastWidth = width;
|
||||
mWidthThumb = null;
|
||||
width = (int) (width * sQuality);
|
||||
|
||||
for(VKApiPhotoSize size : this) {
|
||||
if(size.width >= width) {
|
||||
mWidthThumb = size.src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mWidthThumb;
|
||||
}
|
||||
|
||||
private String getImageForHeight(int height) {
|
||||
if((mHeightThumb != null && mLastHeight != height) || isEmpty()) {
|
||||
return mHeightThumb;
|
||||
}
|
||||
mLastHeight = height;
|
||||
mHeightThumb = null;
|
||||
height = (int) (height * sQuality);
|
||||
|
||||
for(VKApiPhotoSize size : this) {
|
||||
if(size.height >= height) {
|
||||
mHeightThumb = size.src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mHeightThumb;
|
||||
}
|
||||
}
|
37
src/com/vk/sdk/api/model/VKPostArray.java
Normal file
37
src/com/vk/sdk/api/model/VKPostArray.java
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Array of Post
|
||||
* Created by alex_xpert on 29.01.14.
|
||||
*/
|
||||
public class VKPostArray extends VKList<VKApiPost> {
|
||||
@Override
|
||||
public VKApiModel parse(JSONObject response) throws JSONException {
|
||||
fill(response, VKApiPost.class);
|
||||
return this;
|
||||
}
|
||||
}
|
87
src/com/vk/sdk/api/model/VKPrivacy.java
Normal file
87
src/com/vk/sdk/api/model/VKPrivacy.java
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/**
|
||||
* Privacy.java
|
||||
* VK Dev
|
||||
*
|
||||
* Created by Babichev Vitaly on 29.09.13.
|
||||
* Copyright (c) 2013 VK. All rights reserved.
|
||||
*/
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Describes privacy of some VK object
|
||||
*/
|
||||
public class VKPrivacy {
|
||||
|
||||
VKPrivacy() {}
|
||||
|
||||
/**
|
||||
* Access for all users
|
||||
*/
|
||||
public final static int PRIVACY_ALL = 0;
|
||||
|
||||
/**
|
||||
* Access only for friends.
|
||||
*/
|
||||
public final static int PRIVACY_FRIENDS = 1;
|
||||
|
||||
/**
|
||||
* Access only for friends and friend of friends.
|
||||
*/
|
||||
public final static int PRIVACY_FRIENDS_OF_FRIENDS = 2;
|
||||
|
||||
/**
|
||||
* Access only for logged user.
|
||||
*/
|
||||
public final static int PRIVACY_NOBODY = 3;
|
||||
|
||||
/**
|
||||
* Unknown privacy format
|
||||
*/
|
||||
public final static int PRIVACY_UNKNOWN = 4;
|
||||
|
||||
/**
|
||||
* Parses privacy in int format from privacy_view format.
|
||||
* @see <a href="http://vk.com/dev/privacy_setting">http://vk.com/dev/privacy_setting</a>
|
||||
*/
|
||||
public static int parsePrivacy(JSONObject privacyView) {
|
||||
int privacy = 0;
|
||||
if(privacyView != null) {
|
||||
String type = privacyView.optString("type");
|
||||
if("all".equals(type)) {
|
||||
privacy = PRIVACY_ALL;
|
||||
} else if("friends".equals(type)) {
|
||||
privacy = PRIVACY_FRIENDS;
|
||||
} else if("friends_of_friends".equals(type)) {
|
||||
privacy = PRIVACY_FRIENDS_OF_FRIENDS;
|
||||
} else if("nobody".equals(type)) {
|
||||
privacy = PRIVACY_NOBODY;
|
||||
} else {
|
||||
privacy = PRIVACY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
return privacy;
|
||||
}
|
||||
}
|
159
src/com/vk/sdk/api/model/VKScopes.java
Normal file
159
src/com/vk/sdk/api/model/VKScopes.java
Normal file
@ -0,0 +1,159 @@
|
||||
//
|
||||
// Copyright (c) 2014 VK.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
package com.vk.sdk.api.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Application Access Permissions
|
||||
* @see <a href="http://vk.com/dev/permissions">http://vk.com/dev/permissions</a>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class VKScopes {
|
||||
|
||||
private VKScopes() {}
|
||||
|
||||
/**
|
||||
* User allowed to send notifications to him/her.
|
||||
*/
|
||||
public final static String NOTIFY = "notify";
|
||||
|
||||
/**
|
||||
* Access to friends.
|
||||
*/
|
||||
public final static String FRIENDS = "friends";
|
||||
|
||||
/**
|
||||
* Access to photos.
|
||||
*/
|
||||
public final static String PHOTOS = "photos";
|
||||
|
||||
/**
|
||||
* Access to audios.
|
||||
*/
|
||||
public final static String AUDIO = "audio";
|
||||
|
||||
/**
|
||||
* Access to videos.
|
||||
*/
|
||||
public final static String VIDEO = "video";
|
||||
|
||||
/**
|
||||
* Access to documents.
|
||||
*/
|
||||
public final static String DOCS = "docs";
|
||||
|
||||
/**
|
||||
* Access to user notes.
|
||||
*/
|
||||
public final static String NOTES = "notes";
|
||||
|
||||
/**
|
||||
* Access to wiki pages.
|
||||
*/
|
||||
public final static String PAGES = "pages";
|
||||
|
||||
/**
|
||||
* Access to user status.
|
||||
*/
|
||||
public final static String STATUS = "status";
|
||||
|
||||
/**
|
||||
* Access to offers (obsolete methods).
|
||||
*/
|
||||
@Deprecated
|
||||
public final static String OFFERS = "offers";
|
||||
|
||||
/**
|
||||
* Access to questions (obsolete methods).
|
||||
*/
|
||||
@Deprecated
|
||||
public final static String QUESTIONS = "questions";
|
||||
|
||||
/**
|
||||
* Access to standard and advanced methods for the wall.
|
||||
*/
|
||||
public final static String WALL = "wall";
|
||||
|
||||
/**
|
||||
* Access to user groups.
|
||||
*/
|
||||
public final static String GROUPS = "groups";
|
||||
|
||||
/**
|
||||
* Access to advanced methods for messaging.
|
||||
*/
|
||||
public final static String MESSAGES = "messages";
|
||||
|
||||
/**
|
||||
* Access to notifications about answers to the user.
|
||||
*/
|
||||
public final static String NOTIFICATIONS = "notifications";
|
||||
|
||||
/**
|
||||
* Access to statistics of user groups and applications where he/she is an administrator.
|
||||
*/
|
||||
public final static String STATS = "stats";
|
||||
|
||||
/**
|
||||
* Access to advanced methods for <a href="http://vk.com/dev/ads">Ads API</a>.
|
||||
*/
|
||||
public final static String ADS = "ads";
|
||||
|
||||
/**
|
||||
* Access to API at any time from a third party server.
|
||||
*/
|
||||
public final static String OFFLINE = "offline";
|
||||
|
||||
/**
|
||||
* Possibility to make API requests without HTTPS. <br />
|
||||
* <b>Note that this functionality is under testing and can be changed.</b>
|
||||
*/
|
||||
public final static String NOHTTPS = "nohttps";
|
||||
|
||||
/**
|
||||
* Converts integer value of permissions into arraylist of constants
|
||||
* @param permissions integer permissions value
|
||||
* @return ArrayList contains string constants of permissions (scope)
|
||||
*/
|
||||
public static ArrayList<String> parse(int permissions) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
if ((permissions & 1) > 0) result.add(NOTIFY);
|
||||
if ((permissions & 2) > 0) result.add(FRIENDS);
|
||||
if ((permissions & 4) > 0) result.add(PHOTOS);
|
||||
if ((permissions & 8) > 0) result.add(AUDIO);
|
||||
if ((permissions & 16) > 0) result.add(VIDEO);
|
||||
if ((permissions & 128) > 0) result.add(PAGES);
|
||||
if ((permissions & 1024) > 0) result.add(STATUS);
|
||||
if ((permissions & 2048) > 0) result.add(NOTES);
|
||||
if ((permissions & 4096) > 0) result.add(MESSAGES);
|
||||
if ((permissions & 8192) > 0) result.add(WALL);
|
||||
if ((permissions & 32768) > 0) result.add(ADS);
|
||||
if ((permissions & 65536) > 0) result.add(OFFLINE);
|
||||
if ((permissions & 131072) > 0) result.add(DOCS);
|
||||
if ((permissions & 262144) > 0) result.add(GROUPS);
|
||||
if ((permissions & 524288) > 0) result.add(NOTIFICATIONS);
|
||||
if ((permissions & 1048576) > 0) result.add(STATS);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
279
src/org/json/CDL.java
Normal file
279
src/org/json/CDL.java
Normal file
@ -0,0 +1,279 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This provides static methods to convert comma delimited text into a
|
||||
* JSONArray, and to covert a JSONArray into comma delimited text. Comma
|
||||
* delimited text is a very popular format for data interchange. It is
|
||||
* understood by most database, spreadsheet, and organizer programs.
|
||||
* <p>
|
||||
* Each row of text represents a row in a table or a data record. Each row
|
||||
* ends with a NEWLINE character. Each row contains one or more values.
|
||||
* Values are separated by commas. A value can contain any character except
|
||||
* for comma, unless is is wrapped in single quotes or double quotes.
|
||||
* <p>
|
||||
* The first row usually contains the names of the columns.
|
||||
* <p>
|
||||
* A comma delimited list can be converted into a JSONArray of JSONObjects.
|
||||
* The names for the elements in the JSONObjects can be taken from the names
|
||||
* in the first row.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CDL {
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be wrapped in quotes. The value can
|
||||
* be empty.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return The value string, or null if empty.
|
||||
* @throws JSONException if the quoted string is badly formed.
|
||||
*/
|
||||
private static String getValue(JSONTokener x) throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuffer sb;
|
||||
do {
|
||||
c = x.next();
|
||||
} while (c == ' ' || c == '\t');
|
||||
switch (c) {
|
||||
case 0:
|
||||
return null;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuffer();
|
||||
for (;;) {
|
||||
c = x.next();
|
||||
if (c == q) {
|
||||
break;
|
||||
}
|
||||
if (c == 0 || c == '\n' || c == '\r') {
|
||||
throw x.syntaxError("Missing close quote '" + q + "'.");
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
case ',':
|
||||
x.back();
|
||||
return "";
|
||||
default:
|
||||
x.back();
|
||||
return x.nextTo(',');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of strings from a row of comma delimited values.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of strings.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
|
||||
JSONArray ja = new JSONArray();
|
||||
for (;;) {
|
||||
String value = getValue(x);
|
||||
char c = x.next();
|
||||
if (value == null ||
|
||||
(ja.length() == 0 && value.length() == 0 && c != ',')) {
|
||||
return null;
|
||||
}
|
||||
ja.put(value);
|
||||
for (;;) {
|
||||
if (c == ',') {
|
||||
break;
|
||||
}
|
||||
if (c != ' ') {
|
||||
if (c == '\n' || c == '\r' || c == 0) {
|
||||
return ja;
|
||||
}
|
||||
throw x.syntaxError("Bad character '" + c + "' (" +
|
||||
(int)c + ").");
|
||||
}
|
||||
c = x.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject from a row of comma delimited text, using a
|
||||
* parallel JSONArray of strings to provides the names of the elements.
|
||||
* @param names A JSONArray of names. This is commonly obtained from the
|
||||
* first row of a comma delimited text file using the rowToJSONArray
|
||||
* method.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONObject combining the names and values.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
|
||||
throws JSONException {
|
||||
JSONArray ja = rowToJSONArray(x);
|
||||
return ja != null ? ja.toJSONObject(names) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text row from a JSONArray. Values containing
|
||||
* the comma character will be quoted. Troublesome characters may be
|
||||
* removed.
|
||||
* @param ja A JSONArray of strings.
|
||||
* @return A string ending in NEWLINE.
|
||||
*/
|
||||
public static String rowToString(JSONArray ja) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
Object object = ja.opt(i);
|
||||
if (object != null) {
|
||||
String string = object.toString();
|
||||
if (string.length() > 0 && (string.indexOf(',') >= 0 ||
|
||||
string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||
|
||||
string.indexOf(0) >= 0 || string.charAt(0) == '"')) {
|
||||
sb.append('"');
|
||||
int length = string.length();
|
||||
for (int j = 0; j < length; j += 1) {
|
||||
char c = string.charAt(j);
|
||||
if (c >= ' ' && c != '"') {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
sb.append('"');
|
||||
} else {
|
||||
sb.append(string);
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||
* using the first row as a source of names.
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||
* using the first row as a source of names.
|
||||
* @param x The JSONTokener containing the comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
|
||||
return toJSONArray(rowToJSONArray(x), x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||
* using a supplied JSONArray as the source of element names.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param string The comma delimited text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, String string)
|
||||
throws JSONException {
|
||||
return toJSONArray(names, new JSONTokener(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||
* using a supplied JSONArray as the source of element names.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param x A JSONTokener of the source text.
|
||||
* @return A JSONArray of JSONObjects.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
|
||||
throws JSONException {
|
||||
if (names == null || names.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
JSONArray ja = new JSONArray();
|
||||
for (;;) {
|
||||
JSONObject jo = rowToJSONObject(names, x);
|
||||
if (jo == null) {
|
||||
break;
|
||||
}
|
||||
ja.put(jo);
|
||||
}
|
||||
if (ja.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
return ja;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects. The
|
||||
* first row will be a list of names obtained by inspecting the first
|
||||
* JSONObject.
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
JSONObject jo = ja.optJSONObject(0);
|
||||
if (jo != null) {
|
||||
JSONArray names = jo.names();
|
||||
if (names != null) {
|
||||
return rowToString(names) + toString(names, ja);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma delimited text from a JSONArray of JSONObjects using
|
||||
* a provided list of names. The list of names is not included in the
|
||||
* output.
|
||||
* @param names A JSONArray of strings.
|
||||
* @param ja A JSONArray of JSONObjects.
|
||||
* @return A comma delimited text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray names, JSONArray ja)
|
||||
throws JSONException {
|
||||
if (names == null || names.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < ja.length(); i += 1) {
|
||||
JSONObject jo = ja.optJSONObject(i);
|
||||
if (jo != null) {
|
||||
sb.append(rowToString(jo.toJSONArray(names)));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
169
src/org/json/Cookie.java
Normal file
169
src/org/json/Cookie.java
Normal file
@ -0,0 +1,169 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie specification to a JSONObject and back.
|
||||
* JSON and Cookies are both notations for name/value pairs.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Cookie {
|
||||
|
||||
/**
|
||||
* Produce a copy of a string in which the characters '+', '%', '=', ';'
|
||||
* and control characters are replaced with "%hh". This is a gentle form
|
||||
* of URL encoding, attempting to cause as little distortion to the
|
||||
* string as possible. The characters '=' and ';' are meta characters in
|
||||
* cookies. By convention, they are escaped using the URL-encoding. This is
|
||||
* only a convention, not a standard. Often, cookies are expected to have
|
||||
* encoded values. We encode '=' and ';' because we must. We encode '%' and
|
||||
* '+' because they are meta characters in URL encoding.
|
||||
* @param string The source string.
|
||||
* @return The escaped result.
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
char c;
|
||||
String s = string.trim();
|
||||
int length = s.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
c = s.charAt(i);
|
||||
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
|
||||
sb.append('%');
|
||||
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
|
||||
sb.append(Character.forDigit((char)(c & 0x0f), 16));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a cookie specification string into a JSONObject. The string
|
||||
* will contain a name value pair separated by '='. The name and the value
|
||||
* will be unescaped, possibly converting '+' and '%' sequences. The
|
||||
* cookie properties may follow, separated by ';', also represented as
|
||||
* name=value (except the secure property, which does not have a value).
|
||||
* The name will be stored under the key "name", and the value will be
|
||||
* stored under the key "value". This method does not do checking or
|
||||
* validation of the parameters. It only converts the cookie string into
|
||||
* a JSONObject.
|
||||
* @param string The cookie specification string.
|
||||
* @return A JSONObject containing "name", "value", and possibly other
|
||||
* members.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
String name;
|
||||
JSONObject jo = new JSONObject();
|
||||
Object value;
|
||||
JSONTokener x = new JSONTokener(string);
|
||||
jo.put("name", x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put("value", x.nextTo(';'));
|
||||
x.next();
|
||||
while (x.more()) {
|
||||
name = unescape(x.nextTo("=;"));
|
||||
if (x.next() != '=') {
|
||||
if (name.equals("secure")) {
|
||||
value = Boolean.TRUE;
|
||||
} else {
|
||||
throw x.syntaxError("Missing '=' in cookie parameter.");
|
||||
}
|
||||
} else {
|
||||
value = unescape(x.nextTo(';'));
|
||||
x.next();
|
||||
}
|
||||
jo.put(name, value);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie specification string. The JSONObject
|
||||
* must contain "name" and "value" members.
|
||||
* If the JSONObject contains "expires", "domain", "path", or "secure"
|
||||
* members, they will be appended to the cookie specification string.
|
||||
* All other members are ignored.
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie specification string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(escape(jo.getString("name")));
|
||||
sb.append("=");
|
||||
sb.append(escape(jo.getString("value")));
|
||||
if (jo.has("expires")) {
|
||||
sb.append(";expires=");
|
||||
sb.append(jo.getString("expires"));
|
||||
}
|
||||
if (jo.has("domain")) {
|
||||
sb.append(";domain=");
|
||||
sb.append(escape(jo.getString("domain")));
|
||||
}
|
||||
if (jo.has("path")) {
|
||||
sb.append(";path=");
|
||||
sb.append(escape(jo.getString("path")));
|
||||
}
|
||||
if (jo.optBoolean("secure")) {
|
||||
sb.append(";secure");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert <code>%</code><i>hh</i> sequences to single characters, and
|
||||
* convert plus to space.
|
||||
* @param string A string that may contain
|
||||
* <code>+</code> <small>(plus)</small> and
|
||||
* <code>%</code><i>hh</i> sequences.
|
||||
* @return The unescaped string.
|
||||
*/
|
||||
public static String unescape(String string) {
|
||||
int length = string.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
char c = string.charAt(i);
|
||||
if (c == '+') {
|
||||
c = ' ';
|
||||
} else if (c == '%' && i + 2 < length) {
|
||||
int d = JSONTokener.dehexchar(string.charAt(i + 1));
|
||||
int e = JSONTokener.dehexchar(string.charAt(i + 2));
|
||||
if (d >= 0 && e >= 0) {
|
||||
c = (char)(d * 16 + e);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
89
src/org/json/CookieList.java
Normal file
89
src/org/json/CookieList.java
Normal file
@ -0,0 +1,89 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie list string to a JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class CookieList {
|
||||
|
||||
/**
|
||||
* Convert a cookie list into a JSONObject. A cookie list is a sequence
|
||||
* of name/value pairs. The names are separated from the values by '='.
|
||||
* The pairs are separated by ';'. The names and the values
|
||||
* will be unescaped, possibly converting '+' and '%' sequences.
|
||||
*
|
||||
* To add a cookie to a cooklist,
|
||||
* cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
||||
* cookieJSONObject.getString("value"));
|
||||
* @param string A cookie list string
|
||||
* @return A JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
JSONTokener x = new JSONTokener(string);
|
||||
while (x.more()) {
|
||||
String name = Cookie.unescape(x.nextTo('='));
|
||||
x.next('=');
|
||||
jo.put(name, Cookie.unescape(x.nextTo(';')));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a cookie list. A cookie list is a sequence
|
||||
* of name/value pairs. The names are separated from the values by '='.
|
||||
* The pairs are separated by ';'. The characters '%', '+', '=', and ';'
|
||||
* in the names and values are replaced by "%hh".
|
||||
* @param jo A JSONObject
|
||||
* @return A cookie list string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
boolean b = false;
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!jo.isNull(string)) {
|
||||
if (b) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(Cookie.escape(string));
|
||||
sb.append("=");
|
||||
sb.append(Cookie.escape(jo.getString(string)));
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
163
src/org/json/HTTP.java
Normal file
163
src/org/json/HTTP.java
Normal file
@ -0,0 +1,163 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert an HTTP header to a JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTP {
|
||||
|
||||
/** Carriage return/line feed. */
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Convert an HTTP header string into a JSONObject. It can be a request
|
||||
* header or a response header. A request header will contain
|
||||
* <pre>{
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }</pre>
|
||||
* A response header will contain
|
||||
* <pre>{
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }</pre>
|
||||
* In addition, the other parameters in the header will be captured, using
|
||||
* the HTTP field names as JSON names, so that <pre>
|
||||
* Date: Sun, 26 May 2002 18:06:04 GMT
|
||||
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
|
||||
* Cache-Control: no-cache</pre>
|
||||
* become
|
||||
* <pre>{...
|
||||
* Date: "Sun, 26 May 2002 18:06:04 GMT",
|
||||
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
|
||||
* "Cache-Control": "no-cache",
|
||||
* ...}</pre>
|
||||
* It does no further checking or conversion. It does not parse dates.
|
||||
* It does not do '%' transforms on URLs.
|
||||
* @param string An HTTP header string.
|
||||
* @return A JSONObject containing the elements and attributes
|
||||
* of the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
HTTPTokener x = new HTTPTokener(string);
|
||||
String token;
|
||||
|
||||
token = x.nextToken();
|
||||
if (token.toUpperCase().startsWith("HTTP")) {
|
||||
|
||||
// Response
|
||||
|
||||
jo.put("HTTP-Version", token);
|
||||
jo.put("Status-Code", x.nextToken());
|
||||
jo.put("Reason-Phrase", x.nextTo('\0'));
|
||||
x.next();
|
||||
|
||||
} else {
|
||||
|
||||
// Request
|
||||
|
||||
jo.put("Method", token);
|
||||
jo.put("Request-URI", x.nextToken());
|
||||
jo.put("HTTP-Version", x.nextToken());
|
||||
}
|
||||
|
||||
// Fields
|
||||
|
||||
while (x.more()) {
|
||||
String name = x.nextTo(':');
|
||||
x.next(':');
|
||||
jo.put(name, x.nextTo('\0'));
|
||||
x.next();
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into an HTTP header. A request header must contain
|
||||
* <pre>{
|
||||
* Method: "POST" (for example),
|
||||
* "Request-URI": "/" (for example),
|
||||
* "HTTP-Version": "HTTP/1.1" (for example)
|
||||
* }</pre>
|
||||
* A response header must contain
|
||||
* <pre>{
|
||||
* "HTTP-Version": "HTTP/1.1" (for example),
|
||||
* "Status-Code": "200" (for example),
|
||||
* "Reason-Phrase": "OK" (for example)
|
||||
* }</pre>
|
||||
* Any other members of the JSONObject will be output as HTTP fields.
|
||||
* The result will end with two CRLF pairs.
|
||||
* @param jo A JSONObject
|
||||
* @return An HTTP header string.
|
||||
* @throws JSONException if the object does not contain enough
|
||||
* information.
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Status-Code"));
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("Reason-Phrase"));
|
||||
} else if (jo.has("Method") && jo.has("Request-URI")) {
|
||||
sb.append(jo.getString("Method"));
|
||||
sb.append(' ');
|
||||
sb.append('"');
|
||||
sb.append(jo.getString("Request-URI"));
|
||||
sb.append('"');
|
||||
sb.append(' ');
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
} else {
|
||||
throw new JSONException("Not enough material for an HTTP header.");
|
||||
}
|
||||
sb.append(CRLF);
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) &&
|
||||
!"Reason-Phrase".equals(string) && !"Method".equals(string) &&
|
||||
!"Request-URI".equals(string) && !jo.isNull(string)) {
|
||||
sb.append(string);
|
||||
sb.append(": ");
|
||||
sb.append(jo.getString(string));
|
||||
sb.append(CRLF);
|
||||
}
|
||||
}
|
||||
sb.append(CRLF);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
77
src/org/json/HTTPTokener.java
Normal file
77
src/org/json/HTTPTokener.java
Normal file
@ -0,0 +1,77 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The HTTPTokener extends the JSONTokener to provide additional methods
|
||||
* for the parsing of HTTP headers.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class HTTPTokener extends JSONTokener {
|
||||
|
||||
/**
|
||||
* Construct an HTTPTokener from a string.
|
||||
* @param string A source string.
|
||||
*/
|
||||
public HTTPTokener(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next token or string. This is used in parsing HTTP headers.
|
||||
* @throws JSONException
|
||||
* @return A String.
|
||||
*/
|
||||
public String nextToken() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if (c == '"' || c == '\'') {
|
||||
q = c;
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c < ' ') {
|
||||
throw syntaxError("Unterminated string.");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (c == 0 || Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
}
|
977
src/org/json/JSONArray.java
Normal file
977
src/org/json/JSONArray.java
Normal file
@ -0,0 +1,977 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A JSONArray is an ordered sequence of values. Its external text form is a
|
||||
* string wrapped in square brackets with commas separating the values. The
|
||||
* internal form is an object having <code>get</code> and <code>opt</code>
|
||||
* methods for accessing the values by index, and <code>put</code> methods for
|
||||
* adding or replacing values. The values can be any of these types:
|
||||
* <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
|
||||
* <code>Number</code>, <code>String</code>, or the
|
||||
* <code>JSONObject.NULL object</code>.
|
||||
* <p>
|
||||
* The constructor can convert a JSON text into a Java object. The
|
||||
* <code>toString</code> method converts to JSON text.
|
||||
* <p>
|
||||
* A <code>get</code> method returns a value if one can be found, and throws an
|
||||
* exception if one cannot be found. An <code>opt</code> method returns a
|
||||
* default value instead of throwing an exception, and so is useful for
|
||||
* obtaining optional values.
|
||||
* <p>
|
||||
* The generic <code>get()</code> and <code>opt()</code> methods return an
|
||||
* object which you can cast or query for type. There are also typed
|
||||
* <code>get</code> and <code>opt</code> methods that do type checking and type
|
||||
* coercion for you.
|
||||
* <p>
|
||||
* The texts produced by the <code>toString</code> methods strictly conform to
|
||||
* JSON syntax rules. The constructors are more forgiving in the texts they will
|
||||
* accept:
|
||||
* <ul>
|
||||
* <li>An extra <code>,</code> <small>(comma)</small> may appear just
|
||||
* before the closing bracket.</li>
|
||||
* <li>The <code>null</code> value will be inserted when there is <code>,</code>
|
||||
* <small>(comma)</small> elision.</li>
|
||||
* <li>Strings may be quoted with <code>'</code> <small>(single
|
||||
* quote)</small>.</li>
|
||||
* <li>Strings do not need to be quoted at all if they do not begin with a quote
|
||||
* or single quote, and if they do not contain leading or trailing spaces, and
|
||||
* if they do not contain any of these characters:
|
||||
* <code>{ } [ ] / \ : , #</code> and if they do not look like numbers and
|
||||
* if they are not the reserved words <code>true</code>, <code>false</code>, or
|
||||
* <code>null</code>.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONArray {
|
||||
|
||||
/**
|
||||
* The arrayList where the JSONArray's properties are kept.
|
||||
*/
|
||||
private final ArrayList<Object> myArrayList;
|
||||
|
||||
/**
|
||||
* Construct an empty JSONArray.
|
||||
*/
|
||||
public JSONArray() {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a JSONTokener.
|
||||
*
|
||||
* @param x
|
||||
* A JSONTokener
|
||||
* @throws JSONException
|
||||
* If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(JSONTokener x) throws JSONException {
|
||||
this();
|
||||
if (x.nextClean() != '[') {
|
||||
throw x.syntaxError("A JSONArray text must start with '['");
|
||||
}
|
||||
if (x.nextClean() != ']') {
|
||||
x.back();
|
||||
for (;;) {
|
||||
if (x.nextClean() == ',') {
|
||||
x.back();
|
||||
this.myArrayList.add(JSONObject.NULL);
|
||||
} else {
|
||||
x.back();
|
||||
this.myArrayList.add(x.nextValue());
|
||||
}
|
||||
switch (x.nextClean()) {
|
||||
case ',':
|
||||
if (x.nextClean() == ']') {
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
break;
|
||||
case ']':
|
||||
return;
|
||||
default:
|
||||
throw x.syntaxError("Expected a ',' or ']'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a source JSON text.
|
||||
*
|
||||
* @param source
|
||||
* A string that begins with <code>[</code> <small>(left
|
||||
* bracket)</small> and ends with <code>]</code>
|
||||
* <small>(right bracket)</small>.
|
||||
* @throws JSONException
|
||||
* If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(String source) throws JSONException {
|
||||
this(new JSONTokener(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a Collection.
|
||||
*
|
||||
* @param collection
|
||||
* A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<Object> collection) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
if (collection != null) {
|
||||
Iterator<Object> iter = collection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
this.myArrayList.add(JSONObject.wrap(iter.next()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from an array
|
||||
*
|
||||
* @throws JSONException
|
||||
* If not an array.
|
||||
*/
|
||||
public JSONArray(Object array) throws JSONException {
|
||||
this();
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
}
|
||||
} else {
|
||||
throw new JSONException(
|
||||
"JSONArray initial value should be a string or collection or array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index.
|
||||
*/
|
||||
public Object get(int index) throws JSONException {
|
||||
Object object = this.opt(index);
|
||||
if (object == null) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boolean value associated with an index. The string values "true"
|
||||
* and "false" are converted to boolean.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index or if the value is not
|
||||
* convertible to boolean.
|
||||
*/
|
||||
public boolean getBoolean(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object.equals(Boolean.FALSE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("false"))) {
|
||||
return false;
|
||||
} else if (object.equals(Boolean.TRUE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("true"))) {
|
||||
return true;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a boolean.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the double value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value cannot be converted
|
||||
* to a number.
|
||||
*/
|
||||
public double getDouble(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).doubleValue()
|
||||
: Double.parseDouble((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value is not a number.
|
||||
*/
|
||||
public int getInt(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).intValue()
|
||||
: Integer.parseInt((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONArray associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A JSONArray value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index. or if the value is not a
|
||||
* JSONArray
|
||||
*/
|
||||
public JSONArray getJSONArray(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof JSONArray) {
|
||||
return (JSONArray) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONArray.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONObject associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @return A JSONObject value.
|
||||
* @throws JSONException
|
||||
* If there is no value for the index or if the value is not a
|
||||
* JSONObject
|
||||
*/
|
||||
public JSONObject getJSONObject(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof JSONObject) {
|
||||
return (JSONObject) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONObject.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the long value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException
|
||||
* If the key is not found or if the value cannot be converted
|
||||
* to a number.
|
||||
*/
|
||||
public long getLong(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).longValue()
|
||||
: Long.parseLong((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A string value.
|
||||
* @throws JSONException
|
||||
* If there is no string value for the index.
|
||||
*/
|
||||
public String getString(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
if (object instanceof String) {
|
||||
return (String) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] not a string.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the value is null.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return true if the value at the index is null, or if there is no value.
|
||||
*/
|
||||
public boolean isNull(int index) {
|
||||
return JSONObject.NULL.equals(this.opt(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a string from the contents of this JSONArray. The
|
||||
* <code>separator</code> string is inserted between each element. Warning:
|
||||
* This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param separator
|
||||
* A string that will be inserted between the elements.
|
||||
* @return a string.
|
||||
* @throws JSONException
|
||||
* If the array contains an invalid number.
|
||||
*/
|
||||
public String join(String separator) throws JSONException {
|
||||
int len = this.length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(separator);
|
||||
}
|
||||
sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of elements in the JSONArray, included nulls.
|
||||
*
|
||||
* @return The length (or size).
|
||||
*/
|
||||
public int length() {
|
||||
return this.myArrayList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional object value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object value, or null if there is no object at that index.
|
||||
*/
|
||||
public Object opt(int index) {
|
||||
return (index < 0 || index >= this.length()) ? null : this.myArrayList
|
||||
.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns false
|
||||
* if there is no value at that index, or if the value is not Boolean.TRUE
|
||||
* or the String "true".
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index) {
|
||||
return this.optBoolean(index, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns the
|
||||
* defaultValue if there is no value at that index or if it is not a Boolean
|
||||
* or the String "true" or "false" (case insensitive).
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* A boolean default.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index, boolean defaultValue) {
|
||||
try {
|
||||
return this.getBoolean(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. NaN is returned
|
||||
* if there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index) {
|
||||
return this.optDouble(index, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index, double defaultValue) {
|
||||
try {
|
||||
return this.getDouble(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. Zero is returned if
|
||||
* there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index) {
|
||||
return this.optInt(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. The defaultValue is
|
||||
* returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index, int defaultValue) {
|
||||
try {
|
||||
return this.getInt(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONArray associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @return A JSONArray value, or null if the index has no value, or if the
|
||||
* value is not a JSONArray.
|
||||
*/
|
||||
public JSONArray optJSONArray(int index) {
|
||||
Object o = this.opt(index);
|
||||
return o instanceof JSONArray ? (JSONArray) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONObject associated with an index. Null is returned if
|
||||
* the key is not found, or null if the index has no value, or if the value
|
||||
* is not a JSONObject.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A JSONObject value.
|
||||
*/
|
||||
public JSONObject optJSONObject(int index) {
|
||||
Object o = this.opt(index);
|
||||
return o instanceof JSONObject ? (JSONObject) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. Zero is returned if
|
||||
* there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index) {
|
||||
return this.optLong(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. The defaultValue is
|
||||
* returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index, long defaultValue) {
|
||||
try {
|
||||
return this.getLong(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string value associated with an index. It returns an
|
||||
* empty string if there is no value at that index. If the value is not a
|
||||
* string and is not null, then it is coverted to a string.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index) {
|
||||
return this.optString(index, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string associated with an index. The defaultValue is
|
||||
* returned if the key is not found.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index, String defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
return JSONObject.NULL.equals(object) ? defaultValue : object
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a boolean value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A boolean value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(boolean value) {
|
||||
this.put(value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param value
|
||||
* A Collection value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Collection<Object> value) {
|
||||
this.put(new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A double value.
|
||||
* @throws JSONException
|
||||
* if the value is not finite.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(double value) throws JSONException {
|
||||
Double d = new Double(value);
|
||||
JSONObject.testValidity(d);
|
||||
this.put(d);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an int value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* An int value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(int value) {
|
||||
this.put(new Integer(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an long value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* A long value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(long value) {
|
||||
this.put(new Long(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject which
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param value
|
||||
* A Map value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Map<String, Object> value) {
|
||||
this.put(new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value. This increases the array's length by one.
|
||||
*
|
||||
* @param value
|
||||
* An object value. The value should be a Boolean, Double,
|
||||
* Integer, JSONArray, JSONObject, Long, or String, or the
|
||||
* JSONObject.NULL object.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Object value) {
|
||||
this.myArrayList.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a boolean value in the JSONArray. If the index is greater
|
||||
* than the length of the JSONArray, then null elements will be added as
|
||||
* necessary to pad it out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A boolean value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, boolean value) throws JSONException {
|
||||
this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A Collection value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is not finite.
|
||||
*/
|
||||
public JSONArray put(int index, Collection<Object> value) throws JSONException {
|
||||
this.put(index, new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a double value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A double value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is not finite.
|
||||
*/
|
||||
public JSONArray put(int index, double value) throws JSONException {
|
||||
this.put(index, new Double(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an int value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* An int value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, int value) throws JSONException {
|
||||
this.put(index, new Integer(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a long value. If the index is greater than the length of
|
||||
* the JSONArray, then null elements will be added as necessary to pad it
|
||||
* out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* A long value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, long value) throws JSONException {
|
||||
this.put(index, new Long(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject that
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* The Map value.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the the value is an invalid
|
||||
* number.
|
||||
*/
|
||||
public JSONArray put(int index, Map<String, Object> value) throws JSONException {
|
||||
this.put(index, new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an object value in the JSONArray. If the index is greater
|
||||
* than the length of the JSONArray, then null elements will be added as
|
||||
* necessary to pad it out.
|
||||
*
|
||||
* @param index
|
||||
* The subscript.
|
||||
* @param value
|
||||
* The value to put into the array. The value should be a
|
||||
* Boolean, Double, Integer, JSONArray, JSONObject, Long, or
|
||||
* String, or the JSONObject.NULL object.
|
||||
* @return this.
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the the value is an invalid
|
||||
* number.
|
||||
*/
|
||||
public JSONArray put(int index, Object value) throws JSONException {
|
||||
JSONObject.testValidity(value);
|
||||
if (index < 0) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
if (index < this.length()) {
|
||||
this.myArrayList.set(index, value);
|
||||
} else {
|
||||
while (index != this.length()) {
|
||||
this.put(JSONObject.NULL);
|
||||
}
|
||||
this.put(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an index and close the hole.
|
||||
*
|
||||
* @param index
|
||||
* The index of the element to be removed.
|
||||
* @return The value that was associated with the index, or null if there
|
||||
* was no value.
|
||||
*/
|
||||
public Object remove(int index) {
|
||||
return index >= 0 && index < this.length()
|
||||
? this.myArrayList.remove(index)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two JSONArrays are similar.
|
||||
* They must contain similar sequences.
|
||||
*
|
||||
* @param other The other JSONArray
|
||||
* @return true if they are equal
|
||||
*/
|
||||
public boolean similar(Object other) {
|
||||
if (!(other instanceof JSONArray)) {
|
||||
return false;
|
||||
}
|
||||
int len = this.length();
|
||||
if (len != ((JSONArray)other).length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
Object valueThis = this.get(i);
|
||||
Object valueOther = ((JSONArray)other).get(i);
|
||||
if (valueThis instanceof JSONObject) {
|
||||
if (!((JSONObject)valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (valueThis instanceof JSONArray) {
|
||||
if (!((JSONArray)valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!valueThis.equals(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject by combining a JSONArray of names with the values of
|
||||
* this JSONArray.
|
||||
*
|
||||
* @param names
|
||||
* A JSONArray containing a list of key strings. These will be
|
||||
* paired with the values.
|
||||
* @return A JSONObject, or null if there are no names or if this JSONArray
|
||||
* has no values.
|
||||
* @throws JSONException
|
||||
* If any of the names are null.
|
||||
*/
|
||||
public JSONObject toJSONObject(JSONArray names) throws JSONException {
|
||||
if (names == null || names.length() == 0 || this.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jo = new JSONObject();
|
||||
for (int i = 0; i < names.length(); i += 1) {
|
||||
jo.put(names.getString(i), this.opt(i));
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSON text of this JSONArray. For compactness, no unnecessary
|
||||
* whitespace is added. If it is not possible to produce a syntactically
|
||||
* correct JSON text then null will be returned instead. This could occur if
|
||||
* the array contains an invalid number.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* array.
|
||||
*/
|
||||
public String toString() {
|
||||
try {
|
||||
return this.toString(0);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a prettyprinted JSON text of this JSONArray. Warning: This method
|
||||
* assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* object, beginning with <code>[</code> <small>(left
|
||||
* bracket)</small> and ending with <code>]</code>
|
||||
* <small>(right bracket)</small>.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public String toString(int indentFactor) throws JSONException {
|
||||
StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Writer write(Writer writer) throws JSONException {
|
||||
return this.write(writer, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
* @param indent
|
||||
* The indention of the top level.
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
Writer write(Writer writer, int indentFactor, int indent)
|
||||
throws JSONException {
|
||||
try {
|
||||
boolean commanate = false;
|
||||
int length = this.length();
|
||||
writer.write('[');
|
||||
|
||||
if (length == 1) {
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(0),
|
||||
indentFactor, indent);
|
||||
} else if (length != 0) {
|
||||
final int newindent = indent + indentFactor;
|
||||
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
if (commanate) {
|
||||
writer.write(',');
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, newindent);
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(i),
|
||||
indentFactor, newindent);
|
||||
commanate = true;
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, indent);
|
||||
}
|
||||
writer.write(']');
|
||||
return writer;
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
}
|
43
src/org/json/JSONException.java
Normal file
43
src/org/json/JSONException.java
Normal file
@ -0,0 +1,43 @@
|
||||
package org.json;
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONException extends RuntimeException {
|
||||
private static final long serialVersionUID = 0;
|
||||
private Throwable cause;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
* @param cause The cause.
|
||||
*/
|
||||
public JSONException(Throwable cause) {
|
||||
super(cause.getMessage());
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*
|
||||
* @return the cause of this exception or null if the cause is nonexistent
|
||||
* or unknown.
|
||||
*/
|
||||
@Override
|
||||
public Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
}
|
467
src/org/json/JSONML.java
Normal file
467
src/org/json/JSONML.java
Normal file
@ -0,0 +1,467 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2008 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or
|
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
||||
* the JsonML transform.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONML {
|
||||
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static Object parse(
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja
|
||||
) throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
String closeTag = null;
|
||||
int i;
|
||||
JSONArray newja = null;
|
||||
JSONObject newjo = null;
|
||||
Object token;
|
||||
String tagName = null;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
|
||||
while (true) {
|
||||
if (!x.more()) {
|
||||
throw x.syntaxError("Bad XML");
|
||||
}
|
||||
token = x.nextContent();
|
||||
if (token == XML.LT) {
|
||||
token = x.nextToken();
|
||||
if (token instanceof Character) {
|
||||
if (token == XML.SLASH) {
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw new JSONException(
|
||||
"Expected a closing name instead of '" +
|
||||
token + "'.");
|
||||
}
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return token;
|
||||
} else if (token == XML.BANG) {
|
||||
|
||||
// <!
|
||||
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
} else {
|
||||
x.back();
|
||||
}
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if (token.equals("CDATA") && x.next() == '[') {
|
||||
if (ja != null) {
|
||||
ja.put(x.nextCDATA());
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == XML.LT) {
|
||||
i += 1;
|
||||
} else if (token == XML.GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
}
|
||||
} else if (token == XML.QUEST) {
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||
}
|
||||
tagName = (String)token;
|
||||
newja = new JSONArray();
|
||||
newjo = new JSONObject();
|
||||
if (arrayForm) {
|
||||
newja.put(tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newja);
|
||||
}
|
||||
} else {
|
||||
newjo.put("tagName", tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newjo);
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
for (;;) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (!(token instanceof String)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
attribute = (String)token;
|
||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
|
||||
throw x.syntaxError("Reserved attribute.");
|
||||
}
|
||||
token = x.nextToken();
|
||||
if (token == XML.EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
}
|
||||
}
|
||||
if (arrayForm && newjo.length() > 0) {
|
||||
newja.put(newjo);
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
if (token == XML.SLASH) {
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String)parse(x, arrayForm, newja);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError("Mismatched '" + tagName +
|
||||
"' and '" + closeTag + "'");
|
||||
}
|
||||
tagName = null;
|
||||
if (!arrayForm && newja.length() > 0) {
|
||||
newjo.put("childNodes", newja);
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
} else {
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? XML.stringToValue((String)token)
|
||||
: token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return toJSONArray(new XMLTokener(string));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
return toJSONObject(new XMLTokener(string));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
||||
* @param ja A JSONArray.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
int i;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
// Emit <tagName
|
||||
|
||||
tagName = ja.getString(0);
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
object = ja.opt(1);
|
||||
if (object instanceof JSONObject) {
|
||||
i = 2;
|
||||
jo = (JSONObject)object;
|
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
// Emit content in body
|
||||
|
||||
length = ja.length();
|
||||
if (i >= length) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
do {
|
||||
object = ja.get(i);
|
||||
i += 1;
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject)object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray)object));
|
||||
}
|
||||
}
|
||||
} while (i < length);
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject.
|
||||
* The JSONObject must contain a "tagName" property. If it has children,
|
||||
* then it must have a "childNodes" property containing an array of objects.
|
||||
* The other properties are attributes with string values.
|
||||
* @param jo A JSONObject.
|
||||
* @return An XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
//Emit <tagName
|
||||
|
||||
tagName = jo.optString("tagName");
|
||||
if (tagName == null) {
|
||||
return XML.escape(jo.toString());
|
||||
}
|
||||
XML.noSpace(tagName);
|
||||
tagName = XML.escape(tagName);
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
|
||||
//Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
if (!"tagName".equals(key) && !"childNodes".equals(key)) {
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Emit content in body
|
||||
|
||||
ja = jo.optJSONArray("childNodes");
|
||||
if (ja == null) {
|
||||
sb.append('/');
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append('>');
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
object = ja.get(i);
|
||||
if (object != null) {
|
||||
if (object instanceof String) {
|
||||
sb.append(XML.escape(object.toString()));
|
||||
} else if (object instanceof JSONObject) {
|
||||
sb.append(toString((JSONObject)object));
|
||||
} else if (object instanceof JSONArray) {
|
||||
sb.append(toString((JSONArray)object));
|
||||
} else {
|
||||
sb.append(object.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append('<');
|
||||
sb.append('/');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
1683
src/org/json/JSONObject.java
Normal file
1683
src/org/json/JSONObject.java
Normal file
File diff suppressed because it is too large
Load Diff
18
src/org/json/JSONString.java
Normal file
18
src/org/json/JSONString.java
Normal file
@ -0,0 +1,18 @@
|
||||
package org.json;
|
||||
/**
|
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
||||
* method so that a class can change the behavior of
|
||||
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
|
||||
* and <code>JSONWriter.value(</code>Object<code>)</code>. The
|
||||
* <code>toJSONString</code> method will be used instead of the default behavior
|
||||
* of using the Object's <code>toString()</code> method and quoting the result.
|
||||
*/
|
||||
public interface JSONString {
|
||||
/**
|
||||
* The <code>toJSONString</code> method allows a class to produce its own JSON
|
||||
* serialization.
|
||||
*
|
||||
* @return A strictly syntactically correct JSON text.
|
||||
*/
|
||||
public String toJSONString();
|
||||
}
|
78
src/org/json/JSONStringer.java
Normal file
78
src/org/json/JSONStringer.java
Normal file
@ -0,0 +1,78 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* JSONStringer provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONStringer can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONStringer instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting cascade style. For example, <pre>
|
||||
* myString = new JSONStringer()
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject()
|
||||
* .toString();</pre> which produces the string <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONStringer adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2008-09-18
|
||||
*/
|
||||
public class JSONStringer extends JSONWriter {
|
||||
/**
|
||||
* Make a fresh JSONStringer. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONStringer() {
|
||||
super(new StringWriter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON text. This method is used to obtain the product of the
|
||||
* JSONStringer instance. It will return <code>null</code> if there was a
|
||||
* problem in the construction of the JSON text (such as the calls to
|
||||
* <code>array</code> were not properly balanced with calls to
|
||||
* <code>endArray</code>).
|
||||
* @return The JSON text.
|
||||
*/
|
||||
public String toString() {
|
||||
return this.mode == 'd' ? this.writer.toString() : null;
|
||||
}
|
||||
}
|
446
src/org/json/JSONTokener.java
Normal file
446
src/org/json/JSONTokener.java
Normal file
@ -0,0 +1,446 @@
|
||||
package org.json;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A JSONTokener takes a source string and extracts characters and tokens from
|
||||
* it. It is used by the JSONObject and JSONArray constructors to parse
|
||||
* JSON source strings.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener {
|
||||
|
||||
private long character;
|
||||
private boolean eof;
|
||||
private long index;
|
||||
private long line;
|
||||
private char previous;
|
||||
private Reader reader;
|
||||
private boolean usePrevious;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader.
|
||||
*
|
||||
* @param reader A reader.
|
||||
*/
|
||||
public JSONTokener(Reader reader) {
|
||||
this.reader = reader.markSupported()
|
||||
? reader
|
||||
: new BufferedReader(reader);
|
||||
this.eof = false;
|
||||
this.usePrevious = false;
|
||||
this.previous = 0;
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.line = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream.
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) throws JSONException {
|
||||
this(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a string.
|
||||
*
|
||||
* @param s A source string.
|
||||
*/
|
||||
public JSONTokener(String s) {
|
||||
this(new StringReader(s));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Back up one character. This provides a sort of lookahead capability,
|
||||
* so that you can test for a digit or letter before attempting to parse
|
||||
* the next number or identifier.
|
||||
*/
|
||||
public void back() throws JSONException {
|
||||
if (this.usePrevious || this.index <= 0) {
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
this.index -= 1;
|
||||
this.character -= 1;
|
||||
this.usePrevious = true;
|
||||
this.eof = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
* @param c A character between '0' and '9' or between 'A' and 'F' or
|
||||
* between 'a' and 'f'.
|
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||
*/
|
||||
public static int dehexchar(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return c - ('A' - 10);
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean end() {
|
||||
return this.eof && !this.usePrevious;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the source string still contains characters that next()
|
||||
* can consume.
|
||||
* @return true if not yet at the end of the source.
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
this.next();
|
||||
if (this.end()) {
|
||||
return false;
|
||||
}
|
||||
this.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next character in the source string.
|
||||
*
|
||||
* @return The next character, or 0 if past the end of the source string.
|
||||
*/
|
||||
public char next() throws JSONException {
|
||||
int c;
|
||||
if (this.usePrevious) {
|
||||
this.usePrevious = false;
|
||||
c = this.previous;
|
||||
} else {
|
||||
try {
|
||||
c = this.reader.read();
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
|
||||
if (c <= 0) { // End of stream
|
||||
this.eof = true;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
this.index += 1;
|
||||
if (this.previous == '\r') {
|
||||
this.line += 1;
|
||||
this.character = c == '\n' ? 0 : 1;
|
||||
} else if (c == '\n') {
|
||||
this.line += 1;
|
||||
this.character = 0;
|
||||
} else {
|
||||
this.character += 1;
|
||||
}
|
||||
this.previous = (char) c;
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified
|
||||
* character.
|
||||
* @param c The character to match.
|
||||
* @return The character.
|
||||
* @throws JSONException if the character does not match.
|
||||
*/
|
||||
public char next(char c) throws JSONException {
|
||||
char n = this.next();
|
||||
if (n != c) {
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" +
|
||||
n + "'");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next n characters.
|
||||
*
|
||||
* @param n The number of characters to take.
|
||||
* @return A string of n characters.
|
||||
* @throws JSONException
|
||||
* Substring bounds error if there are not
|
||||
* n characters remaining in the source string.
|
||||
*/
|
||||
public String next(int n) throws JSONException {
|
||||
if (n == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char[] chars = new char[n];
|
||||
int pos = 0;
|
||||
|
||||
while (pos < n) {
|
||||
chars[pos] = this.next();
|
||||
if (this.end()) {
|
||||
throw this.syntaxError("Substring bounds error");
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next char in the string, skipping whitespace.
|
||||
* @throws JSONException
|
||||
* @return A character, or 0 if there are no more characters.
|
||||
*/
|
||||
public char nextClean() throws JSONException {
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == 0 || c > ' ') {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the characters up to the next close quote character.
|
||||
* Backslash processing is done. The formal JSON format does not
|
||||
* allow strings in single quotes, but an implementation is allowed to
|
||||
* accept them.
|
||||
* @param quote The quoting character, either
|
||||
* <code>"</code> <small>(double quote)</small> or
|
||||
* <code>'</code> <small>(single quote)</small>.
|
||||
* @return A String.
|
||||
* @throws JSONException Unterminated string.
|
||||
*/
|
||||
public String nextString(char quote) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
throw this.syntaxError("Unterminated string");
|
||||
case '\\':
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
sb.append((char)Integer.parseInt(this.next(4), 16));
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
sb.append(c);
|
||||
break;
|
||||
default:
|
||||
throw this.syntaxError("Illegal escape.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (c == quote) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the
|
||||
* end of line, whichever comes first.
|
||||
* @param delimiter A delimiter character.
|
||||
* @return A string.
|
||||
*/
|
||||
public String nextTo(char delimiter) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including one of the specified delimiter
|
||||
* characters or the end of line, whichever comes first.
|
||||
* @param delimiters A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
*/
|
||||
public String nextTo(String delimiters) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
if (delimiters.indexOf(c) >= 0 || c == 0 ||
|
||||
c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be a Boolean, Double, Integer,
|
||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
* @throws JSONException If syntax error.
|
||||
*
|
||||
* @return An object.
|
||||
*/
|
||||
public Object nextValue() throws JSONException {
|
||||
char c = this.nextClean();
|
||||
String string;
|
||||
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\'':
|
||||
return this.nextString(c);
|
||||
case '{':
|
||||
this.back();
|
||||
return new JSONObject(this);
|
||||
case '[':
|
||||
this.back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle unquoted text. This could be the values true, false, or
|
||||
* null, or it can be a number. An implementation (such as this one)
|
||||
* is allowed to also accept non-standard forms.
|
||||
*
|
||||
* Accumulate characters until we reach the end of the text or a
|
||||
* formatting character.
|
||||
*/
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
|
||||
sb.append(c);
|
||||
c = this.next();
|
||||
}
|
||||
this.back();
|
||||
|
||||
string = sb.toString().trim();
|
||||
if ("".equals(string)) {
|
||||
throw this.syntaxError("Missing value");
|
||||
}
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip characters until the next character is the requested character.
|
||||
* If the requested character is not found, no characters are skipped.
|
||||
* @param to A character to skip to.
|
||||
* @return The requested character, or zero if the requested character
|
||||
* is not found.
|
||||
*/
|
||||
public char skipTo(char to) throws JSONException {
|
||||
char c;
|
||||
try {
|
||||
long startIndex = this.index;
|
||||
long startCharacter = this.character;
|
||||
long startLine = this.line;
|
||||
this.reader.mark(1000000);
|
||||
do {
|
||||
c = this.next();
|
||||
if (c == 0) {
|
||||
this.reader.reset();
|
||||
this.index = startIndex;
|
||||
this.character = startCharacter;
|
||||
this.line = startLine;
|
||||
return c;
|
||||
}
|
||||
} while (c != to);
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
this.back();
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message The error message.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(String message) {
|
||||
return new JSONException(message + this.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
* @return " at {index} [character {character} line {line}]"
|
||||
*/
|
||||
public String toString() {
|
||||
return " at " + this.index + " [character " + this.character + " line " +
|
||||
this.line + "]";
|
||||
}
|
||||
}
|
327
src/org/json/JSONWriter.java
Normal file
327
src/org/json/JSONWriter.java
Normal file
@ -0,0 +1,327 @@
|
||||
package org.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JSONWriter provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONWriter can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONWriter instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting a cascade style. For example, <pre>
|
||||
* new JSONWriter(myWriter)
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject();</pre> which writes <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2011-11-24
|
||||
*/
|
||||
public class JSONWriter {
|
||||
private static final int maxdepth = 200;
|
||||
|
||||
/**
|
||||
* The comma flag determines if a comma should be output before the next
|
||||
* value.
|
||||
*/
|
||||
private boolean comma;
|
||||
|
||||
/**
|
||||
* The current mode. Values:
|
||||
* 'a' (array),
|
||||
* 'd' (done),
|
||||
* 'i' (initial),
|
||||
* 'k' (key),
|
||||
* 'o' (object).
|
||||
*/
|
||||
protected char mode;
|
||||
|
||||
/**
|
||||
* The object/array stack.
|
||||
*/
|
||||
private final JSONObject stack[];
|
||||
|
||||
/**
|
||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||
*/
|
||||
private int top;
|
||||
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected Writer writer;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(Writer w) {
|
||||
this.comma = false;
|
||||
this.mode = 'i';
|
||||
this.stack = new JSONObject[maxdepth];
|
||||
this.top = 0;
|
||||
this.writer = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value.
|
||||
* @param string A string value.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
private JSONWriter append(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null pointer");
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
try {
|
||||
if (this.comma && this.mode == 'a') {
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(string);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if (this.mode == 'o') {
|
||||
this.mode = 'k';
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Value out of sequence.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new array. All values until the balancing
|
||||
* <code>endArray</code> will be appended to this array. The
|
||||
* <code>endArray</code> method must be called to mark the array's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter array() throws JSONException {
|
||||
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
|
||||
this.push(null);
|
||||
this.append("[");
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced array.");
|
||||
}
|
||||
|
||||
/**
|
||||
* End something.
|
||||
* @param mode Mode
|
||||
* @param c Closing character
|
||||
* @return this
|
||||
* @throws JSONException If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(char mode, char c) throws JSONException {
|
||||
if (this.mode != mode) {
|
||||
throw new JSONException(mode == 'a'
|
||||
? "Misplaced endArray."
|
||||
: "Misplaced endObject.");
|
||||
}
|
||||
this.pop(mode);
|
||||
try {
|
||||
this.writer.write(c);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End an array. This method most be called to balance calls to
|
||||
* <code>array</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endArray() throws JSONException {
|
||||
return this.end('a', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* End an object. This method most be called to balance calls to
|
||||
* <code>object</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endObject() throws JSONException {
|
||||
return this.end('k', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key. The key will be associated with the next value. In an
|
||||
* object, every value must be preceded by a key.
|
||||
* @param string A key string.
|
||||
* @return this
|
||||
* @throws JSONException If the key is out of place. For example, keys
|
||||
* do not belong in arrays or if the key is null.
|
||||
*/
|
||||
public JSONWriter key(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null key.");
|
||||
}
|
||||
if (this.mode == 'k') {
|
||||
try {
|
||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
||||
if (this.comma) {
|
||||
this.writer.write(',');
|
||||
}
|
||||
this.writer.write(JSONObject.quote(string));
|
||||
this.writer.write(':');
|
||||
this.comma = false;
|
||||
this.mode = 'o';
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
throw new JSONException("Misplaced key.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin appending a new object. All keys and values until the balancing
|
||||
* <code>endObject</code> will be appended to this object. The
|
||||
* <code>endObject</code> method must be called to mark the object's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter object() throws JSONException {
|
||||
if (this.mode == 'i') {
|
||||
this.mode = 'o';
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
this.append("{");
|
||||
this.push(new JSONObject());
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced object.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pop an array or object scope.
|
||||
* @param c The scope to close.
|
||||
* @throws JSONException If nesting is wrong.
|
||||
*/
|
||||
private void pop(char c) throws JSONException {
|
||||
if (this.top <= 0) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||
if (m != c) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
this.top -= 1;
|
||||
this.mode = this.top == 0
|
||||
? 'd'
|
||||
: this.stack[this.top - 1] == null
|
||||
? 'a'
|
||||
: 'k';
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an array or object scope.
|
||||
* @param jo The scope to open.
|
||||
* @throws JSONException If nesting is too deep.
|
||||
*/
|
||||
private void push(JSONObject jo) throws JSONException {
|
||||
if (this.top >= maxdepth) {
|
||||
throw new JSONException("Nesting too deep.");
|
||||
}
|
||||
this.stack[this.top] = jo;
|
||||
this.mode = jo == null ? 'a' : 'k';
|
||||
this.top += 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append either the value <code>true</code> or the value
|
||||
* <code>false</code>.
|
||||
* @param b A boolean.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(boolean b) throws JSONException {
|
||||
return this.append(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value.
|
||||
* @param d A double.
|
||||
* @return this
|
||||
* @throws JSONException If the number is not finite.
|
||||
*/
|
||||
public JSONWriter value(double d) throws JSONException {
|
||||
return this.value(new Double(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long value.
|
||||
* @param l A long.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(long l) throws JSONException {
|
||||
return this.append(Long.toString(l));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append an object value.
|
||||
* @param object The object to append. It can be null, or a Boolean, Number,
|
||||
* String, JSONObject, or JSONArray, or an object that implements JSONString.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
public JSONWriter value(Object object) throws JSONException {
|
||||
return this.append(JSONObject.valueToString(object));
|
||||
}
|
||||
}
|
372
src/org/json/Kim.java
Normal file
372
src/org/json/Kim.java
Normal file
@ -0,0 +1,372 @@
|
||||
package org.json;
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2013 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Kim makes immutable eight bit Unicode strings. If the MSB of a byte is set,
|
||||
* then the next byte is a continuation byte. The last byte of a character
|
||||
* never has the MSB reset. Every byte that is not the last byte has the MSB
|
||||
* set. Kim stands for "Keep it minimal". A Unicode character is never longer
|
||||
* than 3 bytes. Every byte contributes 7 bits to the character. ASCII is
|
||||
* unmodified.
|
||||
*
|
||||
* Kim UTF-8
|
||||
* one byte U+007F U+007F
|
||||
* two bytes U+3FFF U+07FF
|
||||
* three bytes U+10FFF U+FFFF
|
||||
* four bytes U+10FFFF
|
||||
*
|
||||
* Characters in the ranges U+0800..U+3FFF and U+10000..U+10FFFF will be one
|
||||
* byte smaller when encoded in Kim compared to UTF-8.
|
||||
*
|
||||
* Kim is beneficial when using scripts such as Old South Arabian, Aramaic,
|
||||
* Avestan, Balinese, Batak, Bopomofo, Buginese, Buhid, Carian, Cherokee,
|
||||
* Coptic, Cyrillic, Deseret, Egyptian Hieroglyphs, Ethiopic, Georgian,
|
||||
* Glagolitic, Gothic, Hangul Jamo, Hanunoo, Hiragana, Kanbun, Kaithi,
|
||||
* Kannada, Katakana, Kharoshthi, Khmer, Lao, Lepcha, Limbu, Lycian, Lydian,
|
||||
* Malayalam, Mandaic, Meroitic, Miao, Mongolian, Myanmar, New Tai Lue,
|
||||
* Ol Chiki, Old Turkic, Oriya, Osmanya, Pahlavi, Parthian, Phags-Pa,
|
||||
* Phoenician, Samaritan, Sharada, Sinhala, Sora Sompeng, Tagalog, Tagbanwa,
|
||||
* Takri, Tai Le, Tai Tham, Tamil, Telugu, Thai, Tibetan, Tifinagh, UCAS.
|
||||
*
|
||||
* A kim object can be constructed from an ordinary UTF-16 string, or from a
|
||||
* byte array. A kim object can produce a UTF-16 string.
|
||||
*
|
||||
* As with UTF-8, it is possible to detect character boundaries within a byte
|
||||
* sequence. UTF-8 is one of the world's great inventions. While Kim is more
|
||||
* efficient, it is not clear that it is worth the expense of transition.
|
||||
*
|
||||
* @version 2013-04-18
|
||||
*/
|
||||
public class Kim {
|
||||
|
||||
/**
|
||||
* The byte array containing the kim's content.
|
||||
*/
|
||||
private byte[] bytes = null;
|
||||
|
||||
/**
|
||||
* The kim's hashcode, conforming to Java's hashcode conventions.
|
||||
*/
|
||||
private int hashcode = 0;
|
||||
|
||||
/**
|
||||
* The number of bytes in the kim. The number of bytes can be as much as
|
||||
* three times the number of characters.
|
||||
*/
|
||||
public int length = 0;
|
||||
|
||||
/**
|
||||
* The memoization of toString().
|
||||
*/
|
||||
private String string = null;
|
||||
|
||||
/**
|
||||
* Make a kim from a portion of a byte array.
|
||||
*
|
||||
* @param bytes
|
||||
* A byte array.
|
||||
* @param from
|
||||
* The index of the first byte.
|
||||
* @param thru
|
||||
* The index of the last byte plus one.
|
||||
*/
|
||||
public Kim(byte[] bytes, int from, int thru) {
|
||||
|
||||
// As the bytes are copied into the new kim, a hashcode is computed using a
|
||||
// modified Fletcher code.
|
||||
|
||||
int sum = 1;
|
||||
int value;
|
||||
this.hashcode = 0;
|
||||
this.length = thru - from;
|
||||
if (this.length > 0) {
|
||||
this.bytes = new byte[this.length];
|
||||
for (int at = 0; at < this.length; at += 1) {
|
||||
value = (int) bytes[at + from] & 0xFF;
|
||||
sum += value;
|
||||
this.hashcode += sum;
|
||||
this.bytes[at] = (byte) value;
|
||||
}
|
||||
this.hashcode += sum << 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a kim from a byte array.
|
||||
*
|
||||
* @param bytes
|
||||
* The byte array.
|
||||
* @param length
|
||||
* The number of bytes.
|
||||
*/
|
||||
public Kim(byte[] bytes, int length) {
|
||||
this(bytes, 0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new kim from a substring of an existing kim. The coordinates are
|
||||
* in byte units, not character units.
|
||||
*
|
||||
* @param kim
|
||||
* The source of bytes.
|
||||
* @param from
|
||||
* The point at which to take bytes.
|
||||
* @param thru
|
||||
* The point at which to stop taking bytes.
|
||||
*/
|
||||
public Kim(Kim kim, int from, int thru) {
|
||||
this(kim.bytes, from, thru);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a kim from a string.
|
||||
*
|
||||
* @param string
|
||||
* The string.
|
||||
* @throws JSONException
|
||||
* if surrogate pair mismatch.
|
||||
*/
|
||||
public Kim(String string) throws JSONException {
|
||||
int stringLength = string.length();
|
||||
this.hashcode = 0;
|
||||
this.length = 0;
|
||||
|
||||
// First pass: Determine the length of the kim, allowing for the UTF-16
|
||||
// to UTF-32 conversion, and then the UTF-32 to Kim conversion.
|
||||
|
||||
if (stringLength > 0) {
|
||||
for (int i = 0; i < stringLength; i += 1) {
|
||||
int c = string.charAt(i);
|
||||
if (c <= 0x7F) {
|
||||
this.length += 1;
|
||||
} else if (c <= 0x3FFF) {
|
||||
this.length += 2;
|
||||
} else {
|
||||
if (c >= 0xD800 && c <= 0xDFFF) {
|
||||
i += 1;
|
||||
int d = string.charAt(i);
|
||||
if (c > 0xDBFF || d < 0xDC00 || d > 0xDFFF) {
|
||||
throw new JSONException("Bad UTF16");
|
||||
}
|
||||
}
|
||||
this.length += 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: Allocate a byte array and fill that array with the conversion
|
||||
// while computing the hashcode.
|
||||
|
||||
this.bytes = new byte[length];
|
||||
int at = 0;
|
||||
int b;
|
||||
int sum = 1;
|
||||
for (int i = 0; i < stringLength; i += 1) {
|
||||
int character = string.charAt(i);
|
||||
if (character <= 0x7F) {
|
||||
bytes[at] = (byte) character;
|
||||
sum += character;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
} else if (character <= 0x3FFF) {
|
||||
b = 0x80 | (character >>> 7);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
b = character & 0x7F;
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
} else {
|
||||
if (character >= 0xD800 && character <= 0xDBFF) {
|
||||
i += 1;
|
||||
character = (((character & 0x3FF) << 10) | (string
|
||||
.charAt(i) & 0x3FF)) + 65536;
|
||||
}
|
||||
b = 0x80 | (character >>> 14);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
b = 0x80 | ((character >>> 7) & 0xFF);
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
b = character & 0x7F;
|
||||
bytes[at] = (byte) b;
|
||||
sum += b;
|
||||
this.hashcode += sum;
|
||||
at += 1;
|
||||
}
|
||||
}
|
||||
this.hashcode += sum << 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character at the specified index. The index refers to byte
|
||||
* values and ranges from 0 to length - 1. The index of the next character
|
||||
* is at index + Kim.characterSize(kim.characterAt(index)).
|
||||
*
|
||||
* @param at
|
||||
* the index of the char value. The first character is at 0.
|
||||
* @returns a Unicode character between 0 and 0x10FFFF.
|
||||
* @throws JSONException
|
||||
* if at does not point to a valid character.
|
||||
*/
|
||||
public int characterAt(int at) throws JSONException {
|
||||
int c = get(at);
|
||||
if ((c & 0x80) == 0) {
|
||||
return c;
|
||||
}
|
||||
int character;
|
||||
int c1 = get(at + 1);
|
||||
if ((c1 & 0x80) == 0) {
|
||||
character = ((c & 0x7F) << 7) | c1;
|
||||
if (character > 0x7F) {
|
||||
return character;
|
||||
}
|
||||
} else {
|
||||
int c2 = get(at + 2);
|
||||
character = ((c & 0x7F) << 14) | ((c1 & 0x7F) << 7) | c2;
|
||||
if ((c2 & 0x80) == 0 && character > 0x3FFF && character <= 0x10FFFF
|
||||
&& (character < 0xD800 || character > 0xDFFF)) {
|
||||
return character;
|
||||
}
|
||||
}
|
||||
throw new JSONException("Bad character at " + at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes needed to contain the character in Kim
|
||||
* format.
|
||||
*
|
||||
* @param character
|
||||
* a Unicode character between 0 and 0x10FFFF.
|
||||
* @return 1, 2, or 3
|
||||
* @throws JSONException
|
||||
* if the character is not representable in a kim.
|
||||
*/
|
||||
public static int characterSize(int character) throws JSONException {
|
||||
if (character < 0 || character > 0x10FFFF) {
|
||||
throw new JSONException("Bad character " + character);
|
||||
}
|
||||
return character <= 0x7F ? 1 : character <= 0x3FFF ? 2 : 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of this kim to a byte array.
|
||||
*
|
||||
* @param bytes
|
||||
* A byte array of sufficient size.
|
||||
* @param at
|
||||
* The position within the byte array to take the byes.
|
||||
* @return The position immediately after the copy.
|
||||
*/
|
||||
public int copy(byte[] bytes, int at) {
|
||||
System.arraycopy(this.bytes, 0, bytes, at, this.length);
|
||||
return at + this.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two kim objects containing exactly the same bytes in the same order are
|
||||
* equal to each other.
|
||||
*
|
||||
* @param obj
|
||||
* the other kim with which to compare.
|
||||
* @returns true if this and obj are both kim objects containing identical
|
||||
* byte sequences.
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Kim)) {
|
||||
return false;
|
||||
}
|
||||
Kim that = (Kim) obj;
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (this.hashcode != that.hashcode) {
|
||||
return false;
|
||||
}
|
||||
return java.util.Arrays.equals(this.bytes, that.bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a byte from a kim.
|
||||
* @param at
|
||||
* The position of the byte. The first byte is at 0.
|
||||
* @return The byte.
|
||||
* @throws JSONException
|
||||
* if there is no byte at that position.
|
||||
*/
|
||||
public int get(int at) throws JSONException {
|
||||
if (at < 0 || at > this.length) {
|
||||
throw new JSONException("Bad character at " + at);
|
||||
}
|
||||
return ((int) this.bytes[at]) & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the kim.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return this.hashcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a UTF-16 String from this kim. The number of codepoints in the
|
||||
* string will not be greater than the number of bytes in the kim, although
|
||||
* it could be less.
|
||||
*
|
||||
* @return The string. A kim memoizes its string representation.
|
||||
* @throws JSONException
|
||||
* if the kim is not valid.
|
||||
*/
|
||||
public String toString() throws JSONException {
|
||||
if (this.string == null) {
|
||||
int c;
|
||||
int length = 0;
|
||||
char chars[] = new char[this.length];
|
||||
for (int at = 0; at < this.length; at += characterSize(c)) {
|
||||
c = this.characterAt(at);
|
||||
if (c < 0x10000) {
|
||||
chars[length] = (char) c;
|
||||
length += 1;
|
||||
} else {
|
||||
chars[length] = (char) (0xD800 | ((c - 0x10000) >>> 10));
|
||||
length += 1;
|
||||
chars[length] = (char) (0xDC00 | (c & 0x03FF));
|
||||
length += 1;
|
||||
}
|
||||
}
|
||||
this.string = new String(chars, 0, length);
|
||||
}
|
||||
return this.string;
|
||||
}
|
||||
}
|
72
src/org/json/Property.java
Normal file
72
src/org/json/Property.java
Normal file
@ -0,0 +1,72 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Converts a Property file data into JSONObject and back.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Property {
|
||||
/**
|
||||
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
|
||||
* @param properties java.util.Properties
|
||||
* @return JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
if (properties != null && !properties.isEmpty()) {
|
||||
Enumeration enumProperties = properties.propertyNames();
|
||||
while(enumProperties.hasMoreElements()) {
|
||||
String name = (String)enumProperties.nextElement();
|
||||
jo.put(name, properties.getProperty(name));
|
||||
}
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the JSONObject into a property file object.
|
||||
* @param jo JSONObject
|
||||
* @return java.util.Properties
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static Properties toProperties(JSONObject jo) throws JSONException {
|
||||
Properties properties = new Properties();
|
||||
if (jo != null) {
|
||||
Iterator<String> keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
String name = keys.next();
|
||||
properties.put(name, jo.getString(name));
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
490
src/org/json/XML.java
Normal file
490
src/org/json/XML.java
Normal file
@ -0,0 +1,490 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONObject,
|
||||
* and to covert a JSONObject into an XML text.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XML {
|
||||
|
||||
/** The Character '&'. */
|
||||
public static final Character AMP = '&';
|
||||
|
||||
/** The Character '''. */
|
||||
public static final Character APOS = '\'';
|
||||
|
||||
/** The Character '!'. */
|
||||
public static final Character BANG = '!';
|
||||
|
||||
/** The Character '='. */
|
||||
public static final Character EQ = '=';
|
||||
|
||||
/** The Character '>'. */
|
||||
public static final Character GT = '>';
|
||||
|
||||
/** The Character '<'. */
|
||||
public static final Character LT = '<';
|
||||
|
||||
/** The Character '?'. */
|
||||
public static final Character QUEST = '?';
|
||||
|
||||
/** The Character '"'. */
|
||||
public static final Character QUOT = '"';
|
||||
|
||||
/** The Character '/'. */
|
||||
public static final Character SLASH = '/';
|
||||
|
||||
/**
|
||||
* Replace special characters with XML escapes:
|
||||
* <pre>
|
||||
* & <small>(ampersand)</small> is replaced by &amp;
|
||||
* < <small>(less than)</small> is replaced by &lt;
|
||||
* > <small>(greater than)</small> is replaced by &gt;
|
||||
* " <small>(double quote)</small> is replaced by &quot;
|
||||
* </pre>
|
||||
* @param string The string to be escaped.
|
||||
* @return The escaped string.
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
StringBuilder sb = new StringBuilder(string.length());
|
||||
for (int i = 0, length = string.length(); i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
switch (c) {
|
||||
case '&':
|
||||
sb.append("&");
|
||||
break;
|
||||
case '<':
|
||||
sb.append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.append(">");
|
||||
break;
|
||||
case '"':
|
||||
sb.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
sb.append("'");
|
||||
break;
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the string contains whitespace.
|
||||
* Whitespace is not allowed in tagNames and attributes.
|
||||
* @param string A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static void noSpace(String string) throws JSONException {
|
||||
int i, length = string.length();
|
||||
if (length == 0) {
|
||||
throw new JSONException("Empty string.");
|
||||
}
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (Character.isWhitespace(string.charAt(i))) {
|
||||
throw new JSONException("'" + string +
|
||||
"' contains a space character.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the content following the named tag, attaching it to the context.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param context The JSONObject that will include the new material.
|
||||
* @param name The tag name.
|
||||
* @return true if the close tag is processed.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static boolean parse(XMLTokener x, JSONObject context,
|
||||
String name) throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
JSONObject jsonobject = null;
|
||||
String string;
|
||||
String tagName;
|
||||
Object token;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <! ... >
|
||||
// <![ ... ]]>
|
||||
// <? ... ?>
|
||||
// Report errors for these forms:
|
||||
// <>
|
||||
// <=
|
||||
// <<
|
||||
|
||||
token = x.nextToken();
|
||||
|
||||
// <!
|
||||
|
||||
if (token == BANG) {
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
return false;
|
||||
}
|
||||
x.back();
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if ("CDATA".equals(token)) {
|
||||
if (x.next() == '[') {
|
||||
string = x.nextCDATA();
|
||||
if (string.length() > 0) {
|
||||
context.accumulate("content", string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == LT) {
|
||||
i += 1;
|
||||
} else if (token == GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
return false;
|
||||
} else if (token == QUEST) {
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
return false;
|
||||
} else if (token == SLASH) {
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if (name == null) {
|
||||
throw x.syntaxError("Mismatched close tag " + token);
|
||||
}
|
||||
if (!token.equals(name)) {
|
||||
throw x.syntaxError("Mismatched " + name + " and " + token);
|
||||
}
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (token instanceof Character) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else {
|
||||
tagName = (String)token;
|
||||
token = null;
|
||||
jsonobject = new JSONObject();
|
||||
for (;;) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
if (token instanceof String) {
|
||||
string = (String)token;
|
||||
token = x.nextToken();
|
||||
if (token == EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
jsonobject.accumulate(string,
|
||||
XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
jsonobject.accumulate(string, "");
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
} else if (token == SLASH) {
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (jsonobject.length() > 0) {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
} else {
|
||||
context.accumulate(tagName, "");
|
||||
}
|
||||
return false;
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else if (token == GT) {
|
||||
for (;;) {
|
||||
token = x.nextContent();
|
||||
if (token == null) {
|
||||
if (tagName != null) {
|
||||
throw x.syntaxError("Unclosed tag " + tagName);
|
||||
}
|
||||
return false;
|
||||
} else if (token instanceof String) {
|
||||
string = (String)token;
|
||||
if (string.length() > 0) {
|
||||
jsonobject.accumulate("content",
|
||||
XML.stringToValue(string));
|
||||
}
|
||||
|
||||
// Nested element
|
||||
|
||||
} else if (token == LT) {
|
||||
if (parse(x, jsonobject, tagName)) {
|
||||
if (jsonobject.length() == 0) {
|
||||
context.accumulate(tagName, "");
|
||||
} else if (jsonobject.length() == 1 &&
|
||||
jsonobject.opt("content") != null) {
|
||||
context.accumulate(tagName,
|
||||
jsonobject.opt("content"));
|
||||
} else {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to convert a string into a number, boolean, or null. If the string
|
||||
* can't be converted, return the string. This is much less ambitious than
|
||||
* JSONObject.stringToValue, especially because it does not attempt to
|
||||
* convert plus forms, octal forms, hex forms, or E forms lacking decimal
|
||||
* points.
|
||||
* @param string A String.
|
||||
* @return A simple JSON value.
|
||||
*/
|
||||
public static Object stringToValue(String string) {
|
||||
if ("true".equalsIgnoreCase(string)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(string)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ("null".equalsIgnoreCase(string)) {
|
||||
return JSONObject.NULL;
|
||||
}
|
||||
|
||||
// If it might be a number, try converting it, first as a Long, and then as a
|
||||
// Double. If that doesn't work, return the string.
|
||||
|
||||
try {
|
||||
char initial = string.charAt(0);
|
||||
if (initial == '-' || (initial >= '0' && initial <= '9')) {
|
||||
Long value = new Long(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
try {
|
||||
Double value = new Double(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
} catch (Exception ignoreAlso) {
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject. Some information may be lost in this transformation
|
||||
* because JSON is a data format and XML is a document format. XML uses
|
||||
* elements, attributes, and content text, while JSON uses unordered
|
||||
* collections of name/value pairs and arrays of values. JSON does not
|
||||
* does not like to distinguish between elements and attributes.
|
||||
* Sequences of similar elements are represented as JSONArrays. Content
|
||||
* text may be placed in a "content" member. Comments, prologs, DTDs, and
|
||||
* <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
XMLTokener x = new XMLTokener(string);
|
||||
while (x.more() && x.skipPast("<")) {
|
||||
parse(x, jo, null);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
* @param object A JSONObject.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object) throws JSONException {
|
||||
return toString(object, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
* @param object A JSONObject.
|
||||
* @param tagName The optional name of the enclosing tag.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object, String tagName)
|
||||
throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
String string;
|
||||
Object value;
|
||||
if (object instanceof JSONObject) {
|
||||
|
||||
// Emit <tagName>
|
||||
|
||||
if (tagName != null) {
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
|
||||
// Loop thru the keys.
|
||||
|
||||
jo = (JSONObject)object;
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
value = jo.opt(key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
string = value instanceof String ? (String)value : null;
|
||||
|
||||
// Emit content in body
|
||||
|
||||
if ("content".equals(key)) {
|
||||
if (value instanceof JSONArray) {
|
||||
ja = (JSONArray)value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(escape(ja.get(i).toString()));
|
||||
}
|
||||
} else {
|
||||
sb.append(escape(value.toString()));
|
||||
}
|
||||
|
||||
// Emit an array of similar keys
|
||||
|
||||
} else if (value instanceof JSONArray) {
|
||||
ja = (JSONArray)value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
value = ja.get(i);
|
||||
if (value instanceof JSONArray) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
sb.append(toString(value));
|
||||
sb.append("</");
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
} else if ("".equals(value)) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append("/>");
|
||||
|
||||
// Emit a new tag <k>
|
||||
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
if (tagName != null) {
|
||||
|
||||
// Emit the </tagname> close tag
|
||||
|
||||
sb.append("</");
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
// XML does not have good support for arrays. If an array appears in a place
|
||||
// where XML is lacking, synthesize an <array> element.
|
||||
|
||||
} else {
|
||||
if (object.getClass().isArray()) {
|
||||
object = new JSONArray(object);
|
||||
}
|
||||
if (object instanceof JSONArray) {
|
||||
ja = (JSONArray)object;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
string = (object == null) ? "null" : escape(object.toString());
|
||||
return (tagName == null) ? "\"" + string + "\"" :
|
||||
(string.length() == 0) ? "<" + tagName + "/>" :
|
||||
"<" + tagName + ">" + string + "</" + tagName + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
365
src/org/json/XMLTokener.java
Normal file
365
src/org/json/XMLTokener.java
Normal file
@ -0,0 +1,365 @@
|
||||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The XMLTokener extends the JSONTokener to provide additional methods
|
||||
* for the parsing of XML texts.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XMLTokener extends JSONTokener {
|
||||
|
||||
|
||||
/** The table of entity values. It initially contains Character values for
|
||||
* amp, apos, gt, lt, quot.
|
||||
*/
|
||||
public static final java.util.HashMap<String, Character> entity;
|
||||
|
||||
static {
|
||||
entity = new java.util.HashMap<String, Character>(8);
|
||||
entity.put("amp", XML.AMP);
|
||||
entity.put("apos", XML.APOS);
|
||||
entity.put("gt", XML.GT);
|
||||
entity.put("lt", XML.LT);
|
||||
entity.put("quot", XML.QUOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XMLTokener from a string.
|
||||
* @param s A source string.
|
||||
*/
|
||||
public XMLTokener(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text in the CDATA block.
|
||||
* @return The string up to the <code>]]></code>.
|
||||
* @throws JSONException If the <code>]]></code> is not found.
|
||||
*/
|
||||
public String nextCDATA() throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (end()) {
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
sb.append(c);
|
||||
i = sb.length() - 3;
|
||||
if (i >= 0 && sb.charAt(i) == ']' &&
|
||||
sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
|
||||
sb.setLength(i);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next XML outer token, trimming whitespace. There are two kinds
|
||||
* of tokens: the '<' character which begins a markup tag, and the content
|
||||
* text between markup tags.
|
||||
*
|
||||
* @return A string, or a '<' Character, or null if there is no more
|
||||
* source text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Object nextContent() throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if (c == 0) {
|
||||
return null;
|
||||
}
|
||||
if (c == '<') {
|
||||
return XML.LT;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
if (c == '<' || c == 0) {
|
||||
back();
|
||||
return sb.toString().trim();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the next entity. These entities are translated to Characters:
|
||||
* <code>& ' > < "</code>.
|
||||
* @param ampersand An ampersand character.
|
||||
* @return A Character or an entity String if the entity is not recognized.
|
||||
* @throws JSONException If missing ';' in XML entity.
|
||||
*/
|
||||
public Object nextEntity(char ampersand) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
char c = next();
|
||||
if (Character.isLetterOrDigit(c) || c == '#') {
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else if (c == ';') {
|
||||
break;
|
||||
} else {
|
||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||
}
|
||||
}
|
||||
String string = sb.toString();
|
||||
Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ";";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next XML meta token. This is used for skipping over <!...>
|
||||
* and <?...?> structures.
|
||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
|
||||
* Character, and strings and names are returned as Boolean. We don't care
|
||||
* what the values actually are.
|
||||
* @throws JSONException If a string is not properly closed or if the XML
|
||||
* is badly structured.
|
||||
*/
|
||||
public Object nextMeta() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped meta tag");
|
||||
case '<':
|
||||
return XML.LT;
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
default:
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '<':
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '"':
|
||||
case '\'':
|
||||
back();
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next XML Token. These tokens are found inside of angle
|
||||
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it
|
||||
* may be a string wrapped in single quotes or double quotes, or it may be a
|
||||
* name.
|
||||
* @return a String or a Character.
|
||||
* @throws JSONException If the XML is not well formed.
|
||||
*/
|
||||
public Object nextToken() throws JSONException {
|
||||
char c;
|
||||
char q;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped element");
|
||||
case '<':
|
||||
throw syntaxError("Misplaced '<'");
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
|
||||
// Quoted string
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
// Name
|
||||
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
sb.append(c);
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
return sb.toString();
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '[':
|
||||
case ']':
|
||||
back();
|
||||
return sb.toString();
|
||||
case '<':
|
||||
case '"':
|
||||
case '\'':
|
||||
throw syntaxError("Bad character in a name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip characters until past the requested string.
|
||||
* If it is not found, we are left at the end of the source with a result of false.
|
||||
* @param to A string to skip past.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public boolean skipPast(String to) throws JSONException {
|
||||
boolean b;
|
||||
char c;
|
||||
int i;
|
||||
int j;
|
||||
int offset = 0;
|
||||
int length = to.length();
|
||||
char[] circle = new char[length];
|
||||
|
||||
/*
|
||||
* First fill the circle buffer with as many characters as are in the
|
||||
* to string. If we reach an early end, bail.
|
||||
*/
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
circle[i] = c;
|
||||
}
|
||||
|
||||
/* We will loop, possibly for all of the remaining characters. */
|
||||
|
||||
for (;;) {
|
||||
j = offset;
|
||||
b = true;
|
||||
|
||||
/* Compare the circle buffer with the to string. */
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (circle[j] != to.charAt(i)) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
if (j >= length) {
|
||||
j -= length;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we exit the loop with b intact, then victory is ours. */
|
||||
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Get the next character. If there isn't one, then defeat is ours. */
|
||||
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Shove the character in the circle buffer and advance the
|
||||
* circle offset. The offset is mod n.
|
||||
*/
|
||||
circle[offset] = c;
|
||||
offset += 1;
|
||||
if (offset >= length) {
|
||||
offset -= length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
tmp/styles/main.css
Normal file
43
tmp/styles/main.css
Normal file
@ -0,0 +1,43 @@
|
||||
body {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
margin: 0px auto;
|
||||
padding: 0px;
|
||||
max-width: 900px;
|
||||
font-size: 12px;
|
||||
font-family: tahoma;
|
||||
line-height: 1.182;
|
||||
}
|
||||
|
||||
.im_date_link {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.hr { padding: 5px 0 3px 15px; }
|
||||
|
||||
.im_log_author {
|
||||
text-align: right;
|
||||
padding-right: 10px !important;
|
||||
width: 32px;
|
||||
color: #2B587A;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.audio {
|
||||
padding-left: 5px;
|
||||
padding-top: 2px;
|
||||
float: left;
|
||||
}
|
||||
.play_new {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(http://st0.vk.me/images/playpause.gif) no-repeat 0px 0px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.wall {
|
||||
border-left: 2px solid #C3D1E0;
|
||||
padding-left: 10px;
|
||||
margin: 10px 0 5px 3px;
|
||||
}
|
Loading…
Reference in New Issue
Block a user