project renamed to wson

This commit is contained in:
woggioni committed 2022-01-16 15:37:52 +08:00
1 parent f96ab24ad7
commit 6422a91568
71 files changed
+462 -494

No files matched your search

@@ -1,38 +0,0 @@
package net.woggioni.worth.buffer;
import lombok.SneakyThrows;
import java.io.Reader;
public class CircularBuffer {
private int[] buffer;
private Reader reader;
private int delta = 0, cursor = 0;
public CircularBuffer(Reader reader, int size) {
this.reader = reader;
buffer = new int[size];
}
@SneakyThrows
public int next() {
if (delta < 0)
return buffer[Math.floorMod(cursor + delta++, buffer.length)];
else {
int result = reader.read();
if (result < 0) return result;
buffer[cursor] = result;
cursor = (cursor + 1) % buffer.length;
return result;
}
}
public int prev() {
return buffer[cursor + --delta >= 0 ? cursor + delta : cursor + delta + buffer.length];
}
public int size() {
return buffer.length;
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class IOException extends WorthException {
public IOException(String msg) {
super(msg);
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class MaxDepthExceededException extends WorthException {
public MaxDepthExceededException(String msg) {
super(msg);
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class NotImplementedException extends WorthException {
public NotImplementedException(String msg) {
super(msg);
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class ParseException extends WorthException {
public ParseException(String msg) {
super(msg);
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class TypeException extends WorthException {
public TypeException(String msg) {
super(msg);
}
}
@@ -1,7 +0,0 @@
package net.woggioni.worth.exception;
public class WorthException extends RuntimeException {
public WorthException(String msg) {
super(msg);
}
}
@@ -1,49 +0,0 @@
package net.woggioni.worth.utils;
import lombok.SneakyThrows;
import net.woggioni.worth.xface.Value;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
public class WorthUtils {
public static Optional<Value> nested(Value root, String... keys) {
Value result = root;
for (String key : keys) {
result = result.get(key);
if (result == null) {
break;
}
}
return Optional.ofNullable(result);
}
public static Value getOrNull(Value root, String... keys) {
Value result = root;
for (String key : keys) {
result = result.get(key);
if (result == null) {
result = Value.Null;
break;
}
}
return result;
}
public static <T> T getOrNull(Value root, Function<Value, T> callback, String... keys) {
Value result = getOrNull(root, keys);
return result.type() == Value.Type.NULL ? null : callback.apply(result);
}
@SneakyThrows
public static <T> T getOrThrow(Value root, Function<Value, T> success, Supplier<Throwable> error, String... keys) {
Value result = getOrNull(root, keys);
if (result.type() == Value.Type.NULL) {
throw error.get();
} else {
return success.apply(result);
}
}
}
@@ -1,4 +1,4 @@
package net.woggioni.worth.buffer;
package net.woggioni.wson.buffer;
import lombok.SneakyThrows;
@@ -1,4 +1,4 @@
package net.woggioni.worth.buffer;
package net.woggioni.wson.buffer;
import lombok.SneakyThrows;
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class IOException extends WsonException {
public IOException(String msg) {
super(msg);
}
}
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class MaxDepthExceededException extends WsonException {
public MaxDepthExceededException(String msg) {
super(msg);
}
}
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class NotImplementedException extends WsonException {
public NotImplementedException(String msg) {
super(msg);
}
}
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class ParseException extends WsonException {
public ParseException(String msg) {
super(msg);
}
}
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class TypeException extends WsonException {
public TypeException(String msg) {
super(msg);
}
}
@@ -0,0 +1,7 @@
package net.woggioni.wson.exception;
public class WsonException extends RuntimeException {
public WsonException(String msg) {
super(msg);
}
}
@@ -1,13 +1,13 @@
package net.woggioni.worth.serialization;
package net.woggioni.wson.serialization;
import lombok.RequiredArgsConstructor;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.traversal.TraversalContext;
import net.woggioni.worth.traversal.ValueIdentity;
import net.woggioni.worth.traversal.ValueVisitor;
import net.woggioni.worth.traversal.ValueWalker;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.traversal.TraversalContext;
import net.woggioni.wson.traversal.ValueIdentity;
import net.woggioni.wson.traversal.ValueVisitor;
import net.woggioni.wson.traversal.ValueWalker;
import net.woggioni.wson.xface.Dumper;
import net.woggioni.wson.xface.Value;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -1,17 +1,17 @@
package net.woggioni.worth.serialization;
package net.woggioni.wson.serialization;
import lombok.RequiredArgsConstructor;
import net.woggioni.worth.exception.MaxDepthExceededException;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.exception.ParseException;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.BooleanValue;
import net.woggioni.worth.value.FloatValue;
import net.woggioni.worth.value.IntegerValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.value.StringValue;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.exception.MaxDepthExceededException;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.exception.ParseException;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.value.BooleanValue;
import net.woggioni.wson.value.FloatValue;
import net.woggioni.wson.value.IntegerValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.value.StringValue;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -1,4 +1,4 @@
package net.woggioni.worth.serialization.binary;
package net.woggioni.wson.serialization.binary;
public enum BinaryMarker {
Float(0x0),
@@ -1,14 +1,14 @@
package net.woggioni.worth.serialization.binary;
package net.woggioni.wson.serialization.binary;
import lombok.SneakyThrows;
import net.woggioni.jwo.Leb128;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.traversal.ValueIdentity;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.serialization.ValueDumper;
import net.woggioni.wson.traversal.ValueIdentity;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Dumper;
import net.woggioni.wson.xface.Value;
import java.io.OutputStream;
import java.io.Writer;
@@ -1,12 +1,12 @@
package net.woggioni.worth.serialization.binary;
package net.woggioni.wson.serialization.binary;
import lombok.SneakyThrows;
import net.woggioni.jwo.Leb128;
import net.woggioni.worth.buffer.LookAheadInputStream;
import net.woggioni.worth.exception.ParseException;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.buffer.LookAheadInputStream;
import net.woggioni.wson.exception.ParseException;
import net.woggioni.wson.serialization.ValueParser;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import java.io.InputStream;
import java.util.function.Function;
@@ -1,12 +1,10 @@
package net.woggioni.worth.serialization.json;
package net.woggioni.wson.serialization.json;
import lombok.SneakyThrows;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.traversal.ValueIdentity;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.*;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.serialization.ValueDumper;
import net.woggioni.wson.traversal.ValueIdentity;
import net.woggioni.wson.xface.Dumper;
import net.woggioni.wson.xface.Value;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -15,8 +13,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public class JSONDumper extends ValueDumper {
@@ -1,14 +1,13 @@
package net.woggioni.worth.serialization.json;
package net.woggioni.wson.serialization.json;
import lombok.SneakyThrows;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.exception.IOException;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.exception.ParseException;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.buffer.LookAheadTextInputStream;
import net.woggioni.wson.exception.IOException;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.exception.ParseException;
import net.woggioni.wson.serialization.ValueParser;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -1,9 +1,9 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
@RequiredArgsConstructor
abstract class AbstractStackElement<T> implements StackElement<T> {
@@ -1,8 +1,8 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.xface.Value;
import java.util.Iterator;
@@ -1,7 +1,7 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.xface.Value;
import static net.woggioni.jwo.JWO.newThrowable;
@@ -1,7 +1,7 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Value;
import java.util.Iterator;
import java.util.Map;
@@ -1,6 +1,6 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
public interface StackElement<T> {
T getContext();
@@ -1,4 +1,4 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import java.util.List;
@@ -1,7 +1,7 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import lombok.RequiredArgsConstructor;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
import java.util.Objects;
@@ -1,4 +1,4 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
public interface ValueVisitor<T> {
default boolean visitPre(TraversalContext<T> ctx) { return true; }
@@ -1,8 +1,8 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Value;
import java.util.ArrayList;
import java.util.Collections;
@@ -0,0 +1,32 @@
package net.woggioni.wson.utils;
import lombok.SneakyThrows;
import net.woggioni.wson.xface.Value;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
public class WsonUtils {
public static Value getOrNull(Value root, String... keys) {
Value result = root;
for (String key : keys) {
if(result.type() != Value.Type.OBJECT) {
result = null;
break;
}
result = result.get(key);
}
return result;
}
public static Optional<Value> optGet(Value root, String... keys) {
return Optional.ofNullable(getOrNull(root, keys));
}
@SneakyThrows
public static <T> T getOrThrow(Value root, Function<Value, T> success, Supplier<Throwable> error, String... keys) {
return optGet(root, keys).map(success).orElseThrow(error);
}
}
@@ -1,12 +1,10 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import lombok.NonNull;
import net.woggioni.wson.xface.Value;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.*;
@EqualsAndHashCode
public class ArrayValue implements Value, Iterable<Value> {
@@ -14,10 +12,10 @@ public class ArrayValue implements Value, Iterable<Value> {
private final List<Value> value;
public ArrayValue() {
this.value = new ArrayList();
this.value = new ArrayList<>();
}
public ArrayValue(List<Value> value) {
public ArrayValue(@NonNull List<Value> value) {
this.value = value;
}
@@ -1,7 +1,7 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
@EqualsAndHashCode
public class BooleanValue implements Value {
@@ -1,7 +1,7 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
@EqualsAndHashCode
public class FloatValue implements Value {
@@ -1,7 +1,7 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
@EqualsAndHashCode
public class IntegerValue implements Value {
@@ -1,7 +1,7 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
@EqualsAndHashCode
public class NullValue implements Value {
@@ -1,9 +1,9 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import static net.woggioni.jwo.JWO.newThrowable;
import net.woggioni.worth.xface.Value;
import net.woggioni.wson.xface.Value;
import java.util.*;
@@ -91,7 +91,7 @@ abstract class MapObjectValue implements ObjectValue {
@Override
public Value get(String key) {
return value.getOrDefault(key, Value.Null);
return value.get(key);
}
@Override
@@ -177,7 +177,7 @@ class ListObjectValue implements ObjectValue {
for (Map.Entry<String, Value> entry : value) {
if(Objects.equals(entry.getKey(), key)) return entry.getValue();
}
return Value.Null;
return null;
}
@Override
@@ -1,15 +1,17 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import lombok.NonNull;
import net.woggioni.wson.xface.Value;
import java.util.Objects;
@EqualsAndHashCode
public class StringValue implements Value {
private final String value;
public StringValue(String value)
{
public StringValue(@NonNull String value) {
this.value = value;
}
@@ -1,4 +1,4 @@
package net.woggioni.worth.xface;
package net.woggioni.wson.xface;
import java.io.OutputStream;
import java.io.Writer;
@@ -1,4 +1,4 @@
package net.woggioni.worth.xface;
package net.woggioni.wson.xface;
import java.io.InputStream;
import java.io.Reader;
@@ -1,11 +1,10 @@
package net.woggioni.worth.xface;
package net.woggioni.wson.xface;
import lombok.Builder;
import net.woggioni.worth.exception.TypeException;
import net.woggioni.worth.value.NullValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.wson.exception.TypeException;
import net.woggioni.wson.value.NullValue;
import net.woggioni.wson.value.ObjectValue;
import java.util.List;
import java.util.Map;
public interface Value {
@@ -1,36 +0,0 @@
package net.woggioni.worth.buffer;
import lombok.SneakyThrows;
import org.junit.Assert;
import org.junit.Test;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.Random;
public class CircularBufferTest {
@Test
@SneakyThrows
public void test() {
MessageDigest streamDigest = MessageDigest.getInstance("MD5"), outputDigest = MessageDigest.getInstance("MD5");
InputStream is = new DigestInputStream(getClass().getResourceAsStream("/logging.properties"), streamDigest);
CircularBuffer cb = new CircularBuffer(new InputStreamReader(is), 32);
Random rand = new Random();
while (true) {
int b = cb.next();
if (b < 0) break;
if (rand.nextInt() % 2 == 0) {
cb.prev();
} else {
char c = (char) b;
outputDigest.update((byte) b);
System.out.print(c);
}
}
System.out.println();
Assert.assertArrayEquals(streamDigest.digest(), outputDigest.digest());
}
}
@@ -1,40 +0,0 @@
package net.woggioni.worth.serialization;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import net.woggioni.worth.exception.MaxDepthExceededException;
import net.woggioni.worth.serialization.json.JSONParser;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Test;
import java.io.InputStream;
public class JsonBombTest {
public static InputStream infiniteJson() {
return new InputStream() {
int index = 0;
final String monomer = "{\"key\":[";
@Override
public int read() {
return (int) monomer.charAt(index++ % monomer.length());
}
};
}
@Test(expected = StackOverflowError.class)
@SneakyThrows
public void jackson() {
ObjectMapper om = new ObjectMapper();
om.readTree(infiniteJson());
}
@Test(expected = MaxDepthExceededException.class)
@SneakyThrows
public void worth() {
Value.Configuration cfg = Value.Configuration.builder().maxDepth(1024).build();
Parser parser = JSONParser.newInstance(cfg);
parser.parse(infiniteJson());
}
}
+29
View File
@@ -0,0 +1,29 @@
package net.woggioni.wson;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Foo {
@TempDir
Path tempDir;
@BeforeEach
void beforeEach() {
Assertions.assertTrue(Files.isDirectory(this.tempDir));
}
@Test
void throwsErrorWhenTargetFileExists() throws IOException {
Path output = Files.createFile(
tempDir.resolve("output.txt")
);
}
}
@@ -0,0 +1,32 @@
package net.woggioni.wson.serialization;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import net.woggioni.wson.exception.MaxDepthExceededException;
import net.woggioni.wson.serialization.json.JSONParser;
import net.woggioni.wson.test.JsonBomb;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class JsonBombTest {
@Test
@SneakyThrows
public void jackson() {
ObjectMapper om = new ObjectMapper();
Assertions.assertThrows(StackOverflowError.class, () -> {
om.readTree(JsonBomb.infiniteJson());
});
}
@Test
@SneakyThrows
public void worth() {
Value.Configuration cfg = Value.Configuration.builder().maxDepth(1024).build();
Parser parser = JSONParser.newInstance(cfg);
Assertions.assertThrows(MaxDepthExceededException.class, () -> {
parser.parse(JsonBomb.infiniteJson());
});
}
}
@@ -1,27 +1,30 @@
package net.woggioni.worth.serialization;
package net.woggioni.wson.serialization;
import lombok.SneakyThrows;
import net.woggioni.jwo.JWO;
import net.woggioni.worth.serialization.binary.JBONDumper;
import net.woggioni.worth.serialization.binary.JBONParser;
import net.woggioni.worth.serialization.json.JSONDumper;
import net.woggioni.worth.serialization.json.JSONParser;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.IntegerValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.wson.serialization.binary.JBONDumper;
import net.woggioni.wson.serialization.binary.JBONParser;
import net.woggioni.wson.serialization.json.JSONDumper;
import net.woggioni.wson.serialization.json.JSONParser;
import net.woggioni.wson.value.IntegerValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Dumper;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.util.function.Function;
public class ReferenceTest {
@TempDir
Path testDir;
@SneakyThrows
private void common(Function<Value.Configuration, Dumper> dumperConstructor,
Function<Value.Configuration, Parser> parserConstructor) {
@@ -39,14 +42,14 @@ public class ReferenceTest {
dumper.dump(value, baos);
bytes = baos.toByteArray();
}
JWO.writeBytes2File(Paths.get("/tmp/ciao.jbon"), bytes);
JWO.writeBytes2File(testDir.resolve("ciao.jbon"), bytes);
Value reparsedValue;
try(ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
Parser parser = parserConstructor.apply(cfg);
reparsedValue = parser.parse(bais);
}
Assert.assertEquals(reparsedValue, reparsedValue.get("child"));
Assert.assertEquals(value.get("id"), reparsedValue.get("id"));
Assertions.assertEquals(reparsedValue, reparsedValue.get("child"));
Assertions.assertEquals(value.get("id"), reparsedValue.get("id"));
}
@Test
@@ -1,34 +1,29 @@
package net.woggioni.worth.serialization.binary;
package net.woggioni.wson.serialization.binary;
import lombok.SneakyThrows;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.serialization.json.JSONParser;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.wson.serialization.json.JSONParser;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class JBONTest {
private String[] testFiles = new String[]{"/test.json", "/wordpress.json"};
private static String[] testFiles = new String[]{"/test.json", "/wordpress.json"};
private InputStream getTestSource(String filename) {
return getClass().getResourceAsStream(filename);
private static InputStream getTestSource(String filename) {
return JBONTest.class.getResourceAsStream(filename);
}
@TempDir
Path testDir;
@Test
@SneakyThrows
public void consistencyTest() {
@@ -50,13 +45,13 @@ public class JBONTest {
Parser parser = new JBONParser(cfg);
reParsedValue = parser.parse(is);
}
Assert.assertEquals(parsedValue, reParsedValue);
Assertions.assertEquals(parsedValue, reParsedValue);
byte[] reDumpedJBON;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
JBONDumper.newInstance().dump(reParsedValue, baos);
reDumpedJBON = baos.toByteArray();
}
Assert.assertArrayEquals(dumpedJBON, reDumpedJBON);
Assertions.assertArrayEquals(dumpedJBON, reDumpedJBON);
}
}
@@ -66,7 +61,7 @@ public class JBONTest {
for (String testFile : testFiles) {
Value originalValue = new JSONParser().parse(getTestSource(testFile));
Path outputFile = Files.createTempFile(Paths.get("/tmp"), "worth", null);
Path outputFile = Files.createTempFile(testDir, "worth", null);
try (OutputStream os = new FileOutputStream(outputFile.toFile())) {
JBONDumper jbonDumper = new JBONDumper();
jbonDumper.dump(originalValue, os);
@@ -76,7 +71,7 @@ public class JBONTest {
JBONParser jbonParser = new JBONParser();
binarySerializedValue = jbonParser.parse(is);
}
Assert.assertEquals(originalValue, binarySerializedValue);
Assertions.assertEquals(originalValue, binarySerializedValue);
}
}
}
@@ -1,28 +1,23 @@
package net.woggioni.worth.serialization.json;
package net.woggioni.wson.serialization.json;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import lombok.SneakyThrows;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.IntegerValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.wson.buffer.LookAheadTextInputStream;
import net.woggioni.wson.exception.NotImplementedException;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
public class JSONTest {
@@ -202,11 +197,11 @@ public class JSONTest {
ByteArrayInputStream bais = new ByteArrayInputStream(barray);
parser = new JSONParser(cfg);
Value reParsedValue = parser.parse(bais);
Assert.assertEquals(parsedValue, reParsedValue);
Assertions.assertEquals(parsedValue, reParsedValue);
baos = new ByteArrayOutputStream();
JSONDumper.newInstance().dump(reParsedValue, baos);
String reDumpedJSON = new String(baos.toByteArray());
Assert.assertEquals(dumpedJSON, reDumpedJSON);
Assertions.assertEquals(dumpedJSON, reDumpedJSON);
}
}
@@ -217,8 +212,8 @@ public class JSONTest {
for (String testFile : testFiles) {
JsonNode jsonNode = om.readTree(getTestSource(testFile));
Value value = new JSONParser().parse(getTestSource(testFile));
Assert.assertTrue(compareValueAndJsonNode(value, jsonNode, (v, j) -> {
Assert.fail("Difference found");
Assertions.assertTrue(compareValueAndJsonNode(value, jsonNode, (v, j) -> {
Assertions.fail("Difference found");
}));
}
}
@@ -232,6 +227,6 @@ public class JSONTest {
LookAheadTextInputStream ltis = new LookAheadTextInputStream(new InputStreamReader(bais));
ltis.read();
int result = JSONParser.parseHex(ltis);
Assert.assertEquals(Integer.parseInt(hex, 16), result);
Assertions.assertEquals(Integer.parseInt(hex, 16), result);
}
}
@@ -1,16 +1,16 @@
package net.woggioni.worth.traversal;
package net.woggioni.wson.traversal;
import lombok.SneakyThrows;
import net.woggioni.jwo.JWO;
import net.woggioni.worth.serialization.json.JSONParser;
import net.woggioni.worth.serialization.json.JSONTest;
import net.woggioni.wson.serialization.json.JSONParser;
import net.woggioni.wson.serialization.json.JSONTest;
import net.woggioni.jwo.tuple.Tuple2;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.wson.value.ArrayValue;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.xface.Parser;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.BufferedInputStream;
import java.io.InputStream;
@@ -31,8 +31,8 @@ public class ValueWalkerTest {
}
ValueWalker valueWalker = new ValueWalker(value);
Optional<String> text = valueWalker.get("widget").get("image").get("tags").get(1).map(Value::asString);
Assert.assertTrue(text.isPresent());
Assert.assertEquals("Amazon", text.get());
Assertions.assertTrue(text.isPresent());
Assertions.assertEquals("Amazon", text.get());
}
private static class TestVisitor implements ValueVisitor<Void> {
@@ -84,8 +84,8 @@ public class ValueWalkerTest {
Value v = JSONParser.newInstance().parse(JSONTest.getTestSource("/test.json"));
TestVisitor visitor = new TestVisitor();
ValueWalker.walk(v, visitor);
Assert.assertFalse(visitor.preValues.isEmpty());
Assert.assertFalse(visitor.postValues.isEmpty());
Assert.assertEquals(recursiveWalk(v), new Tuple2<>(visitor.preValues, visitor.postValues));
Assertions.assertFalse(visitor.preValues.isEmpty());
Assertions.assertFalse(visitor.postValues.isEmpty());
Assertions.assertEquals(recursiveWalk(v), new Tuple2<>(visitor.preValues, visitor.postValues));
}
}
@@ -1,9 +1,9 @@
package net.woggioni.worth.value;
package net.woggioni.wson.value;
import net.woggioni.jwo.tuple.Tuple2;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.wson.xface.Value;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
@@ -28,13 +28,13 @@ public class ObjectValueImplementationTest {
Class<? extends ObjectValue> expectedClass =
mapping.stream().filter(t -> t._1 == expectedImplementation).findFirst().get()._2;
ObjectValue obj = ObjectValue.newInstance();
Assert.assertEquals(expectedClass, obj.getClass());
Assertions.assertEquals(expectedClass, obj.getClass());
mapping.forEach(tuple -> {
Value.Configuration cfg = Value.Configuration.builder()
.objectValueImplementation(tuple._1)
.build();
ObjectValue obj2 = ObjectValue.newInstance(cfg);
Assert.assertEquals(tuple._2, obj2.getClass());
Assertions.assertEquals(tuple._2, obj2.getClass());
});
}
Binary file not shown.
Binary file not shown.
-36
View File
@@ -1,36 +0,0 @@
handlers=java.util.logging.ConsoleHandler
config=
sun.net.www.protocol.http.HttpURLConnection.handlers=java.util.logging.ConsoleHandler
#sun.net.www.protocol.http.HttpURLConnection.level=ALL
java.util.logging.FileHandler.level = WARNING
java.util.logging.FileHandler.filter =
java.util.logging.FileHandler.formatter =
java.util.logging.FileHandler.encoding =
java.util.logging.FileHandler.limit =
java.util.logging.FileHandler.count =
java.util.logging.FileHandler.append = false
java.util.logging.FileHandler.pattern = log.%u.%g.txt
#java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.filter =
java.util.logging.ConsoleHandler.formatter =
java.util.logging.ConsoleHandler.encoding =
java.util.logging.StreamHandler.level = WARNING
java.util.logging.StreamHandler.filter =
java.util.logging.StreamHandler.formatter =
java.util.logging.StreamHandler.encoding =
java.util.logging.SocketHandler.level = WARNING
java.util.logging.SocketHandler.filter =
java.util.logging.SocketHandler.formatter =
java.util.logging.SocketHandler.encoding =
java.util.logging.SocketHandler.host =
java.util.logging.SocketHandler.port =
java.util.logging.MemoryHandler.level = WARNING
java.util.logging.MemoryHandler.filter =
java.util.logging.MemoryHandler.size =
java.util.logging.MemoryHandler.push =
java.util.logging.MemoryHandler.target =
-31
View File
@@ -1,31 +0,0 @@
{
"widget": {
"debug": "on",
"window": {
"parent" : null,
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 501
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center",
"tags" : ["Ireland", "Amazon", "development"],
"monochromatic" : false
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}
-318
View File
@@ -1,318 +0,0 @@
[
{
"id": 168697,
"date": "2018-09-06T09:30:53",
"date_gmt": "2018-09-06T16:30:53",
"guid": {
"rendered": "https://www.sitepoint.com/?p=168697"
},
"modified": "2018-09-04T21:31:02",
"modified_gmt": "2018-09-05T04:31:02",
"slug": "the-8-best-wordpress-themes-for-small-business-websites",
"status": "publish",
"type": "post",
"link": "https://www.sitepoint.com/the-8-best-wordpress-themes-for-small-business-websites/",
"title": {
"rendered": "The 8 Best WordPress Themes for Small Business Websites"
},
"content": {
"rendered": "<p class=\"wp-special\"><em>This article was created in partnership with <a href=\"https://bawmedia.com/\" rel=\"nofollow\">BAWMedia</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p>A well-designed website can serve as a powerful marketing tool. These days, creating one for a small business is not distressing or expensive at all. However, it was just a few short years ago.</p>\n<p>Today, you can take advantage of the features provided by the best WordPress themes. There are special themes for small business-oriented websites. It&#39;s not difficult to find a website-building theme that matches a specific business. This can be a startup, a service provider, or some other venture.</p>\n<p>You undoubtedly want nothing but the best business theme, right? Check out those described below. Each possesses functional designs loaded with amazing features. They will help you create a thoroughly engaging website to promote a business.</p>\n<h2>1. <a href=\"http://themes.muffingroup.com/be/splash/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\">Be Theme</a></h2>\n<p><a href=\"http://themes.muffingroup.com/be/splash/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215231.png\" alt=\"\" width=\"1000\" height=\"481\" class=\"aligncenter size-full wp-image-168702\" /></a></p>\n<p>We&#8217;ll start with Be Theme, a responsive, multipurpose WordPress theme that takes every small business need into account with its more than 370 pre-built websites. There&#39;s a multiplicity of small business WordPress themes in this pre-built website collection \u2014 each one embedded with the functionality you need to establish an effective online presence, and fully customizable to meet your business and marketing needs.</p>\n<p>The range of business niches covered is impressive, With more pre-built websites being added every month it&#39;s destined to become even more so. Web designers like Be Theme because it allows them to create a website for most small business types in as little as four hours.</p>\n<p>Clients appreciate the rapid turnaround they receive and the ease in which changes or additions they have in mind can be accommodated.</p>\n<p>Be Theme, one of the best WordPress themes for small business websites is a ThemeForest top 5 best seller whose core features include easy to work with page-building tools, a multiplicity of design features and options, and great support.</p>\n<h2>2. <a href=\"http://bit.ly/2wxuUpA\" rel=\"nofollow\">Astra</a></h2>\n<p><a href=\"http://bit.ly/2wxuUpA\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215352.jpg\" alt=\"\" width=\"1000\" height=\"491\" class=\"aligncenter size-full wp-image-168703\" /></a></p>\n<p>Astra is fast, fully customizable, and one of the best WordPress themes for business websites as well as for blogs and personal portfolios. Built with SEO in mind, Astra is responsive and WooCommerce ready \u2014 mandatory features in today&#39;s online business environment. Its capabilities are easily extendible with premium addons and Astra can be used with most of the popular page builders. This free WP-based theme is definitely worth considering.</p>\n<h2 id=\"\">3. <a href=\"http://bit.ly/2oiQkTS\" rel=\"nofollow\">The100</a></h2>\n<p><a href=\"http://bit.ly/2oiQkTS\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215473.jpg\" alt=\"\" width=\"1000\" height=\"491\" class=\"aligncenter size-full wp-image-168704\" /></a></p>\n<p>A theme selected for WordPress for small businesses can be free or it can be a premium theme requiring an expenditure on your behalf. There are several excellent free themes on the market, and one of them is The100. While it is advertised as having premium-like features, bear in mind that free themes like this one generally can&#39;t compete with premium themes. Nevertheless, The100 is an easy-to-use WP theme that features a multiplicity of layouts and plenty of customization options.</p>\n<h2 id=\"\">4. <a href=\"https://undsgn.com/uncode/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\">Uncode \u2013 Creative Multiuse WordPress Theme</a></h2>\n<p><a href=\"https://undsgn.com/uncode/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215604.jpg\" alt=\"\" width=\"1000\" height=\"415\" class=\"aligncenter size-full wp-image-168705\" /></a></p>\n<p>Uncode has proven to be one of the best WordPress themes for business websites. It&#39;s a multipurpose theme featuring 30+ homepage concepts designed to get designers and their clients off to a fast start on any small business website. Features include an eLine truncated
"protected": false
},
"excerpt": {
"rendered": "<p class=\"wp-special\"><em>This article was created in partnership with <a href=\"https://bawmedia.com/\" rel=\"nofollow\">BAWMedia</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p>A well-designed website can serve as a powerful marketing tool. These days, creating one for a small business is not distressing or expensive at all. However, it was just a few short years ago.</p>\n<p>Today, you can take advantage of the features provided by the best WordPress themes. There are special themes for small business-oriented websites. It&#39;s not difficult to find a website-building theme that matches a specific business. This can be a startup, a service provider, or some other venture.</p>\n<p>You undoubtedly want nothing but the best business theme, right? Check out those described below. Each possesses functional designs loaded with amazing features. They will help you create a thoroughly engaging website to promote a business.</p>\n<h2>1. <a href=\"http://themes.muffingroup.com/be/splash/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\">Be Theme</a></h2>\n<p><a href=\"http://themes.muffingroup.com/be/splash/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215231.png\" alt=\"\" width=\"1000\" height=\"481\" class=\"aligncenter size-full wp-image-168702\" /></a></p>\n<p>We&#8217;ll start with Be Theme, a responsive, multipurpose WordPress theme that takes every small business need into account with its more than 370 pre-built websites. There&#39;s a multiplicity of small business WordPress themes in this pre-built website collection \u2014 each one embedded with the functionality you need to establish an effective online presence, and fully customizable to meet your business and marketing needs.</p>\n<p>The range of business niches covered is impressive, With more pre-built websites being added every month it&#39;s destined to become even more so. Web designers like Be Theme because it allows them to create a website for most small business types in as little as four hours.</p>\n<p>Clients appreciate the rapid turnaround they receive and the ease in which changes or additions they have in mind can be accommodated.</p>\n<p>Be Theme, one of the best WordPress themes for small business websites is a ThemeForest top 5 best seller whose core features include easy to work with page-building tools, a multiplicity of design features and options, and great support.</p>\n<h2>2. <a href=\"http://bit.ly/2wxuUpA\" rel=\"nofollow\">Astra</a></h2>\n<p><a href=\"http://bit.ly/2wxuUpA\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215352.jpg\" alt=\"\" width=\"1000\" height=\"491\" class=\"aligncenter size-full wp-image-168703\" /></a></p>\n<p>Astra is fast, fully customizable, and one of the best WordPress themes for business websites as well as for blogs and personal portfolios. Built with SEO in mind, Astra is responsive and WooCommerce ready \u2014 mandatory features in today&#39;s online business environment. Its capabilities are easily extendible with premium addons and Astra can be used with most of the popular page builders. This free WP-based theme is definitely worth considering.</p>\n<h2 id=\"\">3. <a href=\"http://bit.ly/2oiQkTS\" rel=\"nofollow\">The100</a></h2>\n<p><a href=\"http://bit.ly/2oiQkTS\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215473.jpg\" alt=\"\" width=\"1000\" height=\"491\" class=\"aligncenter size-full wp-image-168704\" /></a></p>\n<p>A theme selected for WordPress for small businesses can be free or it can be a premium theme requiring an expenditure on your behalf. There are several excellent free themes on the market, and one of them is The100. While it is advertised as having premium-like features, bear in mind that free themes like this one generally can&#39;t compete with premium themes. Nevertheless, The100 is an easy-to-use WP theme that features a multiplicity of layouts and plenty of customization options.</p>\n<h2 id=\"\">4. <a href=\"https://undsgn.com/uncode/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\">Uncode \u2013 Creative Multiuse WordPress Theme</a></h2>\n<p><a href=\"https://undsgn.com/uncode/?utm_source=sitepoint.com&amp;utm_medium=content&amp;utm_campaign=wpstartups18\" rel=\"nofollow\"><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/15361215604.jpg\" alt=\"\" width=\"1000\" height=\"415\" class=\"aligncenter size-full wp-image-168705\" /></a></p>\n<p>Uncode has proven to be one of the best WordPress themes for business websites. It&#39;s a multipurpose theme featuring 30+ homepage concepts designed to get designers and their clients off to a fast start on any small business website. Features include an eLine truncated
"protected": false
},
"author": 72596,
"featured_media": 168703,
"comment_status": "open",
"ping_status": "closed",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
5856,
5849
],
"tags": [
11664,
9553,
6298
],
"_links": {
"self": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/168697"
}
],
"collection": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts"
}
],
"about": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/users/72596"
}
],
"replies": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/comments?post=168697"
}
],
"version-history": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/168697/revisions"
}
],
"wp:featuredmedia": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/media/168703"
}
],
"wp:attachment": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/media?parent=168697"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/categories?post=168697"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/tags?post=168697"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
}
},
{
"id": 168397,
"date": "2018-09-06T09:30:31",
"date_gmt": "2018-09-06T16:30:31",
"guid": {
"rendered": "https://www.sitepoint.com/?p=168397"
},
"modified": "2018-09-04T00:20:42",
"modified_gmt": "2018-09-04T07:20:42",
"slug": "integrating-mongodb-and-amazon-kinesis-for-intelligent-durable-streams",
"status": "publish",
"type": "post",
"link": "https://www.sitepoint.com/integrating-mongodb-and-amazon-kinesis-for-intelligent-durable-streams/",
"title": {
"rendered": "Integrating MongoDB and Amazon Kinesis for Intelligent, Durable Streams"
},
"content": {
"rendered": "<p class=\"wp-special\"><em>This article was originally published on <a href=\"https://synd.co/2NCzyKk\u200b\" rel=\"canonical\">MongoDB</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p>You can build your online, operational workloads atop MongoDB and still respond to events in real time by kicking off <a href=\"https://aws.amazon.com/kinesis/\">Amazon Kinesis</a> stream processing actions, using MongoDB Stitch Triggers.</p>\n<p>Let\u2019s look at an example scenario in which a stream of data is being generated as a result of actions users take on a website. We\u2019ll durably store the data and simultaneously feed a Kinesis process to do streaming analytics on something like cart abandonment, product recommendations, or even credit card fraud detection.</p>\n<p>We\u2019ll do this by setting up a Stitch Trigger. When relevant data updates are made in MongoDB, the trigger will use a Stitch Function to call out to AWS Kinesis, as you can see in this architecture diagram:</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536043981image5-d4wtr8tn5c.png\" alt=\"\" width=\"1525\" height=\"844\" class=\"aligncenter size-full wp-image-168426\" /></p>\n<h4 id=\"whatyoullneedtofollowalong\">What you\u2019ll need to follow along</h4>\n<ol>\n<li><strong>An Atlas instance</strong> <br />\nIf you don\u2019t already have an application running on Atlas, you can follow our <a href=\"https://docs.atlas.mongodb.com/getting-started/\">getting started with Atlas guide here</a>. In this example, we\u2019ll be using a database called <em><strong>streamdata</strong></em>, with a collection called <em><strong>clickdata</strong></em> where we\u2019re writing data from our web-based e-commerce application.</li>\n<li><strong>An AWS account and a Kinesis stream</strong> <br />\nIn this example, we\u2019ll use a Kinesis stream to send data downstream to additional applications such as Kinesis Analytics. This is the stream we want to feed our updates into.</li>\n<li><strong>A Stitch application</strong> <br />\nIf you don\u2019t already have a Stitch application, <a href=\"https://cloud.mongodb.com/user#/atlas/login\">log into Atlas</a>, and click <strong>Stitch Apps</strong> from the navigation on the left, then click <strong>Create New Application</strong>.</li>\n</ol>\n<h3 id=\"createacollection\">Create a Collection</h3>\n<p>The first step is to create a database and collection from the Stitch application console. Click <strong>Rules</strong> from the left navigation menu and click the <strong>Add Collection</strong> button. Type <strong>streamdata</strong> for the database and <strong>clickdata</strong> for the collection name. Select the template labeled Users can <strong>only read and write their own data</strong> and provide a field name where we\u2019ll specify the user id.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044010image2-51q4gsi7u2.png\" alt=\"Figure 2. Create a collection\" width=\"1999\" height=\"923\" class=\"aligncenter size-full wp-image-168427\" /></p>\n<h3 id=\"configuringstitchtotalktoaws\">Configuring Stitch to Talk to AWS</h3>\n<p>Stitch lets you configure <em>Services</em> to interact with external <a href=\"https://docs.mongodb.com/stitch/reference/partner-services/amazon-service/\">services such as AWS Kinesis</a>. Choose <strong>Services</strong> from the navigation on the left, and click the <strong>Add a Service</strong> button, select the AWS service and set <strong>AWS <a href=\"https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/\">Access Key ID, and Secret Access Key</a></strong>.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044038image8-2a9rr3qc4k.png\" alt=\"Figure 3. Service Configuration in Stitch\" width=\"1999\" height=\"1041\" class=\"aligncenter size-full wp-image-168428\" /></p>\n<p><em>Services</em> use <em>Rules</em> to specify what aspect of a service Stitch can use, and how. Add a rule which will enable that service to communicate with Kinesis by clicking the button labeled NEW RULE. Name the rule \u201ckinesis\u201d as we\u2019ll be using this specific rule to enable communication with AWS Kinesis. In the section marked Action, select the API labeled Kinesis and select All Actions.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044067image1-h45v2y48z7.gif\" alt=\"Figure 4. Add a rule to enable integration with Kinesis\" width=\"1424\" height=\"746\" class=\"aligncenter size-full wp-image-168429\" /></p>\n<h3 id=\"writeafunctionthatstreamsdocumentsintokinesis\">Write a Function that Streams Documents into Kinesis</h3>\n<p>Now that we have a working AWS service, we can use it to put records into a Kinesis stream. The way we do that in Stitch is with Functions. Let\u2019s set up a <em>putKinesisRecord</em> function.</p>\n<p>Select Functions from the left-hand menu, and click Create New Function. ProviLine truncated
"protected": false
},
"excerpt": {
"rendered": "<p class=\"wp-special\"><em>This article was originally published on <a href=\"https://synd.co/2NCzyKk\u200b\" rel=\"canonical\">MongoDB</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p>You can build your online, operational workloads atop MongoDB and still respond to events in real time by kicking off <a href=\"https://aws.amazon.com/kinesis/\">Amazon Kinesis</a> stream processing actions, using MongoDB Stitch Triggers.</p>\n<p>Let\u2019s look at an example scenario in which a stream of data is being generated as a result of actions users take on a website. We\u2019ll durably store the data and simultaneously feed a Kinesis process to do streaming analytics on something like cart abandonment, product recommendations, or even credit card fraud detection.</p>\n<p>We\u2019ll do this by setting up a Stitch Trigger. When relevant data updates are made in MongoDB, the trigger will use a Stitch Function to call out to AWS Kinesis, as you can see in this architecture diagram:</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536043981image5-d4wtr8tn5c.png\" alt=\"\" width=\"1525\" height=\"844\" class=\"aligncenter size-full wp-image-168426\" /></p>\n<h4 id=\"whatyoullneedtofollowalong\">What you\u2019ll need to follow along</h4>\n<ol>\n<li><strong>An Atlas instance</strong> <br />\nIf you don\u2019t already have an application running on Atlas, you can follow our <a href=\"https://docs.atlas.mongodb.com/getting-started/\">getting started with Atlas guide here</a>. In this example, we\u2019ll be using a database called <em><strong>streamdata</strong></em>, with a collection called <em><strong>clickdata</strong></em> where we\u2019re writing data from our web-based e-commerce application.</li>\n<li><strong>An AWS account and a Kinesis stream</strong> <br />\nIn this example, we\u2019ll use a Kinesis stream to send data downstream to additional applications such as Kinesis Analytics. This is the stream we want to feed our updates into.</li>\n<li><strong>A Stitch application</strong> <br />\nIf you don\u2019t already have a Stitch application, <a href=\"https://cloud.mongodb.com/user#/atlas/login\">log into Atlas</a>, and click <strong>Stitch Apps</strong> from the navigation on the left, then click <strong>Create New Application</strong>.</li>\n</ol>\n<h3 id=\"createacollection\">Create a Collection</h3>\n<p>The first step is to create a database and collection from the Stitch application console. Click <strong>Rules</strong> from the left navigation menu and click the <strong>Add Collection</strong> button. Type <strong>streamdata</strong> for the database and <strong>clickdata</strong> for the collection name. Select the template labeled Users can <strong>only read and write their own data</strong> and provide a field name where we\u2019ll specify the user id.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044010image2-51q4gsi7u2.png\" alt=\"Figure 2. Create a collection\" width=\"1999\" height=\"923\" class=\"aligncenter size-full wp-image-168427\" /></p>\n<h3 id=\"configuringstitchtotalktoaws\">Configuring Stitch to Talk to AWS</h3>\n<p>Stitch lets you configure <em>Services</em> to interact with external <a href=\"https://docs.mongodb.com/stitch/reference/partner-services/amazon-service/\">services such as AWS Kinesis</a>. Choose <strong>Services</strong> from the navigation on the left, and click the <strong>Add a Service</strong> button, select the AWS service and set <strong>AWS <a href=\"https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/\">Access Key ID, and Secret Access Key</a></strong>.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044038image8-2a9rr3qc4k.png\" alt=\"Figure 3. Service Configuration in Stitch\" width=\"1999\" height=\"1041\" class=\"aligncenter size-full wp-image-168428\" /></p>\n<p><em>Services</em> use <em>Rules</em> to specify what aspect of a service Stitch can use, and how. Add a rule which will enable that service to communicate with Kinesis by clicking the button labeled NEW RULE. Name the rule \u201ckinesis\u201d as we\u2019ll be using this specific rule to enable communication with AWS Kinesis. In the section marked Action, select the API labeled Kinesis and select All Actions.</p>\n<p><img src=\"https://www.sitepoint.com/wp-content/uploads/2018/09/1536044067image1-h45v2y48z7.gif\" alt=\"Figure 4. Add a rule to enable integration with Kinesis\" width=\"1424\" height=\"746\" class=\"aligncenter size-full wp-image-168429\" /></p>\n<h3 id=\"writeafunctionthatstreamsdocumentsintokinesis\">Write a Function that Streams Documents into Kinesis</h3>\n<p>Now that we have a working AWS service, we can use it to put records into a Kinesis stream. The way we do that in Stitch is with Functions. Let\u2019s set up a <em>putKinesisRecord</em> function.</p>\n<p>Select Functions from the left-hand menu, and click Create New Function. ProviLine truncated
"protected": false
},
"author": 72676,
"featured_media": 168458,
"comment_status": "open",
"ping_status": "closed",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
422
],
"tags": [
9553,
1599,
6298
],
"_links": {
"self": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/168397"
}
],
"collection": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts"
}
],
"about": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/users/72676"
}
],
"replies": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/comments?post=168397"
}
],
"version-history": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/168397/revisions"
}
],
"wp:featuredmedia": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/media/168458"
}
],
"wp:attachment": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/media?parent=168397"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/categories?post=168397"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/tags?post=168397"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
}
},
{
"id": 167869,
"date": "2018-09-05T09:30:47",
"date_gmt": "2018-09-05T16:30:47",
"guid": {
"rendered": "https://www.sitepoint.com/?p=167869"
},
"modified": "2018-09-06T01:21:52",
"modified_gmt": "2018-09-06T08:21:52",
"slug": "how-to-set-up-a-secure-relational-database-on-alibaba-cloud",
"status": "publish",
"type": "post",
"link": "https://www.sitepoint.com/how-to-set-up-a-secure-relational-database-on-alibaba-cloud/",
"title": {
"rendered": "How to Set up a Secure Relational Database on Alibaba Cloud"
},
"content": {
"rendered": "<p><iframe width=\"900\" height=\"506\" src=\"https://www.youtube.com/embed/c9YzHtgsiKE\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen></iframe></p>\n<p class=\"wp-special\"><em>This article was originally published on <a href=\"https://resource.alibabacloud.com/webinar/live.htm?spm=a2c5p.11425181.0.0.4d913c86X8D869&#038;webinarId=26\" rel=\"canonical\">Alibaba Cloud</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p class=\"wp-special\"><strong>Think you got a better tip for making the best use of Alibaba Cloud services? Tell us about it and go in for your chance to win a Macbook Pro (plus other cool stuff). <a href=\"https://www.sitepoint.com/alibaba-competition\">Find out more here</a>.</strong></p>\n<p>Gain an introduction to ApsaraDB for RDS, a cloud-based relational database product provided by Alibaba Cloud. In this webinar you will watch over the shoulder of a Solution Architect and Trainer, as he covers the basic concepts and features of ApsaraDB for RDS including:</p>\n<ul>\n<li>HA feature (Master/Slave Architecture, Backup/Recovery, Temporary Instance)</li>\n<li>Scalability features (Read-only Instance)</li>\n<li>Security and Monitoring features</li>\n</ul>\n<p>This webinar is ideally suited for database engineers and beginners to the Alibaba Cloud product suite.</p>\n",
"protected": false
},
"excerpt": {
"rendered": "<p><iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/c9YzHtgsiKE\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen></iframe></p>\n<p class=\"wp-special\"><em>This article was originally published on <a href=\"https://resource.alibabacloud.com/webinar/live.htm?spm=a2c5p.11425181.0.0.4d913c86X8D869&#038;webinarId=26\" rel=\"canonical\">Alibaba Cloud</a>. Thank you for supporting the partners who make SitePoint possible.</em></p>\n<p>Gain an introduction to ApsaraDB for RDS, a cloud-based relational database product provided by Alibaba Cloud. In this webinar you will watch over the shoulder of a Solution Architect and Trainer, as he covers the basic concepts and features of ApsaraDB for RDS including:</p>\n<ul>\n<li>HA feature (Master/Slave Architecture, Backup/Recovery, Temporary Instance)</li>\n<li>Scalability features (Read-only Instance)</li>\n<li>Security and Monitoring features</li>\n</ul>\n<p>This webinar is ideally suited for database engineers and beginners to the Alibaba Cloud product suite.</p>\n",
"protected": false
},
"author": 72596,
"featured_media": 167879,
"comment_status": "open",
"ping_status": "closed",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
1292,
422
],
"tags": [
11731,
9553
],
"_links": {
"self": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/167869"
}
],
"collection": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts"
}
],
"about": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/users/72596"
}
],
"replies": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/comments?post=167869"
}
],
"version-history": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/posts/167869/revisions"
}
],
"wp:featuredmedia": [
{
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/media/167879"
}
],
"wp:attachment": [
{
"href": "https://www.sitepoint.com/wp-json/wp/v2/media?parent=167869"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/categories?post=167869"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://www.sitepoint.com/wp-json/wp/v2/tags?post=167869"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
}
}
]