Skip to content

Commit

Permalink
Merge pull request #308 from kbss-cvut/development
Browse files Browse the repository at this point in the history
[2.2.2] Release
  • Loading branch information
ledsoft authored Jan 18, 2025
2 parents ba97d62 + 4ea77c4 commit ee07598
Show file tree
Hide file tree
Showing 51 changed files with 1,529 additions and 1,679 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# JOPA - Change Log

## 2.2.2 - 2025-01-18
- Fix an issue with parsing SPARQL query parameters (Enhancement #294).
- Fix an issue with passing a lazy loading proxy to `EntityManager.remove` (Bug #306).
- Refactor test metamodel setup (GH #301).
- Allow using primitive types as mapped attribute types.
- Dependency updates: RDF4J 5.1.0.

## 2.2.1 - 2024-12-12
- Rename `MultilingualString` in OntoDriver to `Translations` to prevent confusion with `MultilingualString` from JOPA (GH #288).
- Fix a SPARQL query parsing issue (Bug #294).
Expand Down
2 changes: 1 addition & 1 deletion datatype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>jopa-all</artifactId>
<groupId>cz.cvut.kbss.jopa</groupId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public class DatatypeTransformer {

private static final Map<Pair, Function<Object, ?>> TRANSFORMERS = initTransformers();

private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVES = Map.of(
Integer.class, int.class,
Boolean.class, boolean.class,
Byte.class, byte.class,
Short.class, short.class,
Long.class, long.class,
Float.class, float.class,
Double.class, double.class
);

private DatatypeTransformer() {
throw new AssertionError();
}
Expand Down Expand Up @@ -79,14 +89,31 @@ private DatatypeTransformer() {
return map;
}

/**
* Converts the specified wrapper class to its corresponding primitive class.
* <p>
* If the class parameter is a wrapper type, the equivalent primitive type will be returned (e.g. int.class for
* Integer.class) In all other cases, the return value is null.
*
* @param cls - the class to convert
* @return Optional containing the primitive type, or empty if the specified class is not a wrapper type
*/
public static Optional<Class<?>> wrapperTypeToPrimitiveType(Class<?> cls) {
if (cls != null && WRAPPER_TO_PRIMITIVES.containsKey(cls)) {
return Optional.of(WRAPPER_TO_PRIMITIVES.get(cls));
}
return Optional.empty();
}

/**
* Maps the specified value to the target type (if possible).
*
* @param value The value to convert
* @param targetType The type to which the specified value should be converted
* @param <T> Target type
* @return Value as the target type
* @throws UnsupportedTypeTransformationException If the specified value cannot be transformed to the specified target type
* @throws UnsupportedTypeTransformationException If the specified value cannot be transformed to the specified
* target type
*/
public static <T> T transform(Object value, Class<T> targetType) {
Objects.requireNonNull(targetType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,36 @@

import java.net.InetAddress;
import java.net.URL;
import java.util.Optional;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

class DatatypeTransformerTest {

@Test
void wrapperTypeToPrimitiveTypeReturnsNullForNullInput() {
assertEquals(Optional.empty(), DatatypeTransformer.wrapperTypeToPrimitiveType(null));
}

@ParameterizedTest
@MethodSource("wrapperTypeToPrimitiveTypeTestValues")
void wrapperTypeToPrimitiveType(Class<?> wrapper, Class<?> primitive) {
assertEquals(Optional.of(primitive), DatatypeTransformer.wrapperTypeToPrimitiveType(wrapper));
}

private static Stream<Arguments> wrapperTypeToPrimitiveTypeTestValues() {
return Stream.of(
Arguments.arguments(Integer.class, int.class),
Arguments.arguments(Boolean.class, boolean.class),
Arguments.arguments(Byte.class, byte.class),
Arguments.arguments(Short.class, short.class),
Arguments.arguments(Long.class, long.class),
Arguments.arguments(Float.class, float.class),
Arguments.arguments(Double.class, double.class)
);
}

@Test
void transformReturnsNullForNullInput() {
assertNull(DatatypeTransformer.transform(null, String.class));
Expand Down
2 changes: 1 addition & 1 deletion jopa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
131 changes: 66 additions & 65 deletions jopa-impl/src/main/antlr4/cz/cvut/kbss/jopa/query/soql/Soql.g4
Original file line number Diff line number Diff line change
@@ -1,48 +1,30 @@
grammar Soql;

start: querySentence EOF ;

querySentence : selectStatement whereClauseWrapper? groupByClause? orderByClause? ;
querySentence: selectStatement ;

selectStatement: typeDef params FROM tables ;
selectStatement: selectClause fromClause whereClause? groupByClause? orderByClause? ;

typeDef: SELECT ;
singleValuedObjectPathExpression: simpleSubpath DOT singleValuedObjectField ;

params: paramComma* distinctParam ;
simpleSubpath: singleValuedObjectField (DOT simpleSubpath)* ;

paramComma: distinctParam ',' ;
singleValuedObjectField: IDENTIFICATION_VARIABLE ;

distinctParam: distinct? selectedParam ;
selectClause: SELECT (DISTINCT)? selectItem (',' selectItem)* ;

selectedParam: param | count;
selectItem: selectExpression;

count: COUNT '(' param ')' ;
selectExpression: simpleSubpath | aggregateExpression ;

param: objWithAttr | objWithOutAttr ;
aggregateExpression: COUNT '(' (DISTINCT)? simpleSubpath ')';

objWithAttr: object DOT attribute;
fromClause: FROM entityName IDENTIFICATION_VARIABLE;

objWithOutAttr: object ;
entityName: IDENTIFICATION_VARIABLE ;

distinct: DISTINCT ;

object: IDENTIFICATION_VARIABLE ;

attribute: IDENTIFICATION_VARIABLE ;

joinedParams: object DOT attribute (DOT attribute)+ ;



tables: tableWithName ;

table: IDENTIFICATION_VARIABLE ;

tableName: IDENTIFICATION_VARIABLE ;

tableWithName: table tableName ;


whereClauseWrapper
whereClause
: WHERE conditionalExpression
;

Expand All @@ -66,38 +48,44 @@ simpleConditionalExpression
;

inExpression
: whereClauseParam (NOT)? IN '('? (inItem (',' inItem)*) ')'?
: simpleSubpath (NOT)? IN '('? (inItem (',' inItem)*) ')'?
;

inItem
: literal
| whereClauseValue
| inputParameter
;

literal
:
: STRING_LITERAL
| INT_LITERAL
| FLOAT_LITERAL
| BOOLEAN_LITERAL
| IDENTIFICATION_VARIABLE
;

likeExpression
: stringExpression (NOT)? LIKE whereClauseValue
: stringExpression (NOT)? LIKE stringExpression
;

memberOfExpression
: inItem (NOT)? MEMBEROF whereClauseParam
: inItem (NOT)? MEMBER OF simpleSubpath
;

entityExpression
: IDENTIFICATION_VARIABLE
| inputParameter
;

comparisonExpression
: stringExpression COMPARISON_OPERATOR stringExpression
| simpleArithmeticExpression COMPARISON_OPERATOR simpleArithmeticExpression
| whereClauseParam COMPARISON_OPERATOR ( whereClauseParam | whereClauseValue )
: stringExpression comparisonOperator stringExpression
| simpleArithmeticExpression comparisonOperator simpleArithmeticExpression
| entityExpression op=(EQUAL | NOT_EQUAL) ( entityExpression )
;

whereClauseValue: (QMARK TEXT QMARK) | inputParameter ;

whereClauseParam: param | joinedParams ;

stringExpression
: whereClauseParam
: simpleSubpath
| STRING_LITERAL
| inputParameter
| functionsReturningStrings
;
Expand All @@ -107,7 +95,7 @@ functionsReturningStrings
| 'SUBSTRING' '(' stringExpression ',' simpleArithmeticExpression ',' simpleArithmeticExpression ')'
| 'LOWER' '(' stringExpression ')'
| 'UPPER' '(' stringExpression ')'
| 'LANG' '(' whereClauseParam ')'
| 'LANG' '(' simpleSubpath ')'
;

simpleArithmeticExpression
Expand All @@ -123,7 +111,7 @@ arithmeticFactor
;

arithmeticPrimary
: param
: simpleSubpath
| literal
| '(' simpleArithmeticExpression ')'
| inputParameter
Expand All @@ -138,22 +126,24 @@ functionsReturningNumerics
| 'FLOOR' '(' simpleArithmeticExpression ')'
;

orderByClause: ORDERBY orderByFullFormComma orderByFullFormComma* ;

orderByFullFormComma: orderByFullForm ','? ;

orderByFullForm: orderByParam ORDERING? ;

orderByParam: object DOT attribute (DOT attribute)* ;
orderByClause: ORDER BY orderByItem (',' orderByItem)* ;

groupByClause: GROUPBY groupByParamComma groupByParamComma* ;
orderByItem: singleValuedObjectPathExpression (ASC | DESC) ;

groupByParamComma: groupByParam ','? ;
groupByClause: GROUP BY groupByItem (',' groupByItem)* ;

groupByParam: object DOT attribute (DOT attribute)* ;
groupByItem: singleValuedObjectPathExpression ;

inputParameter: COLON IDENTIFICATION_VARIABLE ;

comparisonOperator
: op=EQUAL
| op='>'
| op='>='
| op='<'
| op='<='
| op=NOT_EQUAL
;

SELECT: 'SELECT' ;

Expand All @@ -169,11 +159,13 @@ AND: 'AND' ;

OR: 'OR' ;

ORDERBY: 'ORDER BY' ;
BY: 'BY' ;

OF: 'OF' ;

ORDERING: ASC | DESC ;
ORDER: 'ORDER' ;

GROUPBY: 'GROUP BY' ;
GROUP: 'GROUP' ;

ASC: 'ASC' ;

Expand All @@ -187,18 +179,31 @@ LIKE: 'LIKE' ;

IN: 'IN' ;

MEMBEROF: 'MEMBER OF' ;
MEMBER: 'MEMBER' ;

COMPARISON_OPERATOR: '>' | '<' | '>=' | '<=' | '=' | '<>' | '!=' ;
EQUAL: '=' ;
NOT_EQUAL: '<>' | '!=' ;

DOT: '.' ;

QMARK: '"' ;

COLON: ':' ;

TRUE: 'TRUE';

FALSE: 'FALSE';

IDENTIFICATION_VARIABLE: (LOWERCASE | UPPERCASE | '_') (LOWERCASE | UPPERCASE | DIGIT | '_')* ;

STRING_LITERAL: QMARK TEXT QMARK ;

INT_LITERAL: DIGIT+;

FLOAT_LITERAL: DIGIT* '.' DIGIT;

BOOLEAN_LITERAL: TRUE | FALSE;

TEXT: (LOWERCASE | UPPERCASE | DIGIT)+ ;

UPPERCASE: ('A'..'Z');
Expand All @@ -207,8 +212,4 @@ LOWERCASE: ('a'..'z');

DIGIT: ('0'..'9');

NUMBER: DIGIT+ ;

VALUE: NUMBER ;

WHITESPACE: (' ')+ -> skip;
Loading

0 comments on commit ee07598

Please sign in to comment.