Skip to content

Commit 4634719

Browse files
author
ehennum
committed
lazy conversion from JsonNode for Optic enhancements #1282
1 parent fb21bfe commit 4634719

File tree

2 files changed

+88
-146
lines changed

2 files changed

+88
-146
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/impl/RowManagerImpl.java

Lines changed: 85 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -800,17 +800,14 @@ public RowRecord next() {
800800
private Object getColumnValue(String columnName, JsonNode columnNode) {
801801
JsonNodeType nodeType = columnNode.getNodeType();
802802
switch(nodeType) {
803-
case ARRAY:
804-
case OBJECT:
805-
return columnNode;
806-
case BOOLEAN:
807-
return columnNode.booleanValue();
808803
case NULL:
809804
return null;
805+
case ARRAY:
806+
case BOOLEAN:
810807
case NUMBER:
811-
return columnNode.numberValue();
808+
case OBJECT:
812809
case STRING:
813-
return columnNode.textValue();
810+
return columnNode;
814811
case BINARY:
815812
case MISSING:
816813
case POJO:
@@ -1128,101 +1125,79 @@ public String getString(PlanExprCol col) {
11281125
}
11291126
@Override
11301127
public String getString(String columnName) {
1131-
try {
1132-
return asString(get(columnName));
1133-
} catch(NodeNotAStringException e) {
1134-
throw new IllegalArgumentException("value for column \""+columnName+"\" not a string");
1135-
}
1128+
return asString(columnName, get(columnName));
11361129
}
11371130

11381131
private boolean asBoolean(String columnName, Object value) {
1139-
if (value == null) {
1140-
throw new IllegalStateException("column "+columnName+" has null instead of boolean value");
1141-
} else if (value instanceof Boolean) {
1142-
return ((Boolean) value).booleanValue();
1143-
} else if (value instanceof String) {
1144-
return Boolean.parseBoolean((String) value);
1145-
}
1146-
throw new IllegalStateException("column "+columnName+" does not have a boolean value");
1132+
return asPrimitiveValueNode(columnName, value).asBoolean();
11471133
}
11481134
private byte asByte(String columnName, Object value) {
1149-
if (value == null) {
1150-
throw new IllegalStateException("column "+columnName+" has null instead of byte value");
1151-
} else if (value instanceof Number) {
1152-
return ((Number) value).byteValue();
1153-
} else if (value instanceof String) {
1154-
return Byte.parseByte((String) value);
1155-
}
1156-
throw new IllegalStateException("column "+columnName+" does not have a byte value");
1135+
return (byte) asPrimitiveValueNode(columnName, value).asInt();
11571136
}
11581137
private double asDouble(String columnName, Object value) {
1159-
if (value == null) {
1160-
throw new IllegalStateException("column "+columnName+" has null instead of double value");
1161-
} else if (value instanceof Number) {
1162-
return ((Number) value).doubleValue();
1163-
} else if (value instanceof String) {
1164-
return Double.parseDouble((String) value);
1165-
}
1166-
throw new IllegalStateException("column "+columnName+" does not have a double value");
1138+
return asPrimitiveValueNode(columnName, value).asDouble();
11671139
}
11681140
private float asFloat(String columnName, Object value) {
1169-
if (value == null) {
1170-
throw new IllegalStateException("column "+columnName+" has null instead of float value");
1171-
} else if (value instanceof Number) {
1172-
return ((Number) value).floatValue();
1173-
} else if (value instanceof String) {
1174-
return Float.parseFloat((String) value);
1175-
}
1176-
throw new IllegalStateException("column "+columnName+" does not have a float value");
1141+
return (float) asPrimitiveValueNode(columnName, value).asDouble();
11771142
}
11781143
private int asInt(String columnName, Object value) {
1179-
if (value == null) {
1180-
throw new IllegalStateException("column "+columnName+" has null instead of integer value");
1181-
} else if (value instanceof Number) {
1182-
return ((Number) value).intValue();
1183-
} else if (value instanceof String) {
1184-
return Integer.parseInt((String) value);
1185-
}
1186-
throw new IllegalStateException("column "+columnName+" does not have an integer value");
1144+
return asPrimitiveValueNode(columnName, value).asInt();
11871145
}
11881146
private long asLong(String columnName, Object value) {
1189-
if (value == null) {
1190-
throw new IllegalStateException("column "+columnName+" has null instead of long value");
1191-
} else if (value instanceof Number) {
1192-
return ((Number) value).longValue();
1193-
} else if (value instanceof String) {
1194-
return Long.parseLong((String) value);
1195-
}
1196-
throw new IllegalStateException("column "+columnName+" does not have a long value");
1147+
return asPrimitiveValueNode(columnName, value).asLong();
11971148
}
11981149
private short asShort(String columnName, Object value) {
1150+
return (short) asPrimitiveValueNode(columnName, value).asInt();
1151+
}
1152+
private String asString(String columnName, Object value) {
11991153
if (value == null) {
1200-
throw new IllegalStateException("column "+columnName+" has null instead of short value");
1201-
} else if (value instanceof Number) {
1202-
return ((Number) value).shortValue();
1203-
} else if (value instanceof String) {
1204-
return Short.parseShort((String) value);
1205-
}
1206-
throw new IllegalStateException("column "+columnName+" does not have a short value");
1207-
}
1208-
/**
1209-
* @throws NodeNotAStringException when the value is a node but not a single text node
1210-
* (with content-type "text/plain")
1211-
*/
1212-
private String asString(Object value) throws NodeNotAStringException {
1213-
if (value == null || value instanceof String) {
1214-
return (String) value;
1154+
return null;
12151155
} else if (value instanceof JsonNode) {
1216-
return ((JsonNode) value).toPrettyString();
1156+
JsonNode node = (JsonNode) value;
1157+
if (node.isNull()) {
1158+
return null;
1159+
} else if (node.isValueNode()) {
1160+
return node.asText();
1161+
} else if (node.isContainerNode()) {
1162+
return node.toPrettyString();
1163+
}
12171164
} else if (value instanceof RESTServiceResult) {
12181165
RESTServiceResult result = (RESTServiceResult) value;
1219-
if ( result.getMimetype() != null && result.getMimetype().startsWith("text/plain") ) {
1166+
Format format = result.getFormat();
1167+
if (format != null && format != Format.BINARY) {
12201168
return result.getContent(new StringHandle()).get();
1221-
} else {
1222-
throw new NodeNotAStringException();
12231169
}
12241170
}
1225-
return value.toString();
1171+
throw new IllegalStateException("column "+columnName+" cannot convert to string");
1172+
}
1173+
1174+
private JsonNode asPrimitiveValueNode(String columnName, Object value) {
1175+
JsonNode node = asAtomicValueNode(columnName, value);
1176+
if (node == null) {
1177+
throw new IllegalStateException("column "+columnName+" has null instead of primitive value");
1178+
}
1179+
return node;
1180+
}
1181+
private JsonNode asAtomicValueNode(String columnName, Object value) {
1182+
JsonNode node = asJsonNode(columnName, value);
1183+
if (node != null && !node.isValueNode()) {
1184+
throw new IllegalStateException("column "+columnName+" does not have an atomic value");
1185+
}
1186+
return node;
1187+
}
1188+
private JsonNode asJsonNode(String columnName, Object value) {
1189+
if (value == null) {
1190+
return null;
1191+
}
1192+
JsonNode node;
1193+
if (value instanceof JsonNode) {
1194+
node = (JsonNode) value;
1195+
} else if (value instanceof RESTServiceResult && getContentFormat(columnName) == Format.JSON) {
1196+
node = ((RESTServiceResult) value).getContent(new JacksonHandle()).get();
1197+
} else {
1198+
throw new IllegalStateException("column "+columnName+" does not have a value");
1199+
}
1200+
return node.isNull() ? null : node;
12261201
}
12271202

12281203
private RESTServiceResult getServiceResult(String columnName) {
@@ -1243,21 +1218,13 @@ public <T extends XsAnyAtomicTypeVal> T getValueAs(String columnName, Class<T> a
12431218
throw new IllegalArgumentException("cannot construct "+columnName+" value with null class");
12441219
}
12451220

1246-
Object value = get(columnName);
1247-
if (value == null) {
1248-
return null;
1249-
}
1250-
1251-
if (as.isInstance(value)) {
1252-
return as.cast(value);
1253-
}
1254-
12551221
try {
1256-
String valueStr = asString(value);
1257-
if (String.class.isAssignableFrom(as)) {
1258-
return as.cast(valueStr);
1222+
JsonNode node = asAtomicValueNode(columnName, get(columnName));
1223+
if (node == null) {
1224+
return null;
12591225
}
12601226

1227+
String valueStr = node.asText();
12611228
Function<String,? extends XsAnyAtomicTypeVal> factory = getFactory(as);
12621229
if (factory != null) {
12631230
return as.cast(factory.apply(valueStr));
@@ -1272,8 +1239,6 @@ public <T extends XsAnyAtomicTypeVal> T getValueAs(String columnName, Class<T> a
12721239
}
12731240

12741241
return constructor.newInstance(valueStr);
1275-
} catch(NodeNotAStringException e) {
1276-
throw new IllegalArgumentException("column \""+columnName+"\" is a node, not an atomic");
12771242
} catch(NoSuchMethodException e) {
12781243
throw new IllegalArgumentException("cannot construct "+columnName+" value as class: "+as.getName());
12791244
} catch (InstantiationException e) {
@@ -1392,15 +1357,6 @@ public <T> T getContainerAs(String columnName, Class<T> as) {
13921357
return handle.get();
13931358
}
13941359

1395-
private JsonNode asJsonNode(String columnName, Object value) {
1396-
if (value == null || value instanceof JsonNode) {
1397-
return (JsonNode) value;
1398-
} else if (value instanceof RESTServiceResult) {
1399-
return ((RESTServiceResult) value).getContent(new JacksonHandle()).get();
1400-
}
1401-
throw new IllegalStateException("column "+columnName+" does not have a JSON container value");
1402-
}
1403-
14041360
@Override
14051361
public Format getContentFormat(PlanExprCol col) {
14061362
return getContentFormat(getNameForColumn(col));
@@ -1506,40 +1462,39 @@ public String toString() {
15061462

15071463
switch(colKind) {
15081464
case ATOMIC_VALUE:
1465+
String atomicVal = getString(colName);
15091466
buf.append("value: ");
1510-
1511-
String colVal = getString(colName);
1512-
1513-
switch(colType) {
1514-
case "xs:boolean":
1515-
case "xs:byte":
1516-
case "xs:decimal":
1517-
case "xs:double":
1518-
case "xs:float":
1519-
case "xs:int":
1520-
case "xs:integer":
1521-
case "xs:long":
1522-
case "xs:short":
1523-
case "xs:unsignedByte":
1524-
case "xs:unsignedInt":
1525-
case "xs:unsignedLong":
1526-
case "xs:unsignedShort":
1527-
buf.append(colVal);
1528-
break;
1529-
default:
1530-
if (colVal == null) {
1531-
buf.append("null");
1532-
} else {
1467+
if (atomicVal == null) {
1468+
buf.append("null");
1469+
} else {
1470+
switch(colType) {
1471+
case "xs:boolean":
1472+
case "xs:byte":
1473+
case "xs:decimal":
1474+
case "xs:double":
1475+
case "xs:float":
1476+
case "xs:int":
1477+
case "xs:integer":
1478+
case "xs:long":
1479+
case "xs:short":
1480+
case "xs:unsignedByte":
1481+
case "xs:unsignedInt":
1482+
case "xs:unsignedLong":
1483+
case "xs:unsignedShort":
1484+
buf.append(atomicVal);
1485+
break;
1486+
default:
15331487
buf.append("\"");
1534-
buf.append(colVal.replace("\"", "\\\""));
1488+
buf.append(atomicVal.replace("\"", "\\\""));
15351489
buf.append("\"");
1536-
}
1537-
break;
1490+
break;
1491+
}
15381492
}
15391493
break;
15401494
case CONTAINER_VALUE:
1495+
String containerVal = getString(colName);
15411496
buf.append("value: ");
1542-
buf.append(getString(colName));
1497+
buf.append((containerVal == null) ? "null" : containerVal);
15431498
break;
15441499
case CONTENT:
15451500
buf.append("format: \"");
@@ -1812,7 +1767,4 @@ public RawPlanDefinition withHandle(JSONWriteHandle handle) {
18121767
return this;
18131768
}
18141769
}
1815-
1816-
private static class NodeNotAStringException extends Exception {
1817-
}
18181770
}

marklogic-client-api/src/test/java/com/marklogic/client/test/RowManagerTest.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -530,25 +530,15 @@ public void testJoinSrcDoc() throws IOException {
530530
String[] firstName = {"Louis", "Miles"};
531531

532532
int rowNum = 0;
533-
boolean didARowFail = false;
534533
for (RowRecord row: rowMgr.resultRows(builtPlan)) {
535534
assertEquals("unexpected lastName value in row record "+rowNum, lastName[rowNum], row.getString("lastName"));
536535
assertEquals("unexpected firstName value in row record "+rowNum, firstName[rowNum], row.getString("firstName"));
537536

538-
String instruments;
539-
try {
540-
instruments = row.getString("instruments");
541-
} catch (IllegalArgumentException e ) {
542-
didARowFail = true;
543-
instruments = row.getContentAs("instruments", String.class);
544-
}
545-
assertNotNull("null instrucments value in row record "+rowNum, instruments);
546-
assertTrue("unexpected instrucments value in row record "+rowNum, instruments.contains("trumpet"));
537+
String instruments = row.getString("instruments");
538+
assertNotNull("null instruments value in row record "+rowNum, instruments);
539+
assertTrue("unexpected instruments value in row record "+rowNum, instruments.contains("trumpet"));
547540
rowNum++;
548541
}
549-
if ( didARowFail == false ) {
550-
fail("getString(\"instruments\") should throw an exception since some rows return an array");
551-
}
552542
assertEquals("unexpected count of result records", 2, rowNum);
553543
}
554544
@Test

0 commit comments

Comments
 (0)