Skip to content

Commit 352af2d

Browse files
authored
Merge pull request #11 from JavaWebStack/dev
Release 1.0.1
2 parents f8505a2 + c8df0bf commit 352af2d

16 files changed

+578
-64
lines changed

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
<artifactId>snakeyaml</artifactId>
4747
<version>1.29</version>
4848
</dependency>
49+
<dependency>
50+
<groupId>org.mongodb</groupId>
51+
<artifactId>bson</artifactId>
52+
<version>4.4.1</version>
53+
<optional>true</optional>
54+
</dependency>
4955
</dependencies>
5056

5157
<build>

src/main/java/org/javawebstack/abstractdata/AbstractArray.java

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package org.javawebstack.abstractdata;
22

3+
import org.javawebstack.abstractdata.collector.AbstractArrayCollector;
4+
35
import java.util.*;
6+
import java.util.function.Function;
7+
import java.util.stream.Collector;
48
import java.util.stream.Stream;
59

610
public class AbstractArray implements AbstractElement, Iterable<AbstractElement> {
@@ -289,4 +293,12 @@ public AbstractElement clone() {
289293
return array;
290294
}
291295

296+
public static <T> Collector<T, ?, AbstractArray> collect(Function<T, AbstractElement> mappingFunction) {
297+
return new AbstractArrayCollector<>(mappingFunction);
298+
}
299+
300+
public static <T extends AbstractElement> Collector<T, ?, AbstractArray> collect() {
301+
return new AbstractArrayCollector<>(e -> e);
302+
}
303+
292304
}

src/main/java/org/javawebstack/abstractdata/AbstractElement.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.javawebstack.abstractdata;
22

3+
import org.bson.BsonValue;
4+
import org.javawebstack.abstractdata.bson.BsonConverter;
5+
import org.javawebstack.abstractdata.bson.BsonTypeAdapter;
36
import org.javawebstack.abstractdata.json.JsonDumper;
47
import org.javawebstack.abstractdata.json.JsonParser;
58
import org.javawebstack.abstractdata.util.QueryString;
@@ -73,6 +76,14 @@ default Number number() {
7376
return primitive().number();
7477
}
7578

79+
default BsonValue toBson() {
80+
return new BsonConverter().toBson(this);
81+
}
82+
83+
default byte[] toBsonBytes() {
84+
return (byte[]) new BsonTypeAdapter().fromAbstract(null, this, byte[].class);
85+
}
86+
7687
default String toJsonString(boolean pretty) {
7788
return new JsonDumper().setPretty(pretty).dump(this);
7889
}
@@ -154,6 +165,14 @@ default String toFormDataString() {
154165
return toFormData().toString();
155166
}
156167

168+
static AbstractElement fromBson(BsonValue value) {
169+
return new BsonConverter().toAbstract(value);
170+
}
171+
172+
static AbstractElement fromBson(byte[] value) {
173+
return new BsonTypeAdapter().toAbstract(null, value);
174+
}
175+
157176
AbstractElement clone();
158177

159178
Map<String[], Object> toTree();
@@ -162,8 +181,7 @@ static AbstractElement fromJson(String json) {
162181
try {
163182
return new JsonParser().parse(json);
164183
} catch (ParseException e) {
165-
e.printStackTrace();
166-
return null;
184+
throw new RuntimeException(e);
167185
}
168186
}
169187

@@ -212,4 +230,5 @@ public boolean isPrimitive() {
212230
return this == NUMBER || this == BOOLEAN || this == STRING;
213231
}
214232
}
233+
215234
}

src/main/java/org/javawebstack/abstractdata/AbstractMapper.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,39 @@
22

33
import org.javawebstack.abstractdata.mapper.Mapper;
44

5+
@Deprecated
56
public class AbstractMapper {
67

78
private final Mapper mapper = new Mapper();
89
private NamingPolicy namingPolicy = NamingPolicy.NONE;
910
private String dateFormat = "yyyy-MM-dd HH:mm:ss";
10-
private boolean exposeRequired = false;
1111

1212
public AbstractMapper setNamingPolicy(NamingPolicy namingPolicy) {
1313
this.namingPolicy = namingPolicy;
1414
mapper.namingPolicy(namingPolicy.getMapperPolicy());
1515
return this;
1616
}
1717

18+
public boolean shouldOmitNull() {
19+
return mapper.shouldOmitNull();
20+
}
21+
22+
public AbstractMapper setOmitNull(boolean omitNull) {
23+
this.mapper.omitNull(omitNull);
24+
return this;
25+
}
26+
1827
public NamingPolicy getNamingPolicy() {
1928
return namingPolicy;
2029
}
2130

2231
public AbstractMapper setExposeRequired(boolean exposeRequired) {
23-
this.exposeRequired = exposeRequired;
2432
mapper.requireExpose(exposeRequired);
2533
return this;
2634
}
2735

2836
public boolean isExposeRequired() {
29-
return exposeRequired;
37+
return mapper.isExposeRequired();
3038
}
3139

3240
public AbstractMapper setDateFormat(String dateFormat) {

src/main/java/org/javawebstack/abstractdata/AbstractObject.java

+13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package org.javawebstack.abstractdata;
22

3+
import org.javawebstack.abstractdata.collector.AbstractObjectCollector;
4+
35
import java.lang.reflect.Field;
46
import java.util.HashMap;
57
import java.util.LinkedHashMap;
68
import java.util.Map;
79
import java.util.Set;
810
import java.util.function.BiConsumer;
11+
import java.util.function.Function;
12+
import java.util.stream.Collector;
13+
import java.util.stream.Stream;
914

1015
public class AbstractObject implements AbstractElement {
1116

@@ -207,10 +212,18 @@ public AbstractArray values() {
207212
return AbstractArray.fromList(entries.values());
208213
}
209214

215+
public Stream<Map.Entry<String, AbstractElement>> stream() {
216+
return entries().stream();
217+
}
218+
210219
public AbstractElement clone() {
211220
AbstractObject object = new AbstractObject();
212221
forEach((k, v) -> object.set(k, v.clone()));
213222
return object;
214223
}
215224

225+
public static <T> Collector<T, ?, AbstractObject> collect(Function<T, String> keyFunction, Function<T, AbstractElement> valueFunction) {
226+
return new AbstractObjectCollector<>(keyFunction, valueFunction);
227+
}
228+
216229
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package org.javawebstack.abstractdata.bson;
2+
3+
import org.bson.*;
4+
import org.bson.internal.Base64;
5+
import org.bson.types.Decimal128;
6+
import org.bson.types.ObjectId;
7+
import org.javawebstack.abstractdata.*;
8+
9+
import java.text.DateFormat;
10+
import java.text.ParseException;
11+
import java.text.SimpleDateFormat;
12+
import java.util.Date;
13+
14+
public class BsonConverter {
15+
16+
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
17+
18+
public BsonConverter dateFormat(DateFormat dateFormat) {
19+
this.dateFormat = dateFormat;
20+
return this;
21+
}
22+
23+
public BsonConverter dateFormat(String format) {
24+
return dateFormat(new SimpleDateFormat(format));
25+
}
26+
27+
public AbstractObject toAbstract(ObjectId value) {
28+
return new AbstractObject().set("$oid", value.toHexString());
29+
}
30+
31+
public AbstractObject toAbstract(Decimal128 value) {
32+
return new AbstractObject().set("$numberDecimal", value.toString());
33+
}
34+
35+
public AbstractElement toAbstract(BsonValue value) {
36+
switch (value.getBsonType()) {
37+
case NULL:
38+
return AbstractNull.INSTANCE;
39+
case STRING:
40+
return new AbstractPrimitive(value.asString().getValue());
41+
case BOOLEAN:
42+
return new AbstractPrimitive(value.asBoolean().getValue());
43+
case INT32:
44+
return new AbstractPrimitive(value.asInt32().getValue());
45+
case INT64:
46+
return new AbstractPrimitive(value.asInt64().getValue());
47+
case DOUBLE:
48+
return new AbstractPrimitive(value.asDouble().getValue());
49+
case OBJECT_ID:
50+
return toAbstract(value.asObjectId().getValue());
51+
case DATE_TIME:
52+
return new AbstractObject().set("$date", dateFormat.format(new Date(value.asDateTime().getValue())));
53+
case UNDEFINED:
54+
return new AbstractObject().set("$undefined", true);
55+
case SYMBOL:
56+
return new AbstractObject().set("$symbol", value.asSymbol().getSymbol());
57+
case MIN_KEY:
58+
return new AbstractObject().set("$minKey", 1);
59+
case MAX_KEY:
60+
return new AbstractObject().set("$maxKey", 1);
61+
case JAVASCRIPT:
62+
return new AbstractObject().set("$code", value.asJavaScript().getCode());
63+
case JAVASCRIPT_WITH_SCOPE:
64+
return new AbstractObject()
65+
.set("$code", value.asJavaScriptWithScope().getCode())
66+
.set("$scope", toAbstract(value.asJavaScriptWithScope().getScope()));
67+
case DECIMAL128:
68+
return toAbstract(value.asDecimal128().getValue());
69+
case REGULAR_EXPRESSION:
70+
return new AbstractObject().set("$regularExpression", new AbstractObject()
71+
.set("pattern", value.asRegularExpression().getPattern())
72+
.set("options", value.asRegularExpression().getOptions())
73+
);
74+
case TIMESTAMP:
75+
return new AbstractObject().set("$timestamp", new AbstractObject()
76+
.set("t", Integer.toUnsignedLong(value.asTimestamp().getTime()))
77+
.set("i", Integer.toUnsignedLong(value.asTimestamp().getInc()))
78+
);
79+
case BINARY:
80+
return new AbstractObject().set("$binary", new AbstractObject()
81+
.set("base64", Base64.encode(value.asBinary().getData()))
82+
.set("subType", String.format("%02x", value.asBinary().getType()))
83+
);
84+
case ARRAY: {
85+
AbstractArray a = new AbstractArray();
86+
value.asArray().forEach(v -> a.add(toAbstract(v)));
87+
return a;
88+
}
89+
case DOCUMENT: {
90+
AbstractObject o = new AbstractObject();
91+
value.asDocument().forEach((k, v) -> o.set(k, toAbstract(v)));
92+
return o;
93+
}
94+
}
95+
throw new UnsupportedOperationException("Unsupported Bson Type: " + value.getBsonType().name());
96+
}
97+
98+
public BsonValue toBson(AbstractElement element) {
99+
if(element == null || element.isNull())
100+
return BsonNull.VALUE;
101+
if(element.isString())
102+
return new BsonString(element.string());
103+
if(element.isBoolean())
104+
return new BsonBoolean(element.bool());
105+
if(element.isNumber()) {
106+
Number n = element.number();
107+
if(n instanceof Integer || n instanceof Short || n instanceof Byte) {
108+
return new BsonInt32(n.intValue());
109+
} else if(n instanceof Long) {
110+
return new BsonInt64(n.longValue());
111+
} else if(n instanceof Float || n instanceof Double) {
112+
return new BsonDouble(n.doubleValue());
113+
}
114+
}
115+
if(element.isArray()) {
116+
BsonArray a = new BsonArray();
117+
for(AbstractElement e : element.array())
118+
a.add(toBson(e));
119+
return a;
120+
}
121+
AbstractObject o = element.object();
122+
if(o.size() == 1 && o.has("$oid") && o.get("$oid").isString())
123+
return new BsonObjectId(new ObjectId(o.string("$oid")));
124+
if(o.size() == 1 && o.has("$undefined") && o.get("$undefined").isBoolean())
125+
return new BsonUndefined();
126+
if(o.size() == 1 && o.has("$date") && o.get("$date").isString()) {
127+
try {
128+
return new BsonDateTime(dateFormat.parse(o.string("$date")).getTime());
129+
} catch (ParseException ignored) {}
130+
}
131+
if(o.size() == 1 && o.has("$numberDecimal") && o.get("$numberDecimal").isString())
132+
return new BsonDecimal128(Decimal128.parse(o.string("$numberDecimal")));
133+
if(o.size() == 1 && o.has("$minKey") && o.get("$minKey").isNumber())
134+
return new BsonMinKey();
135+
if(o.size() == 1 && o.has("$maxKey") && o.get("$maxKey").isNumber())
136+
return new BsonMinKey();
137+
if(o.size() == 1 && o.has("$symbol") && o.get("$symbol").isString())
138+
return new BsonSymbol(o.string("$symbol"));
139+
if(o.size() == 1 && o.has("$code") && o.get("$code").isString())
140+
return new BsonJavaScript(o.string("$code"));
141+
if(o.size() == 2 && o.has("$code") && o.has("$scope") && o.get("$code").isString() && o.get("$scope").isObject())
142+
return new BsonJavaScriptWithScope(o.string("$code"), toBson(o.get("$scope")).asDocument());
143+
if(o.size() == 1 && o.has("$timestamp") && o.get("$timestamp").isObject()) {
144+
AbstractObject ts = o.object("$timestamp");
145+
if(ts.has("t") && ts.has("i") && ts.get("t").isNumber() && ts.get("i").isNumber()) {
146+
return new BsonTimestamp((int) ts.number("t").longValue(), (int) ts.number("i").longValue());
147+
}
148+
}
149+
if(o.size() == 1 && o.has("$regularExpression") && o.get("$regularExpression").isObject()) {
150+
AbstractObject re = o.object("$regularExpression");
151+
if(re.has("pattern") && re.has("options") && re.get("pattern").isString() && (re.get("options").isString() || re.get("options").isNull())) {
152+
return new BsonRegularExpression(re.string("pattern"), (String) re.toObject());
153+
}
154+
}
155+
if(o.size() == 1 && o.has("$binary") && o.get("$binary").isObject()) {
156+
AbstractObject bin = o.object("$binary");
157+
if(bin.has("base64") && bin.has("subType") && bin.get("base64").isString() && bin.get("subType").isString()) {
158+
byte[] data = Base64.decode(bin.string("base64"));
159+
byte type = (byte) Integer.parseInt(bin.string("subType"), 16);
160+
return new BsonBinary(type, data);
161+
}
162+
}
163+
BsonDocument doc = new BsonDocument(o.size());
164+
for(String k : o.keys())
165+
doc.put(k, toBson(o.get(k)));
166+
return doc;
167+
}
168+
169+
}

0 commit comments

Comments
 (0)