Conversation
23a8bd4 to
0d14509
Compare
|
3614876 to
c202b21
Compare
|
There was a problem hiding this comment.
Pull Request Overview
Generifies the OGNL core API to parameterize most classes and interfaces with a context type C extends OgnlContext, adds a builder pattern for OgnlContext creation, and updates tests and runtime utilities to the new generic signatures.
- Introduces generic type parameter C across context, nodes, accessors, and runtime utilities.
- Refactors OgnlContext construction and addDefaultContext helper methods (including new builder support) but introduces several argument-type mismatches in deprecated overloads.
- Updates supporting classes (property/method accessors, AST nodes) replacing length()/trim().length() patterns with isEmpty() and adding @serial annotations.
Reviewed Changes
Copilot reviewed 90 out of 90 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| BeanProviderAccessor.java | Adds generic context parameter to accessor methods. |
| ShortCircuitingExpressionTest.java | Adapts tests to generic SimpleNode/OgnlContext usage. |
| PropertyAccessorTest.java | Test refactor to generic PropertyAccessor and context member access. |
| OgnlContextCreateTest.java | Updates context creation to generic factory methods. |
| Java8Test.java | Uses generic createDefaultContext. |
| OgnlContextTest.java | Adjusts constructor argument order to new signature. |
| DefaultMemberAccess.java | Introduces generic context type on MemberAccess implementation. |
| OgnlExpressionCompiler.java | Generifies compiler interface methods to use Node. |
| ExpressionCompiler.java | Generic implementation; minor string utility updates. |
| ExpressionAccessor.java | Adds generic context parameter to accessor interface. |
| ContextClassLoader.java | Generifies class loader wrapper around OgnlContext. |
| TypeConverter.java | Adds generic context parameter to converter interface. |
| SimpleNode.java | Heavy refactor to generic Node, updating evaluation and child management. |
| SetPropertyAccessor.java | Generic property accessor for Set. |
| PropertyAccessor.java | Interface now generic on context. |
| OgnlRuntime.java | Broad generic refactor of static utility methods; alters classForName signature. |
| OgnlContext.java | Major redesign: generic class, new constructors, builder, deprecated old constructors. |
| OgnlCache.java | Returns generic accessors (MethodAccessor, PropertyAccessor, NullHandler). |
| Ognl.java | Refactors factory & utility methods to generics; introduces deprecated overloads with argument issues. |
| ObjectPropertyAccessor.java | Generic property accessor methods. |
| ObjectNullHandler.java | Generic null handler. |
| ObjectMethodAccessor.java | Generic method accessor with isEmpty() usage. |
| ObjectElementsAccessor.java | Uses diamond operator & enumeration generics. |
| NumericExpression.java | Generic numeric expression base. |
| NumberElementsAccessor.java | Diamond operator in enumeration creation. |
| NullHandler.java | Generic interface. |
| Node.java | Generic node interface with updated accessor types. |
| MethodAccessor.java | Generic method accessor interface. |
| MemberAccess.java | Generic member access interface. |
| MapPropertyAccessor.java | Generic map accessor methods. |
| ListPropertyAccessor.java | Generic list accessor; updated index handling. |
| JavaSource.java | Generic source generation interface. |
| IteratorPropertyAccessor.java | Generic iterator accessor. |
| ExpressionNode.java | Generic expression node with updated constant checks. |
| EvaluationPool.java | Generic evaluation factory. |
| Evaluation.java | Generic evaluation tree structure. |
| EnumerationPropertyAccessor.java | Generic enumeration accessor. |
| DefaultTypeConverter.java | Generic converter implementation. |
| DefaultClassResolver.java | Generic class resolver. |
| ComparisonExpression.java | Generic comparison expression base. |
| ClassResolver.java | Generic class resolver interface. |
| BooleanExpression.java | Generic boolean expression base. |
| ArrayPropertyAccessor.java | Generic array accessor. |
| AbstractMemberAccess.java | Generic abstract member access base. |
| (Multiple AST* files) | All AST node implementations generified; minor serialization and source string changes. |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| public static <C extends OgnlContext<C>> C addDefaultContext(Object root, C context) { | ||
| MemberAccess<C> memberAccess = new AbstractMemberAccess<>() { | ||
| @Override | ||
| public boolean isAccessible(C context, Object target, Member member, String propertyName) { | ||
| int modifiers = member.getModifiers(); | ||
| return Modifier.isPublic(modifiers); | ||
| } | ||
| }; | ||
| return addDefaultContext(root, memberAccess, null, null, context); |
There was a problem hiding this comment.
The call addDefaultContext(root, memberAccess, null, null, context) passes the OgnlContext instance (context) to a parameter that expects Map<String, Object>. This will not compile; use context.getValues() (or null) instead.
| public static <C extends OgnlContext<C>> C addDefaultContext(Object root, ClassResolver<C> classResolver, C context) { | ||
| MemberAccess<C> memberAccess = new AbstractMemberAccess<>() { | ||
| @Override | ||
| public boolean isAccessible(C context, Object target, Member member, String propertyName) { | ||
| int modifiers = member.getModifiers(); | ||
| return Modifier.isPublic(modifiers); | ||
| } | ||
| }; | ||
| return addDefaultContext(root, memberAccess, classResolver, null, context); |
There was a problem hiding this comment.
Again passing context (OgnlContext) where a Map<String, Object> is expected in addDefaultContext(..., context). Replace with context.getValues() or null.
| return Modifier.isPublic(modifiers); | ||
| } | ||
| }; | ||
| return addDefaultContext(root, memberAccess, classResolver, converter, context); |
There was a problem hiding this comment.
Incorrect argument: passing context (OgnlContext) to a parameter declared as Map<String, Object>. Use context.getValues() (or null) for the initialContext argument.
| return addDefaultContext(root, memberAccess, classResolver, converter, context); | |
| return addDefaultContext(root, memberAccess, classResolver, converter, context != null ? context.getValues() : null); |
| * @param context the context to which OGNL context will be added. | ||
| * @return {@link OgnlContext} with the keys <CODE>root</CODE> and <CODE>context</CODE> set | ||
| * appropriately | ||
| * @deprecated use ono of {{addDefaultContext()}} which accepts {@link MemberAccess} |
There was a problem hiding this comment.
Corrected spelling of 'ono' to 'one'.
| * @param context The context to which OGNL context will be added. | ||
| * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE> set | ||
| * appropriately | ||
| * @deprecated use ono of {{addDefaultContext()}} which accepts {@link MemberAccess} |
There was a problem hiding this comment.
Corrected spelling of 'ono' to 'one'.
| * @param context The context to which OGNL context will be added. | ||
| * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE> set | ||
| * appropriately | ||
| * @deprecated use ono of {{addDefaultContext()}} which accepts {@link MemberAccess} |
There was a problem hiding this comment.
Corrected spelling of 'ono' to 'one'.
| } | ||
|
|
||
| public static <T> Class<T> classForName(OgnlContext context, String className) throws ClassNotFoundException { | ||
| public static <C extends OgnlContext<C>> Class classForName(C context, String className) throws ClassNotFoundException { |
There was a problem hiding this comment.
Returning raw Class loses type safety. Change signature to 'public static <C extends OgnlContext> Class<?> classForName(...)' (or restore a generic parameter) to avoid raw types and unchecked usage.
| public static <C extends OgnlContext<C>> Class classForName(C context, String className) throws ClassNotFoundException { | |
| public static <C extends OgnlContext<C>> Class<?> classForName(C context, String className) throws ClassNotFoundException { |
| throw new ClassNotFoundException("Unable to resolve class: " + className); | ||
|
|
||
| return (Class<T>) result; | ||
| return result; |
There was a problem hiding this comment.
Returning raw Class loses type safety. Change signature to 'public static <C extends OgnlContext> Class<?> classForName(...)' (or restore a generic parameter) to avoid raw types and unchecked usage.
bf83d31 to
84cffa7
Compare
Pull Request Review: Generic Context (PR #376)OverviewThis PR introduces a significant architectural enhancement by making Changes: 90 files modified (+999/-754 lines) Positive Aspects ✅1. Well-Designed Generic PatternThe recursive generic bound
public class OgnlContext<C extends OgnlContext<C>> implements Map<String, Object>2. Comprehensive Refactoring
3. Backward Compatibility PreservedThe PR maintains the existing API surface:
4. Context Root Preservation LogicLines 361-381 in if (initialContext instanceof OgnlContext) {
@SuppressWarnings("unchecked")
OgnlContext<C> ognlInitialContext = (OgnlContext<C>) initialContext;
if (ognlInitialContext.getRoot() != null &&
ognlInitialContext.size() > 0 && newRoot != ognlInitialContext.getRoot()) {
return context.withRoot(ognlInitialContext.getRoot());
}
}This addresses a critical bug where context roots were being overwritten during list processing operations. Concerns and Recommendations
|
Pull Request Review: Generic Context (#376)SummaryThis PR introduces generic type parameters to OgnlContext to allow users to provide their own custom context implementations. This is a significant architectural enhancement that modernizes the OGNL API while maintaining backward compatibility. Strengths1. Architecture and Design
2. Critical Bug Fix IntegrationThe PR successfully integrates the root preservation logic from PR #449 into the generic context builder (Ognl.java:366-381). This prevents context root overwriting during nested evaluations and addresses the issue described in CLAUDE.md Feature Development Rules #1. All 8 context root preservation tests pass. 3. Test Coverage
4. Code Quality
Observations and Minor Concerns1. Breaking Change Potential (Medium Risk)While technically backward compatible, the extensive use of generics may cause issues for users with custom AST node implementations, reflection-heavy code that inspects OGNL types, and frameworks using raw types without generics. Recommendation: Ensure release notes clearly document this as a major version bump requiring recompilation. 2. SerialVersionUID ChangesAll serialVersionUIDs were regenerated. This breaks serialization compatibility with previous versions - any serialized OGNL AST objects from previous versions cannot be deserialized in this version. Recommendation: Document this breaking change prominently in release notes. 3. Performance ConsiderationsThe builder pattern adds a layer of indirection via Function<Builder, C> provider. Impact is minimal - only affects context creation, not expression evaluation. The AtomicReference for thread-safe builder caching is appropriate. Security ReviewPositive aspects:
RecommendationsMust Address:
Should Consider:
Final VerdictAPPROVE with minor recommendations This is a well-executed architectural improvement that:
The code quality is high, the design is sound, and the test coverage is excellent. The integration of the root preservation fix is implemented correctly and all edge cases are covered. Recommended Actions Before Merge:
Great work integrating two complex features (generic contexts + root preservation) into a cohesive implementation! Review performed using CLAUDE.md guidelines and all 607 tests verified passing. |
…uilder This commit resolves the conflict between the generic context feature and PR #449 (fix/context-root-preservation-issue-390) by integrating the root preservation logic into the OgnlContext.Builder provider. The root preservation logic from PR #449 prevented context root overwriting during nested evaluations (like list processing). When the generic context branch replaced addDefaultContext() with a builder pattern, this logic was lost during the rebase. This fix adds the same conditional logic to the builder's default provider: - Checks if initialContext is an OgnlContext instance - Preserves original root when context has user variables (size() > 0) - Preserves original root when new root differs from existing root - Otherwise uses the new root (normal behavior) All 607 tests pass, including the 8 context root preservation tests from PR #449. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
84cffa7 to
da02fd0
Compare
|
Pull Request Review: Generic Context (#376)SummaryThis PR introduces generic type parameters to Positive Aspects ✅1. Excellent Type Safety
2. Backward Compatibility Maintained
3. Builder Pattern Integration
4. Root Preservation Logic Integrated
5. Code Quality
Areas of Concern
|
Added detailed documentation to the Developer Guide covering: - Overview of the generic context feature (C extends OgnlContext<C>) - Basic usage examples for common scenarios - Creating custom context implementations - Custom ClassResolver and TypeConverter implementations - Builder pattern usage for context creation - Type safety benefits and compile-time checking - Backward compatibility guarantees - Complete example with SecurityContext This addresses the documentation gap from PR #376 where the generic context feature was introduced. Fixes #454 Co-authored-by: Lukasz Lenart <[email protected]>
Added detailed documentation to the Developer Guide covering: - Overview of the generic context feature (C extends OgnlContext<C>) - Basic usage examples for common scenarios - Creating custom context implementations - Custom ClassResolver and TypeConverter implementations - Builder pattern usage for context creation - Type safety benefits and compile-time checking - Backward compatibility guarantees - Complete example with SecurityContext This addresses the documentation gap from PR #376 where the generic context feature was introduced. Fixes #454 Co-authored-by: Lukasz Lenart <[email protected]>




No description provided.