Skip to content

Commit

Permalink
Merge pull request #49 from jsonx-org/binding
Browse files Browse the repository at this point in the history
External binding schema
  • Loading branch information
safris committed Sep 29, 2023
2 parents d3e4ca2 + 03d7cce commit c8c9800
Show file tree
Hide file tree
Showing 97 changed files with 7,003 additions and 4,619 deletions.
4 changes: 3 additions & 1 deletion binding/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,9 @@ The following illustrates usage of the <ins>binding API</ins> with an example of
<phase>generate-sources</phase>
<configuration>
<destDir>${project.build.directory}/generated-sources/jsonx</destDir>
<prefix>com.example.invoice.</prefix>
<namespacePackages>
<namespacePackage package="com.example.invoice."/>
</namespacePackages>
<schemas>
<schema>src/main/resources/invoice.jsd</schema> <!-- or invoice.jsdx -->
</schemas>
Expand Down
2 changes: 1 addition & 1 deletion binding/src/main/java/org/jsonx/ClassToGetMethods.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.function.Predicate;

abstract class ClassToGetMethods extends HashMap<Class<? extends JxObject>,Method[]> implements Predicate<Method> {
private static final Method[] emptyMethods = new Method[0];
private static final Method[] emptyMethods = {};

private Method[] getGetMethods(final Method[] methods, final int length, final int index, final int depth) {
if (index == length)
Expand Down
10 changes: 7 additions & 3 deletions binding/src/main/java/org/jsonx/JsdUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import org.libj.util.Comparators;

final class JsdUtil {
static final Comparator<String> ATTRIBUTES = Comparators.newFixedOrderComparator("id", "name", "names", "xsi:type", "abstract", "extends", "lang", "type", "field", "types", "booleans", "numbers", "objects", "strings", "elementIds", "scale", "range", "pattern", "use", "minIterate", "maxIterate", "minOccurs", "maxOccurs", "nullable", "decode", "encode");
static final Comparator<String> ATTRIBUTES = Comparators.newFixedOrderComparator("jx:ns", "jx:type", "id", "name", "names", "xsi:type", "abstract", "extends", "lang", "type", "field", "types", "booleans", "numbers", "objects", "strings", "elementIds", "scale", "range", "pattern", "use", "minIterate", "maxIterate", "minOccurs", "maxOccurs", "nullable", "decode", "encode");
private static final char prefix = '_';
private static final Function<Character,String> classSubs = c -> c == null ? "_" : c != '_' ? Integer.toHexString(c) : "__";
private static final Function<Character,String> camelSubs = c -> c == null ? "_" : c == '-' ? "-" : c != '_' ? Integer.toHexString(c) : "__";
Expand Down Expand Up @@ -65,7 +65,7 @@ private static String toIdentifier(final String name, final Boolean classCase) {
return str.charAt(0) == prefix && name.charAt(0) != prefix ? str.substring(1) : str;
}

return Identifiers.toInstanceCase(name, prefix, classSubs);
return getFieldName(name);
}

static String toIdentifier(final String name) {
Expand All @@ -81,8 +81,12 @@ static String toInstanceName(String name) {
return Arrays.binarySearch(reservedWords, name) < 0 ? name : "_" + name;
}

static String getFieldName(final String name) {
return Identifiers.toInstanceCase(name, prefix, classSubs);
}

static String getFieldName(final Method getMethod) {
return Identifiers.toInstanceCase(getMethod.getName().substring(3));
return getFieldName(getMethod.getName().substring(3));
}

static Class<?> getRealType(final Method getMethod) {
Expand Down
4 changes: 2 additions & 2 deletions binding/src/main/java/org/jsonx/JxDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ public JxDecoder build() {
}
}

public static JxDecoder VALIDATING = new JxDecoder(true, null);
public static JxDecoder NON_VALIDATING = new JxDecoder(false, null);
public static final JxDecoder VALIDATING = new JxDecoder(true, null);
public static final JxDecoder NON_VALIDATING = new JxDecoder(false, null);

private static JxDecoder global = new JxDecoder(false);

Expand Down
44 changes: 21 additions & 23 deletions binding/src/main/java/org/jsonx/ObjectCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,32 +105,30 @@ else if (codec instanceof PrimitiveCodec) {

value = primitiveCodec.parse(new String(buf, off, len), reader.isStrict());
}
else if (codec instanceof AnyCodec) {
final AnyCodec anyCodec = (AnyCodec)codec;
final String token = new String(buf, off, len);
value = AnyCodec.decode(anyCodec.property, token, reader, validate, null);
}
else {
if (codec instanceof AnyCodec) {
final AnyCodec anyCodec = (AnyCodec)codec;
final String token = new String(buf, off, len);
value = AnyCodec.decode(anyCodec.property, token, reader, validate, null);
c0 = reader.bufToChar(off);
if (codec instanceof ObjectCodec) {
if (c0 != '{')
return abort(Error.EXPECTED_TOKEN(codec.name, codec.elementName(), new String(buf, off, len), reader), reader, index);

final ObjectCodec objectCodec = (ObjectCodec)codec;
value = decodeObject(objectCodec.type, reader, validate, null); // NOTE: Setting `onPropertyDecode = null` here on purpose!
}
else if (codec instanceof ArrayCodec) {
if (c0 != '[')
return abort(Error.EXPECTED_TOKEN(codec.name, codec.elementName(), new String(buf, off, len), reader), reader, index);

final ArrayCodec arrayCodec = (ArrayCodec)codec;
final IdToElement idToElement = arrayCodec.idToElement;
value = ArrayCodec.decodeObject(arrayCodec.annotations, idToElement.getMinIterate(), idToElement.getMaxIterate(), idToElement, reader, validate, onPropertyDecode);
}
else {
c0 = reader.bufToChar(off);
if (codec instanceof ObjectCodec) {
if (c0 != '{')
return abort(Error.EXPECTED_TOKEN(codec.name, codec.elementName(), new String(buf, off, len), reader), reader, index);

final ObjectCodec objectCodec = (ObjectCodec)codec;
value = decodeObject(objectCodec.type, reader, validate, null); // NOTE: Setting `onPropertyDecode = null` here on purpose!
}
else if (codec instanceof ArrayCodec) {
if (c0 != '[')
return abort(Error.EXPECTED_TOKEN(codec.name, codec.elementName(), new String(buf, off, len), reader), reader, index);

final ArrayCodec arrayCodec = (ArrayCodec)codec;
final IdToElement idToElement = arrayCodec.idToElement;
value = ArrayCodec.decodeObject(arrayCodec.annotations, idToElement.getMinIterate(), idToElement.getMaxIterate(), idToElement, reader, validate, onPropertyDecode);
}
else {
throw new UnsupportedOperationException("Unsupported " + Codec.class.getSimpleName() + " type: " + codec.getClass().getName());
}
throw new UnsupportedOperationException("Unsupported " + Codec.class.getSimpleName() + " type: " + codec.getClass().getName());
}
}

Expand Down
3 changes: 3 additions & 0 deletions binding/src/main/java/org/jsonx/Range.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ private Range(final String string, final Class<? extends Number> type) throws Pa
final StringBuilder b = new StringBuilder();
this.min = parseNumber(b, string, 1, true, type);
this.minStr = toString(min);
if ("1.0E100".equals(minStr))
toString(min);

final int length = b.length() + 1;
if (string.charAt(length) != ',')
throw new ParseException("Missing ',' in string: \"" + string + "\"", length + 1);
Expand Down
4 changes: 2 additions & 2 deletions binding/src/test/java/org/jsonx/LibraryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public void testAddress() throws DecodeException, IOException {

@Test
public void testStaff() throws DecodeException, IOException {
final List<Employee> staff = new ArrayList<>();
final ArrayList<Employee> staff = new ArrayList<>();
for (int i = 0; i < 12; ++i) // [N]
staff.add(createEmployee());

Expand Down Expand Up @@ -167,7 +167,7 @@ public void testLibrary() throws DecodeException, IOException {
final Library library = new Library();
library.setAddress(Optional.of(createAddress()));
library.setHandicap(true);
final List<List<String>> schedule = new ArrayList<>();
final ArrayList<List<String>> schedule = new ArrayList<>();
for (final String[] slot : new String[][] {{"07:00", "17:00"}, {"08:00", "18:00"}, {"09:00", "19:00"},
{"10:00", "20:00"}, {"11:00", "21:00"}, {"12:00", "22:00"}, {"13:00", "23:00"}})
schedule.add(Arrays.asList(slot));
Expand Down
19 changes: 9 additions & 10 deletions generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ The <ins>JSONx Binding Generator</ins> provides convenience utilities for genera

### <b>4.1</b> `Generator`

The following example generates binding classes (`.java` files) in `target/generated-sources/jsonx` for the <ins>schema document</ins> at `src/main/resources/example.jsd`, with prefix `org.example$`.
The following example generates binding classes (`.java` files) in `target/generated-sources/jsonx` for the <ins>schema document</ins> at `src/main/resources/example.jsd`, with package prefix `org.example$`.

```bash
java -cp ... org.jsonx.Generator --prefix org.example$ -d target/generated-sources/jsonx src/main/resources/example.jsd
java -cp ... org.jsonx.Generator -p org.example$ -d target/generated-sources/jsonx src/main/resources/example.jsd
```

### <b>4.2</b> `Converter`
Expand All @@ -85,27 +85,26 @@ A distinction has to be made between "normative scope" and "non-normative scope"
The `Generator` is a utility class that can be used on the CLI to generate Java binding classes from a JSD schema. The `Generator` class has the following usage specification:

```
Usage: Generator [OPTIONS] <-d DEST_DIR> <SCHEMA_FILE>
Usage: Generator <-p [NAMESPACE] PREFIX>... <-d DEST_DIR> <SCHEMA.jsd|SCHEMA.jsdx|BINDING.jsb|BINDING.jsbx>...
Mandatory arguments:
-d <destDir> Specify the destination directory.
Optional arguments:
--prefix <PREFIX> Package prefix for generated classes.
-p [NAMESPACE] <PREFIX> Package prefix of generated classes for provided namespace, recurrable.
-d <DEST_DIR> The destination directory.
Supported SCHEMA_FILE formats:
<JSD|JSDx>
<JSD|JSDx|JSB|JSBx>
```

### <b>5.2</b> `Converter`

The `Converter` is a utility class that can be used on the CLI to convert JSD files to JSDx, and vice versa. The `Converter` class has the following usage specification:

```
Usage: Converter <SCHEMA_IN> [SCHEMA_OUT]
Usage: Converter <SCHEMA_IN.jsd|SCHEMA_IN.jsdx> [SCHEMA_OUT.jsd|SCHEMA_OUT.jsdx]
(or) <BINDING_IN.jsb|BINDING_IN.jsbx> [BINDING_OUT.jsb|BINDING_OUT.jsbx]
Supported SCHEMA_IN|OUT formats:
<JSD|JSDx>
<JSD|JSDx|JSB|JSBx>
```

If a `SCHEMA_OUT` argument is not provided, the `Converter` will output the converted content to stdout.
Expand Down
2 changes: 1 addition & 1 deletion generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<configuration>
<destDir>${project.build.directory}/generated-sources/jaxsb</destDir>
<schemas>
<schema>http://www.jsonx.org/schema.xsd</schema>
<schema>http://www.jsonx.org/binding.xsd</schema>
</schemas>
</configuration>
</execution>
Expand Down
Loading

0 comments on commit c8c9800

Please sign in to comment.