Skip to content

Commit

Permalink
Merge branch 'main-javax' of
Browse files Browse the repository at this point in the history
https://[email protected]/exxcellent/olingo-jpa-processor-v4.git into
main-javax
  • Loading branch information
Ralf Zozmann committed Feb 3, 2025
2 parents 0c10d5b + e612ac8 commit 884c67c
Show file tree
Hide file tree
Showing 86 changed files with 1,073 additions and 680 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/produce-coveragereport-javax.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ jobs:
- name: Create code coverage report
run: mvn clean verify -Duse-eclipselink -Ddisable.jetty=false -Dmaven.source.skip -Dmaven.javadoc.skip
- name: Archive code coverage results for download
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
path: code-coverage-report/target/jacoco-aggregate-ut/jacoco.xml
overwrite: true
- name: Upload code coverage report
uses: codecov/codecov-action@v5
with:
Expand Down
5 changes: 3 additions & 2 deletions doc/integrators/MoreHints.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,6 @@ With Hibernate byte code enhancement produce problems with every configuration (
Calling bound action means that the entity will be loaded from database. JPA provider like Hibernate cannot (EclipseLink will do) instance/load data for abstract entity classes.
* The OData-JPA-Adapter will create a entity proxy for abstract classes to work on it while converting from OData to JPA.

# Customizing of SQL queries
Reading data from the database based on a OData request is normally completely managed by the library. But sometimes it is necessary to modify the query for any reason. So the builtin processor used to read data from the database provides a mechanism to customize any read query. You have to implement the `org.apache.olingo.jpa.processor.core.api.QueryCustomizer` interface and to inject the customizer on a per request base into the `JPAODataServletHandler`. See into the [example servlet](https://github.com/exxcellent/olingo-jpa-processor-v4/blob/main-javax/jpa-examples/tutorial-servlet-example/src/main/java/org/apache/olingo/jpa/servlet/example/ODataServlet.java#L114) for more details.
# Customizing of SQL queries and their results
Reading data from the database based on a OData request is normally completely managed by the library. But sometimes it is necessary to modify the query for any reason. So the builtin processor used to read data from the database provides a mechanism to customize any read query. You have to implement the `org.apache.olingo.jpa.processor.core.api.QueryCustomizer` interface and to inject the customizer on a per request base into the `JPAODataServletHandler`. It is also possible to modify the result of such queries. This can be done by implementing the `org.apache.olingo.jpa.processor.core.api.QueryResponseCustomizer` interface and to inject the customizer on a per request base into the `JPAODataServletHandler`.
See into the [example servlet](https://github.com/exxcellent/olingo-jpa-processor-v4/blob/main-javax/jpa-examples/tutorial-servlet-example/src/main/java/org/apache/olingo/jpa/servlet/example/ODataServlet.java#L114) for more details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.apache.olingo.jpa.servlet.example;

import java.util.Arrays;
import java.util.UUID;

import org.apache.olingo.commons.api.data.ComplexValue;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.jpa.processor.core.api.QueryResponseCustomizer;
import org.apache.olingo.jpa.processor.core.testmodel.Person;

public class ExampleQueryResponseCustomizer implements QueryResponseCustomizer {

@Override
public EntityCollection customizeResult(Edm edm, Class<?> entityType, EntityCollection result) {
if(entityType == Person.class && !result.getEntities().isEmpty()) {
result.getEntities().forEach(p -> {
Property pNewComplex = new Property();
pNewComplex.setName("personExtendByAdditionalAttribute");
pNewComplex.setType("org.apache.olingo.jpa.ChangeInformation");
ComplexValue cNew = new ComplexValue();
Property pComplexNested = new Property();
pComplexNested.setName("By"); //the property is not dynamic -> use existing property name, but type is already known
pComplexNested.setValue(ValueType.PRIMITIVE, UUID.randomUUID().toString());
cNew.getValue().add(pComplexNested);
pNewComplex.setValue(ValueType.COMPLEX, Arrays.asList(cNew));
p.addProperty(pNewComplex);
});
}
//as default: to not touch the result
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.olingo.jpa.processor.ModifiableJPAODataRequestContext;
import org.apache.olingo.jpa.processor.core.api.JPAODataServletHandler;
import org.apache.olingo.jpa.processor.core.api.QueryRequestCustomizer;
import org.apache.olingo.jpa.processor.core.api.QueryResponseCustomizer;
import org.apache.olingo.jpa.processor.core.database.JPA_DERBYDatabaseProcessor;
import org.apache.olingo.jpa.processor.core.mapping.AbstractJPAAdapter;
import org.apache.olingo.jpa.processor.core.mapping.ResourceLocalPersistenceAdapter;
Expand Down Expand Up @@ -115,6 +116,8 @@ protected void prepareRequestContext(final ModifiableJPAODataRequestContext requ
requestContext.getDependencyInjector().registerDependencyMapping(String.class, getServletName());
requestContext.getDependencyInjector().registerDependencyMapping(QueryRequestCustomizer.class,
new ExampleQueryCustomizer());
requestContext.getDependencyInjector().registerDependencyMapping(QueryResponseCustomizer.class,
new ExampleQueryResponseCustomizer());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class TypeConverterAPIWriter extends AbstractWriter {

@SuppressWarnings("unused")
private final AbstractJPASchema schema;
private final JPAStructuredType type;
private final JPAStructuredType<?> type;

public TypeConverterAPIWriter(final File generationBaseDirectory, final AbstractJPASchema schema,
final JPAStructuredType et) {
final JPAStructuredType<?> et) {
super(generationBaseDirectory, et.getTypeClass().getPackage().getName(), determineConverterName(et));
this.schema = schema;
this.type = et;
Expand All @@ -70,7 +70,7 @@ public void writeProtocolCodeStart() throws IOException {
write(NEWLINE + "\t" + "}");
}

static String determineConverterName(final JPAStructuredType type) {
static String determineConverterName(final JPAStructuredType<?> type) {
return TypeDtoAPIWriter.determineTypeName(type.getTypeClass().getSimpleName()) + "Converter";
}

Expand Down Expand Up @@ -110,7 +110,7 @@ private void generateConvertDto2Entity() throws IOException, ODataJPAModelExcept
write(NEWLINE + "\t" + "}");
}

private void generateConvertMethods4Attribute2PropertyValue(final JPAStructuredType ownerType,
private void generateConvertMethods4Attribute2PropertyValue(final JPAStructuredType<?> ownerType,
final Set<String> mapAlreadeGeneratedMethods)
throws ODataJPAModelException, IOException {
for (final JPAMemberAttribute attribute : ownerType.getAttributes(false)) {
Expand Down Expand Up @@ -250,7 +250,7 @@ private String generateConvertMethodAttribute2PrimitiveValue(final JPAMemberAttr
return methodName;
}

private void generateAllAttribute2PropertyConversion(final JPAStructuredType sType, final boolean ownerISRootEntity,
private void generateAllAttribute2PropertyConversion(final JPAStructuredType<?> sType, final boolean ownerISRootEntity,
final Set<String> mapAlreadeGeneratedMethods) throws ODataJPAModelException,
IOException {
for (final JPAAssociationAttribute asso : sType.getAssociations()) {
Expand Down Expand Up @@ -301,7 +301,7 @@ private void generateConvertEntity2Dto() throws IOException, ODataJPAModelExcept
write(NEWLINE + "\t" + "}");
}

private void generateConvertMethods4Property2Attribute(final JPAStructuredType ownerType,
private void generateConvertMethods4Property2Attribute(final JPAStructuredType<?> ownerType,
final Set<String> mapAlreadeGeneratedMethods)
throws ODataJPAModelException, IOException {
for (final JPAMemberAttribute attribute : ownerType.getAttributes(false)) {
Expand Down Expand Up @@ -824,7 +824,7 @@ private String generateConvertMethod4Attribute2PropertyCollectionValue(final JPA
return methodCollectionName;
}

private void generateAllProperty2AttributeConversion(final JPAStructuredType sType, final boolean ownerISRootEntity,
private void generateAllProperty2AttributeConversion(final JPAStructuredType<?> sType, final boolean ownerISRootEntity,
final Set<String> mapAlreadeGeneratedMethods) throws ODataJPAModelException,
IOException {
for (final JPAAssociationAttribute asso : sType.getAssociations()) {
Expand Down Expand Up @@ -852,7 +852,7 @@ private void generateAllProperty2AttributeConversion(final JPAStructuredType sTy
}
}

private void generateProperty2AssociationConversion(final JPAStructuredType ownerType, final boolean ownerISRootEntity,
private void generateProperty2AssociationConversion(final JPAStructuredType<?> ownerType, final boolean ownerISRootEntity,
final JPAAssociationAttribute relationship) throws ODataJPAModelException, IOException {
final String memberName = qualifiedName2FirstCharacterUppercasedString(relationship.getInternalName());
final String propClientType = TypeDtoAPIWriter.determineClientSidePropertyJavaTypeName(relationship, false);
Expand Down Expand Up @@ -891,7 +891,7 @@ private void generateProperty2AssociationConversion(final JPAStructuredType owne
}
}

private void generateAssociation2PropertyConversion(final JPAStructuredType ownerType,
private void generateAssociation2PropertyConversion(final JPAStructuredType<?> ownerType,
final boolean ownerISRootEntity,
final JPAAssociationAttribute relationship) throws ODataJPAModelException, IOException {
final String memberName = qualifiedName2FirstCharacterUppercasedString(relationship.getInternalName());
Expand Down Expand Up @@ -932,7 +932,7 @@ private void generateAssociation2PropertyConversion(final JPAStructuredType owne
/**
* DTO Attribute -> Olingo Entity Property
*/
private void generateAttribute2PropertyConversion(final JPAStructuredType ownerType, final boolean ownerISRootEntity,
private void generateAttribute2PropertyConversion(final JPAStructuredType<?> ownerType, final boolean ownerISRootEntity,
final JPAMemberAttribute attribute)
throws ODataJPAModelException,
IOException {
Expand Down Expand Up @@ -998,7 +998,7 @@ private void generateAttribute2PropertyConversion(final JPAStructuredType ownerT
/**
* Olingo Entity Property -> DTO Attribute
*/
private void generateProperty2AttributeConversion(final JPAStructuredType ownerType, final boolean ownerISRootEntity,
private void generateProperty2AttributeConversion(final JPAStructuredType<?> ownerType, final boolean ownerISRootEntity,
final JPAMemberAttribute attribute)
throws ODataJPAModelException,
IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

class TypeMetaAPIWriter extends AbstractWriter {

private final JPAStructuredType type;
private final JPAStructuredType<?> type;

public TypeMetaAPIWriter(final File generationBaseDirectory, final JPAStructuredType st) {
public TypeMetaAPIWriter(final File generationBaseDirectory, final JPAStructuredType<?> st) {
super(generationBaseDirectory, st.getTypeClass().getPackage()
.getName(), determineTypeMetaName(st.getTypeClass().getSimpleName()));
this.type = st;
Expand All @@ -32,7 +32,7 @@ public void writeMetaStart() throws IOException, ODataJPAModelException {
final String typeMetaName = determineTypeMetaName(type.getTypeClass().getSimpleName());
String extendsBaseClass = "";
if (AbstractStructuredTypeJPA.class.isInstance(type)) {
final JPAStructuredType base = AbstractStructuredTypeJPA.class.cast(type).getBaseType();
final JPAStructuredType<?> base = AbstractStructuredTypeJPA.class.cast(type).getBaseType();
if (base != null) {
extendsBaseClass = " extends " + determineTypeMetaName(base.getTypeClass().getSimpleName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public final void assignSheetName(final String entityTypeName, final String shee
mapEntityType2SheetName.put(entityTypeName, sheetName);
}

String getSheetName(final JPAEntityType entity) {
String getSheetName(final JPAEntityType<?> entity) {
final String sheetName = mapEntityType2SheetName.get(determineSheetKeyName(entity));
if (sheetName != null) {
return sheetName;
Expand Down Expand Up @@ -164,7 +164,7 @@ public final void addSuppressedColumns(final String entityTypeName, final String
}
}

boolean isSuppressedColumn(final JPAEntityType entity, final String dbColumnName) {
boolean isSuppressedColumn(final JPAEntityType<?> entity, final String dbColumnName) {
return isSuppressedColumn(determineSheetKeyName(entity), dbColumnName);
}

Expand Down Expand Up @@ -248,7 +248,7 @@ public final void assignColumnIndex(final String entityTypeName, final String db
*
* @return The custom name or <code>null</code>
*/
String getCustomColumnName(final JPAEntityType entity, final String dbColumnName) {
String getCustomColumnName(final JPAEntityType<?> entity, final String dbColumnName) {
final ColumnConfiguration cc = findColumnConfiguration(determineSheetKeyName(entity), dbColumnName);
if (cc == null) {
return null;
Expand All @@ -263,7 +263,7 @@ String getCustomColumnName(final JPAEntityType entity, final String dbColumnName
* @return A map where the key is the DB column name and the value the assigned column index for final Excel sheet.
* Unassigned columns are not present in map. The map is created as return value and not used internally.
*/
Map<String, Integer> getCustomColumnIndexes(final JPAEntityType entity) {
Map<String, Integer> getCustomColumnIndexes(final JPAEntityType<?> entity) {
final Map<String, ColumnConfiguration> configs = mapEntityType2ColumnConfiguration.get(determineSheetKeyName(
entity));
if (configs == null) {
Expand All @@ -282,7 +282,7 @@ Map<String, Integer> getCustomColumnIndexes(final JPAEntityType entity) {
return result;
}

private static String determineSheetKeyName(final JPAEntityType entity) {
private static String determineSheetKeyName(final JPAEntityType<?> entity) {
return entity.getExternalName();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public Object getValue() {
*/
private static class WorkbookState {
private final Workbook workbook;
Map<JPAEntityType, SheetState> sheets = new HashMap<>();
Map<JPAEntityType<?>, SheetState> sheets = new HashMap<>();
short shortBestFontHeight = XSSFFont.DEFAULT_FONT_SIZE;
Map<EdmPrimitiveTypeKind, CellStyle> mapDatatypeCellStyle = new HashMap<>();
Map<Integer, Integer> mapColumn2RecommendedWidth = new HashMap<>();
Expand All @@ -90,13 +90,13 @@ public WorkbookState(final Workbook workbook) {

private static class SheetState {
private final WorkbookState workbookState;
private final JPAEntityType jpaType;
private final JPAEntityType<?> jpaType;
private final Sheet sheet;
@SuppressWarnings("unused")
boolean isNewCreated = false;
Map<String, Integer> mapAlias2ColumnIndex = null;

public SheetState(final WorkbookState ws, final JPAEntityType jpaType, final Sheet sheet) {
public SheetState(final WorkbookState ws, final JPAEntityType<?> jpaType, final Sheet sheet) {
this.workbookState = ws;
this.jpaType = jpaType;
this.sheet = sheet;
Expand All @@ -114,7 +114,7 @@ private WorkbookState createWorkbook() throws IOException {
return new WorkbookState(new SXSSFWorkbook());
}

private SheetState findOrCreateSheet(final WorkbookState workbookState, final JPAEntityType jpaType) {
private SheetState findOrCreateSheet(final WorkbookState workbookState, final JPAEntityType<?> jpaType) {
SheetState sheetState = workbookState.sheets.get(jpaType);
if (sheetState != null) {
return sheetState;
Expand Down Expand Up @@ -276,7 +276,7 @@ public final ODataResponseContent produceExcel(final QueryEntityResult input,
return new ODataResponseContent(contentState, isResult);
}

private Map<String, Integer> buildColumnOrder(final JPAEntityType jpaType,
private Map<String, Integer> buildColumnOrder(final JPAEntityType<?> jpaType,
final Collection<String> requestedResultAttributes, final List<TupleElement<?>> unsortedList) {
// use copy constructor to modify map
final Map<String, Integer> mapConfigured = new HashMap<>(configuration.getCustomColumnIndexes(jpaType));
Expand Down Expand Up @@ -312,7 +312,7 @@ private Map<String, Integer> buildColumnOrder(final JPAEntityType jpaType,
return mapResult;
}

private boolean isSuppressedColumn(final JPAEntityType jpaType, final Collection<String> requestedResultAttributes,
private boolean isSuppressedColumn(final JPAEntityType<?> jpaType, final Collection<String> requestedResultAttributes,
final String dbAlias) {
// static config exlusion?
if (configuration.isSuppressedColumn(jpaType, dbAlias)) {
Expand Down Expand Up @@ -423,7 +423,7 @@ private void processTimeRelatedCell(final WorkbookState state, final Cell cell,
*
* @return The combination of resulting value for Excel sheet (after any conversion) and data type assignment.
*/
protected ExcelCell determineCellContent(final JPAEntityType entityType, final String attributePath,
protected ExcelCell determineCellContent(final JPAEntityType<?> entityType, final String attributePath,
final JPAAttribute<?> targetAttribute, final Object value) {
final EdmPrimitiveTypeKind kindOfCell = determineCellRepresentation(entityType, attributePath, targetAttribute);
Object odataValue;
Expand All @@ -447,7 +447,7 @@ protected ExcelCell determineCellContent(final JPAEntityType entityType, final S
* @return The primitive data type of column to use for Excel cell formatting.
* @see #determineCellContent(JPAEntityType, String, JPAAttribute, Object)
*/
protected EdmPrimitiveTypeKind determineCellRepresentation(final JPAEntityType entityType, final String attributePath,
protected EdmPrimitiveTypeKind determineCellRepresentation(final JPAEntityType<?> entityType, final String attributePath,
final JPAAttribute<?> targetAttribute) {
if (JPADescribedElement.class.isInstance(targetAttribute)) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,6 @@ public Class<ODataResponseContent> getOutputType() {
return ODataResponseContent.class;
}

@SuppressWarnings("unchecked")
@Override
public <I> Transformation<I, ODataResponseContent> createSubTransformation(final Class<I> newStart)
throws SerializerException {
if (newStart.isAssignableFrom(getInputType())) {
return (Transformation<I, ODataResponseContent>) this;
}
throw new SerializerException("Sub transformation not supported",
SerializerException.MessageKeys.UNSUPPORTED_FORMAT);
}

@Override
public final ODataResponseContent transform(final QueryEntityResult input) throws SerializerException {
if (!input.getExpandChildren().isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void testColumnIndex() throws IOException, ODataException {
configuration.assignColumnIndex(DatatypeConversionEntity.class.getAnnotation(Entity.class).name(), "C1", 2);
configuration.assignColumnIndex(DatatypeConversionEntity.class.getAnnotation(Entity.class).name(), "C2", 3);

final JPAEntityType et = helper.getJPAEntityType("DatatypeConversionEntities");
final JPAEntityType<?> et = helper.getJPAEntityType("DatatypeConversionEntities");
final Map<String, Integer> map = configuration.getCustomColumnIndexes(et);
assertEquals(2, map.size());
}
Expand Down
Loading

0 comments on commit 884c67c

Please sign in to comment.