More than 1 #Projection in a #RepositoryRestResource - spring-data-rest

Consider that you have an Entity class that has 2 (or eventually more) #Projection's:
#Projection(name ="S", types = { Entity.class })
public interface EntitySmall {
Long getId();
String getName();
}
And:
#Projection(name ="L", types = { Entity.class })
public interface EntityLarge {
Long getId();
String getName();
Date getCreatedAt();
String getCreatedBy();
//...and more stuff
}
Question 1
Is it possible to use both #Projection's on a #RepositoryRestResource of the same Entity class?
What I managed to do so far, is to define one (and only one) #Projection, as an 'excerptProjection' in the #RepositoryRestResource, and if i don't define any, the Repo uses the default representation of the Entity
Question 2
Is the only solution as many #RepositoryRestResource's as the amount of #Projection's?

Related

Best Practice for OOP function with multiple possible control flows

In my project, I have this special function that does needs to evaluate the following:
State -- represented by an enum -- and there are about 6 different states
Left Argument
Right Argument
Left and Right arguments are represented by strings, but their values can be the following:
"_" (a wildcard)
"1" (an integer string)
"abc" (a normal string)
So as you can see, to cover all every single possibility, there's about 2 * 3 * 6 = 36 different logics to evaluate and of course, using if-else in one giant function will not be feasible at all. I have encapsulated the above 3 input into an object that I'll pass to my function.
How would one try to use OOP to solve this. Would it make sense to have 6 different subclasses of the main State class with an evaluate() method, and then in their respective methods, I have if else statements to check:
if left & right arg are wildcards, do something
if left is number, right is string, do something else
Repeat for all the valid combinations in each State subclass
This feels like the right direction, but it also feels like theres alot of duplicate logic (for example check if both args are wildcards, or both strings etc.) for all 6 subclasses. Then my thought is to abstract it abit more and make another subclass:
For each state subclass, I have stateWithTwoWildCards, statewithTwoString etc.
But I feel like this is going way overboard and over-engineering and being "too" specific (I get that this technically adheres tightly to SOLID, especially SRP and OCP concepts). Any thoughts on this?
Possibly something like template method pattern can be useful in this case. I.e. you will encapsulate all the checking logic in the base State.evaluate method and create several methods which subclasses will override. Something along this lines:
class StateBase
def evaluate():
if(bothWildcards)
evalBothWildcards()
else if(bothStrings)
evalBothStrings()
else if ...
def evalBothWildcards():
...
def evalBothStrings():
...
Where evalBothWildcards, evalBothStrings, etc. will be overloaded in inheritors.
there's about 2 * 3 * 6 = 36 different logics to evaluate
We can apply divide and conquer technique.
you have 6 states. It is possible to use Chain of Responibility pattern here to choose appropriate state handler
when desired state handler is found, then we can apply desired function. The appropriate function can be considered as strategy. So it is a place where Strategy pattern can be applied.
we can separate strategies by appropriate states and put them in simple factory to get desired strategy by key.
This is what we will do. So let's see it more thoroughly.
Chain of responsibility pattern
If you have a lot if else statements, it is possible to use Chain of Responsibility pattern. As wiki says about Chain of Responsibility:
The chain-of-responsibility pattern is a behavioral design pattern
consisting of a source of command objects and a series of processing
objects. Each processing object contains logic that defines the
types of command objects that it can handle; the rest are passed to
the next processing object in the chain. A mechanism also exists for
adding new processing objects to the end of this chain
So let's dive in code. Let me show an example via C#.
So this is our Argument class which has Left and Right operands:
public class Arguments
{
public string Left { get; private set; }
public string Right { get; private set; }
public MyState MyState { get; private set; }
public MyKey MyKey => new MyKey(MyState, Left);
public Arguments(string left, string right, MyState myState)
{
Left = left;
Right = right;
MyState = myState;
}
}
And this is your 6 states:
public enum MyState
{
One, Two, Three, Four, Five, Six
}
This is start of Decorator pattern. This is an abstraction of StateHandler which defines behaviour to to set next handler:
public abstract class StateHandler
{
public abstract MyState State { get; }
private StateHandler _nextStateHandler;
public void SetSuccessor(StateHandler nextStateHandler)
{
_nextStateHandler = nextStateHandler;
}
public virtual IDifferentLogicStrategy Execute(Arguments arguments)
{
if (_nextStateHandler != null)
return _nextStateHandler.Execute(arguments);
return null;
}
}
and its concrete implementations of StateHandler:
public class OneStateHandler : StateHandler
{
public override MyState State => MyState.One;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
public class TwoStateHandler : StateHandler
{
public override MyState State => MyState.Two;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
and the third state handler looks like this:
public class ThreeStateHandler : StateHandler
{
public override MyState State => MyState.Three;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
Strategy pattern
Let's pay attention to the following row of code:
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
The above code is an example of using Strategy pattern. We have different ways or strategies to handle
your cases. Let me show a code of strategies of evaluation of your expressions.
This is an abstraction of strategy:
public interface IDifferentLogicStrategy
{
string Evaluate(Arguments arguments);
}
And its concrete implementations:
public class StrategyWildCardStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "_" (a wildcard)
return "StrategyWildCardStateOne";
}
}
public class StrategyIntegerStringStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "1" (an integer string)
return "StrategyIntegerStringStateOne";
}
}
And the third strategy:
public class StrategyNormalStringStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "abc" (a normal string)
return "StrategyNormalStringStateOne";
}
}
Simple factory
There is no pattern like simple factory. However, it is a place where we can get instances of strategies by key. So by doing this we avoided to use multiple if else statements to choose correct strategy.
So, we need a place where we can store strategies by state and argument value. At first, let's create MyKey struct. It will have help us to differentiate State and arguments:
public struct MyKey
{
public readonly MyState MyState { get; }
public readonly string ArgumentValue { get; } // your three cases: "_",
// an integer string, a normal string
public MyKey(MyState myState, string argumentValue)
{
MyState = myState;
ArgumentValue = argumentValue;
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is MyKey mys
&& mys.MyState == MyState
&& mys.ArgumentValue == ArgumentValue;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + MyState.GetHashCode();
hash = hash * 23 + ArgumentValue.GetHashCode();
return hash;
}
}
}
and then we can create a simple factory:
public class StrategyStateFactory
{
private Dictionary<MyKey, IDifferentLogicStrategy>
_differentLogicStrategyByStateAndValue =
new Dictionary<MyKey, IDifferentLogicStrategy>()
{
{ new MyKey(MyState.One, "_"), new StrategyWildCardStateOne() },
{ new MyKey(MyState.One, "intString"),
new StrategyIntegerStringStateOne() },
{ new MyKey(MyState.One, "normalString"),
new StrategyNormalStringStateOne() }
};
public IDifferentLogicStrategy GetInstanceByMyKey(MyKey myKey)
{
return _differentLogicStrategyByStateAndValue[myKey];
}
}
So we've written our strategies and we've stored these strategies in simple factory StrategyStateFactory.
Then we need to check the above implementation:
StateHandler chain = new OneStateHandler();
StateHandler secondStateHandler = new TwoStateHandler();
StateHandler thirdStateHandler = new ThreeStateHandler();
chain.SetSuccessor(secondStateHandler);
secondStateHandler.SetSuccessor(thirdStateHandler);
Arguments arguments = new Arguments("_", "_", MyState.One);
IDifferentLogicStrategy differentLogicStrategy = chain.Execute(arguments);
string evaluatedResult =
differentLogicStrategy.Evaluate(arguments); // output: "StrategyWildCardStateOne"
I believe I gave basic idea how it can be done.

How to create an optional module signature type in OCaml/Reason

I am trying to follow the builder design pattern using modules in Reason.
I have the following type:
type userBuilderType = {
mutable name: string,
};
As well as signature type:
module type UserBuilderType = {
let name: string;
};
I am passing the UserBuilderType signature type as a functor to the BuilderPattern:
module BuilderPattern = fun(Builder: UserBuilderType) => {
let builder = {
name: "",
};
let setName = builder.name = Builder.name;
let getName () => builder.name;
};
I am then passing the appropriate value as a module doing the following:
module SetOfMixedPairs = BuilderPattern({
let name = "asd";
});
However, in order for this builder design pattern, to truly be a builder design pattern, the signature type will need to be optional. I am struggling as how to do so. If I were for instance, to edit the signature type to be empty:
module type UserBuilderType = {};
The compiler will complain: Unbound value Builder.name. Any suggestions as to how to make the signature type optional, are more than welcome. My thanks as always.
Full code can be seen here.
First of all, usually you can't implement a design pattern using some mechanism of a language, as design patterns are not expressible directly in the language type system and syntax. Design patterns describe a particular methodology for solving recurring problems in software development. As soon, as a language provides a mechanism to express a design pattern directly, this is no longer considered a design pattern. Thus something that is a design pattern in one language, becomes a mechanism in another language. For example, a loop in assembly language is a design pattern, though in most modern languages it's a syntactic construct. A presence of design patterns usually indicates a lack of expressivity of a particular language or programming paradigm. Though, no matter how expressive your language, there always be abstractions, that can't be implemented directly using the language mechanisms.
You should also understand that GoF design patterns were written with the OOP paradigm in mind with peculiarities and limitations of OOP languages of that time. So they are not always applicable or even needed in OCaml/Reason or any other languages with parametric polymorphism and first-class functions.
In particular, the problem that the Builder pattern is trying to solve is an absence of first-class constructors and parametric polymorphism. Since we have both in Reason, we are usually not bothered with designing complex hierarchies of types. Another limitation of OOP is an absence of algebraic data types, that are ideal language mechanism for implementing complex compound data structures such as abstract syntax trees (expression parsing trees) and so on.
With all this said, you can still use the Builder pattern in Reason, but most likely you don't actually need it, as the language provides much better and more expressible mechanisms for solving your problem. Let's use the SportsCarBuilder code from Wikipedia, as our working example,
/// <summary>
/// Represents a product created by the builder
/// </summary>
public class Car
{
public string Make { get; }
public string Model { get; }
public int NumDoors { get; }
public string Colour { get; }
public Car(string make, string model, string colour, int numDoors)
{
Make = make;
Model = model;
Colour = colour;
NumDoors = numDoors;
}
}
/// <summary>
/// The builder abstraction
/// </summary>
public interface ICarBuilder
{
string Colour { get; set; }
int NumDoors { get; set; }
Car GetResult();
}
/// <summary>
/// Concrete builder implementation
/// </summary>
public class FerrariBuilder : ICarBuilder
{
public string Colour { get; set; }
public int NumDoors { get; set; }
public Car GetResult()
{
return NumDoors == 2 ? new Car("Ferrari", "488 Spider", Colour, NumDoors) : null;
}
}
/// <summary>
/// The director
/// </summary>
public class SportsCarBuildDirector
{
private ICarBuilder _builder;
public SportsCarBuildDirector(ICarBuilder builder)
{
_builder = builder;
}
public void Construct()
{
_builder.Colour = "Red";
_builder.NumDoors = 2;
}
}
public class Client
{
public void DoSomethingWithCars()
{
var builder = new FerrariBuilder();
var director = new SportsCarBuildDirector(builder);
director.Construct();
Car myRaceCar = builder.GetResult();
}
}
We will provide a one-to-one translation from C# to Reason, to show the direct counterparts of C# mechanisms in Reason. Note, we will not build an idiomatic Reason code, people will unlikely follow the Builder Pattern in Reason.
The Car class defines an interface of a build product. We will represent it as a module type in Reason:
module type Car = {
type t;
let make : string;
let model : string;
let numDoors : int;
let colour: string;
let create : (~make:string, ~model:string, ~numDoors:int, ~colour:string) => t;
};
We decided to make the car type abstract (letting an implementor to choose a particular implementation, whether it would be a record, an object, or maybe an key to a SQL database of cars.
We will now define a corresponding interface for the car builder:
module type CarBuilder = {
type t;
type car;
let setColour : (t,string) => unit;
let getColour : t => string;
let setNumDoors : (t,int) => unit;
let getNumDoors : t => int;
let getResult : t => car;
}
Now let's implement a concrete builder. Since we decided to make the car type abstract, we need to parametrize our concrete builder with the car type. In OCaml/Reason, when you need something to parametrize with a type, you usually use functors.
module FerariBuilder = (Car: Car) => {
type t = {
mutable numDoors: int,
mutable colour: string
};
exception BadFerrari;
let setColour = (builder, colour) => builder.colour = colour;
let getColour = (builder) => builder.colour;
let setNumDoors = (builder, n) => builder.numDoors = n;
let getNumDoors = (builder) => builder.numDoors;
let getResult = (builder) =>
if (builder.numDoors == 2) {
Car.create(~make="Ferrari", ~model="488 Spider",
~numDoors=2, ~colour=builder.colour)
} else {
raise(BadFerrari)
};
};
And finally, let's implement a director.
module Director = (Car: Car, Builder: CarBuilder with type car = Car.t) => {
let construct = (builder) => {
Builder.setColour(builder, "red");
Builder.setNumDoors(builder, 2)
};
};
I will let you implementing the user code as an exercise. Hint, you need to start with a concrete implementation of the Car interface. You may look and play with the code (including the OCaml and Javascript version) at Try Reason.

IL comments with cecil

Is it possible using mono Cecil to get and set IL comments? I'm trying to add a comment to an assembly using a patcher, so that if the patcher gets run on the file twice it can access the comment and avoid making changes twice.
No you can not add comments to the methodbody.
But you can persist your information in the metadata by adding them as custom attributes on the first run. When you need complex data it could be a bit tricky since types in custom attributes are limited to:
One of the following types: bool, byte, char, double, float, int, long, short, string.
The type object.
The type System.Type.
An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility (Section
17.2).
Single-dimensional arrays of the above types.
But when you are a bit creative it should be doable, for example when its enough to mark offsets in the methodbody after a change you could add metadata like this:
public class C
{
[TypeOneChanges(new uint[] { 0, 16, 124 })]
[TypeTwoChanges(new uint[] { 5, 10 })]
public void M() { }
}
[AttributeUsage(System.AttributeTargets.Method)]
class RemarkableOffsetAttribute : Attribute
{
public uint[] Offsets { get; }
public RemarkableOffsetAttribute(uint[] offsets)
{
Offsets = offsets;
}
}
class TypeOneChangesAttribute : RemarkableOffsetAttribute
{
public TypeOneChangesAttribute(uint[] offsets) : base(offsets) { }
}
class TypeTwoChangesAttribute : RemarkableOffsetAttribute
{
public TypeTwoChangesAttribute(uint[] offsets) : base(offsets) { }
}

Wrong approach or Wrong OOP design?

Following is my code isolation.
Interactable Interface.
public interface Interactable <E extends Interactable> {
List<Person> personsInteracting = new ArrayList<>();
List<Person> personsWaiting = new ArrayList<>();
long INTERACTION_TIME = 5 * 60;
default int getNumberOfPeopleInteracting () {
return personsInteracting.size();
}
default int getNumberOfPeopleWaiting () {
return personsWaiting.size();
}
boolean isMultipleActionsAllowed ();
boolean isFurtherActionsAllowed ();
public abstract boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException;
E getObject ();
EnumSet<Interactions> getInteractions ();
}
InteractiveObject Abstract Class
public abstract class InteractiveObject implements Interactable {
protected final String name;
protected int numberOfSimultaneousInteractions;
protected Interactions currentInteraction;
public InteractiveObject (final String name) {
this.name = name;
}
#Override
public boolean isMultipleActionsAllowed () {
return numberOfSimultaneousInteractions > 1;
}
#Override
public boolean isFurtherActionsAllowed () {
return personsInteracting.isEmpty() ||
(getNumberOfPeopleInteracting() > numberOfSimultaneousInteractions);
}
#Override
public boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException {
boolean isOccupied = false;
if (!isFurtherActionsAllowed()) {
throw new InteractionNotPossibleException(this + " is already in use by some other " +
"person.");
}
personsInteracting.add(person);
currentInteraction = interaction;
return isOccupied;
}
#Override
public String toString () {
return name;
}
public int getNumberOfSimultaneousInteractions () {
return numberOfSimultaneousInteractions;
}
}
Chair (One of the child class)
public class Chair extends InteractiveObject {
private final EnumSet<Interactions> INTERACTIONS = EnumSet.copyOf(Arrays.asList(
new Interactions[] {Interactions.DRAG, Interactions.SIT}));
public Chair (final String objectName) {
super(objectName);
super.numberOfSimultaneousInteractions = 1;
}
#Override
public Interactable getObject () {
return this;
}
#Override
public EnumSet<Interactions> getInteractions () {
return INTERACTIONS;
}
}
Here is the piece of code that executes and brings the problem, this question is asked for.
final InteractiveObject chair1 = new Chair("Chair1");
final Person person1 = new Person("Person1");
final Room room = new Room("Room1", 2, 2);
room.personEnters(person1);
room.putObject(chair1);
person1.tryOccupying(chair1);
Above piece of code, successfully occupies the chair object. Now,
final InteractiveObject chair2 = new Chair("Chair2");
final Person person2 = new Person("Person2");
final Room room2 = new Room("Room2", 2, 2);
room2.personEnters(person2);
room2.putObject(chair2);
person2.tryOccupying(chair2);
This piece of code doesn't let the person2 occupy since my code states that 1 person is already interacting with chair2, where as no one is interacting with it.
Solution of my problem:
I moved my List of personInteracting to InteractiveObject and function tryOccupiedBy to each child class and everything works fine.
Questions:
I put personsInteracting in Interactable interface since I believe that every future implementation of Interactable will have it. Developers won't have to implement themselves. (But perhaps this idea seems to be wrong)
If tryOccupiedBy function has same implementation, what is the purpose of whole OOP?
I now know that the isolation was wrong and I know where to place the pieces to get the results. But can someone kindly point me out about some OOP concept which I did not understand and should be implemented in a much better way?
The default keyword was not added to the Java language to do the kind of thing which you seem to be trying to achieve. Data defined in an interface is intended to be constant - the modifiers 'public static' are automatically applied to any field definitions in an interface. If you create a default method in the interface then it must either be stateless or act directly only on purely statically available state. Default methods can call other interface methods to modify instance state, .
By placing personsInteracting field in the interface, you made the same instance common to every object implementing that interface, and so your tryOccupying method was acting on purely global state.
So, the purpose of having default methods in the Java language is to support adding new methods to interfaces in a backwards compatible fashion, nothing more. You shouldn't reuse it as a generic form of code re-use - it was never intended for that and you'll get (as you did) weird behaviour.
You didn't have to put tryOccupiedBy in the child classes, however, so you didn't have to have a load of duplicated code. You could still declare the method signature in the interface (which is what interfaces are generally supposed to do) and then implement the common method in your abstract base class. By putting the data fields in the base class, you make them instance fields and so they are not shared between objects.
public interface Interactable <E extends Interactable> {
...
boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException;
...
}
public abstract class InteractiveObject implements Interactable {
private final List<Person> personsInteracting = new ArrayList<>();
private final List<Person> personsWaiting = new ArrayList<>();
...
#Override
public final boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException {
boolean isOccupied = false;
if (!isFurtherActionsAllowed()) {
throw new InteractionNotPossibleException(this + " is already in use by some other " +
"person.");
}
personsInteracting.add(person);
currentInteraction = interaction;
return isOccupied;
}
...
}

Serialization of derived objects with json.net

Serialization of an object inherited from Dictionary<DateTime, double> does not include field and properties in the resulting json string.
Note: This is a simplified example. Yes, I know one should not derive from the Dictionary type.
Serializing an object of the type:
public class Timeserie : Dictionary<DateTime, double>
{
public string id;
public Timeserie()
{
}
public Timeserie(string id)
{
this.id = id;
}
}
Using:
var json_settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };
var s = JsonConvert.SerializeObject(timeserie, Formatting.Indented, json_settings);
Includes only the base class data:
{
"01/02/2009 00:00:00": 10.23,
"01/05/2009 00:00:00": 11.33
}
The field id is not included.
How do I need to use json.net so that fields and properties declared in the derived class are included in the serialization?
It seems, looking through the code for json.net, it has a special contract for handling dictionaries.
so either make a new contract, or encapsulate the dictionary ( ie, make the dictionary a property of your class )
if you make plain classes that inherit off each other, this code will serialize all the properties of the derived classes