I'm trying to figure out the best design pattern to use for managing a "competition" between two interacting objects. For example, if I want to have a Fox class that chases a Rabbit class through a simple environment. I want to let them "compete" and find out which one wins. Eventually it would become a teaching tool that students can use to experiment with inheritance and other OO programming skills.
Is there an established design patter for this use case?
Here's the best I could come up with: one class to represent the environment that hosts both other objects. I'm keeping it very simple and assuming the animals only run in straight lines and the fox catches the rabbit if he gets close enough to bite the rabbit. Here is some code demonstrating what I'm describing. I used PHP because I can write it quickly, but I don't want to focus on the specifics of the language. My question is really about the design pattern / architecture.
class Forrest() {
public $fox;
public $rabbit;
public $width = 100; //meters?
public $length = 100;
__construct() {
$this->fox = new Fox();
$this->rabbit = new Rabbit();
$this->theChase();
}
public function theChase() {
while (!$this->rabbit->isBitten) {
$this->rabbit->react($fox);
$this->fox->react($rabbit);
}
log('The fox got the rabbit!');
}
}
abstract class Animal() {
public $speed;
public $hasTeeth = false;
public $position;
public $direction;
public $isBitten = false;
public function run($distance) {
// update coordinates based on direction and speed
}
public function bite($someone) {
if (isCloseEnough( $someone ) && $this->hasTeeth) {
$someone->isBitten = true;
log(get_class($this) . ' bit the ' . get_class($someone)); //the Fox bit the Rabbit
}
}
public abstract function react($someone);
}
class Rabbit extends Animal {
__construct() {
$this->speed = 30;
$this->position = [0,0];
$this->direction = 'north';
log(get_class($this) . ' starts at 0,0');
}
public react($fox) {
//avoid the fox
}
}
class Fox extends Animal {
__construct() {
$this->speed = 20;
$this->position = [100,100];
$this->direction = 'south';
log (get_class($this) . ' starts at 100,100');
}
public react($rabbit) {
//try to catch the rabbit
}
}
There are two immediate problems I see with this approach:
This architecture results in sequential, alternating actions. In other words, first the rabbit does something then the fox does something then the rabbit does something... This is more like a card game where each player takes turns moving. It would be more interesting if both objects were able to react simultaneously.
There is not yet a system for limiting the amount of activity per "turn". There needs to be some sort of restriction on what can happen in a single "turn" to keep it interesting. Otherwise the fox could simply run() run() run() ... run() until it catches the rabbit on it's first turn.
There are probably other problems that I haven't noticed yet. I suspect that the answer to both (1) and (2) above is some sort of event system that allows action from one animal to trigger action from the other and visa versa. I also think there may need to be some representation of time associated with each action, but I'm not entirely sure.
So, you are tasked with fitting something like game under design patterns, which originally were created for enterprise kind of software only. Games are not enterprise software by definition, and that's the reason why many people have avoided thinking about design patterns when designing games. That does not mean it's not doable though.
My recommendations:
Think model first: design your problem as you envision it.
Remember it's still a game, so it needs to follow game development patterns: there's just one actually - game loop.
So, if you combine the two above (I wish the second was not there), then I'd design it this way (I will mention the design pattern if my suggestions remind me one):
Mark current time point.
Environment starts game loop.
For each loop step, calculate time passed since the last time point. This will give you time span in some units (e.g. N milliseconds passed).
Given time span, you need to ask each object to update its state (conceptually, ask them - where would you be now if N milliseconds had passed?). This reminds me of Visitor pattern a bit.
After all objects have updated their states, Environment displays results on the screen (in real games this means to draw the current state of the game - each object gets redrawn on the screen; for your simple application, you could check whether Fox has reported that it has caught the rabbit).
Obviously, while within the loop step, you need to keep marking the current time, so that the time span difference can be calculated at each step.
Step #4 involves some complexities, especially if the accuracy is critical. e.g. what if the time span is about a second, and within that second (in the middle somewhere) the fox would have caught the rabbit, but in the end there is still distance? this can happen if the speeds of fox and rabbit are functions of time (sometimes they slow down, sometimes they speed up) [btw, this sounds like a Strategy pattern - variation for calculating current speed - e.g. linear vs time-function). Obviously, if the fox and rabbit both just report their positions at the end of the time span, the catching moment will be missed, which is not desirable.
Here is how I would solve it: for given time span, if it's more than a single millisecond (let's assume millisecond is the shortest acceptable atomic time for good enough accuracy), then split it into the time spans of millisecond length each, and for each millisecond, ask every object to update its state. After all, if the object can update its state based on a time span, we can call it as many times as we want with shorter time spans. Obviously, there is unavoidable side effect - you need to update states in some order, but given that millisecond is too short period of time, it should be just fine to do that.
Pseudo code would look like this:
var foxAndRabbitGame = new FoxAndRabbitGame();
foxAndRabbitGame.RunGame(screen); //visitor
/* when this line is reached, game is over. Do something with it. */
class FoxAndRabbitGame
{
private fox = new Fox(Speed.Linear()); //strategy
private rabbit = new Rabbit(Speed.Linear()); //strategy
void RunGame(screen)
{
var currentTime = NOW;
while (true)
{
var timePassed = NOW - currentTime;
currentTime = NOW;
foreach (millisecond in timePassed)
{
fox.UpdateState ( millisecond , rabbit );
rabbit.UpdateState ( millisecond, fox );
if (fox.TryBite(rabbit))
{
//game over.
return;
}
}
//usually, drawing is much slower than calculating state,
//so we do it once, after all calculations.
screen.Draw(this); //visitor
screen.Draw(Fox); //visitor
screen.Draw(rabbit); //visitor
}
}
}
In a game-loop, one usually would update the velocities (here in your the react function) of both objects and then update the position of the objects. Thus moving simultaneously.
while(!gameOver) {
rabbit->react(fox);
fox->react(rabbit);
rabbit->updatePosition();
fox->updatePosition();
}
For limiting activity per turn/frame you'd have to think of something clever. For example you could make a certain set of actions that one can do, and each action has an energy cost. You would get a certain amount of energy each turn to use. You'd have to have more than one run() action though to make this interesting :).
I would suggest the Mediator pattern. It generally promotes loose
direct coupling between a set of objects (in your case fox and
rabbit). You would need to introduce another object which captures
the state of the system as a result of the actions of the rabbit and
the fox (eg call it "the chase").
A mediator object would handle the interaction between all
objects. I.e evaluate the actions requested by rabbit and fox,
then determine what the actual result of these actions will be
(everything goes through the mediator!) and update "the chase"
accordingly. This way you can control your issues 1 and 2 above,
or other issues.
I have previously implemented this pattern for HMI interfaces,
where users could interact with a system via keypad & screen,
and depending on selections/system state / previous selection,
etc appropriate state transitions needed to occur.
On a general idea my approach would be:
Each subject (fox, rabbit, etc) has a state (in your case velocity, position and direction).
The environment (container) has a state which is a combination of the states of the subjects and others constraint if needed (impenetrable zones, ruined terrain, etc).
Each subject has a cost function to be minimized (the fox has the distance between the subjects, the rabbit the inverse of such distance)
Each subject must have some constraint (such as max_distance_per_turn, max_direction_changes_per_turn, etc) to prevent the first subject to win at time 1.
The environment state can affect the subject actions (e.g. the fox running has dug a hole which can't be passed by the rabbit), so each action must be aware of the global current state.
Each subject modify its state starting only from the starting environment + subjects states; the fox moves accordingly to rabbit's position at time 0 (and the rabbit does the same). Note that this is different from fox.react(rabbit); rabbit.react(fox); because the rabbit knows where the fox is at time 1 (after it moved).
If needed, also the whole transaction should be examinated: if at time 0 the rabbit is not biteable, and at time 1 it is also not biteable, but during the transition it reached a point in where it was biteable, the fox should win. To avoid this th goal is to make the "turns" as atomic as possible, in order to ignore those transactions. Alternatively you can add a transaction check to the environment to be run after each turn.
In a more general view, you can think of that environment as a closed system with retroaction: each action modify the whole state which will affect the new actions. In this scenario each istruction is still sequential, but each "turn" is indeed a closed transaction from one state to the next one, in which all the subjects execute simultaneously.
Elaborating on the mediator pattern suggestion, to add the illusion of simultaneity the game state could be extracted to a separate object (plain old data) and updated after all objects made their decisions. For example (in java-ish language)
public class OpponentData {
private Position theirPosition; // + public get
// constructor with theirPosition param, keeping the class immutable
}
public interface Animal {
// returns data containing their updated data
OpponentData React(OpponentData data);
Position GetPosition();
}
public class Fox implements Animal {
public OpponentData React(OpponentData data) {
if (this.position == data.GetPosition())
// this method can be a little tricky to write, depending on your chosen technology, current architecture etc
// Fox can either have a reference to GameController to inform it about victory, or fire an event
// or maybe even do it itself, depending if you need to destroy the rabbit object in game controller
EatTheRabbit();
else {
// since the game state won't be updated immediately, I can't just run until I reach the rabbit
// I can use a bunch of strategies: always go 1 meter forward, or use a random value or something more complicated
ChaseTheRabbit();
}
return new OpponentData(this.position);
}
}
public class Rabbit implements Animal {
public OpponentData React(OpponentData data) {
KeepRunningForYourLife();
// maybe you can add something more for the rabbit to think about
// for example, bushes it can run to and hide in
return new OpponentData(this.position);
}
}
public class GameController {
private Fox fox;
private Rabbit rabbit;
private OpponentData foxData;
private OpponentData rabbitData;
private void Init() {
fox = new Fox();
rabbit = new Rabbit();
foxData = new OpponentData(fox.GetPosition());
rabbitData = new OpponentData(rabbit.GetPosition());
}
private void PerformActions() {
var oldData = foxData;
foxData = fox.React(rabbitData);
// giving the old data to the rabbit so it doesn't know where the fox just moved
rabbitData = rabbit.React(oldData);
}
}
If you want the game to depend on more factors than just the position, you can easily extend the OpponentData class adding health level, strength etc.
This approach solves both your problems, because each of the players (fox and rabbit) doesn't know what the other is doing in the same turn so the rabbit can evade the fox and the fox can't just run() run() run() to it's victim (because it doesn't know where the rabbit is going to move). Fun fact - the Game of Thrones board game uses the same technique to create an illusion of giving orders to your armies simultaneously with other players.
I thought, there should be two abstract classes related to animal abstract class.(Omnivore and carnivore classes, both have different attributes)
here is Animal Abstract class
public abstract class Animal implements Runnable{
private double speed = 0 ; // Default
private Point location = new Point(new Random().nextInt(50) + 1 , new Random().nextInt(50) + 1);
abstract void runAway(Animal animal);
abstract void chase(Animal animal);
abstract void search4Feed();
abstract void feed();
public synchronized Point getLocation() {
return location;
}
public synchronized void setLocation(Point location) {
this.location = location;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
}
Here is Carnivore and Omnivore Classes
public abstract class Carnivore extends Animal {
Animal targetAnimal ;
}
public abstract class Omnivore extends Animal {
Animal chasingAnimal;
}
For forest class and its implementation, Iforest may be implemented by different forest classes.And it needs to keep its own animal ecosystem.
public class Forest implements IForest {
private List<Animal> animalList = new ArrayList<Animal>();
public Forest() {
}
#Override
public void addAnimalToEcoSystem(Animal animal) {
animalList.add(animal);
}
#Override
public void removeAnimalFromEcoSystem(Animal animal) {
animalList.remove(animal);
}
#Override
public void init() {
// to do:
}
#Override
public List<Animal> getAnimals() {
return this.animalList;
}
}
public interface IForest {
void removeAnimalFromEcoSystem(Animal animal);
void addAnimalToEcoSystem(Animal animal);
List<Animal> getAnimals();
void init();
}
Here is rabbit and fox classes.
Rabbit and fox classes have IForest class instance in their constructor.
Chasing an animal or running away from any animal needs to be forest ecosystem
And these classes has to notify their movements to Forest classes via IForest interface.Here I used Runnable thread because these classes needs to move independently, not sequential.In run method you can define rules for hunter or hunt's according to your specified conditions.
public class Rabbit extends Omnivore {
private IForest forest = null ;
public Rabbit(IForest forest) {
this.forest = forest;
this.setSpeed(40);
}
#Override
public void runAway(Animal animal) {
this.chasingAnimal = animal;
this.run();
}
#Override
public void chase(Animal animal) {
// same as fox's
}
#Override
void feed() {
// todo:
}
#Override
void search4Feed() {
}
#Override
public void run() {
double distance = 10000; //default,
this.chasingAnimal.runAway(this); // notify rabbit that it has to run away
while(distance < 5){ // fox gives chasing up when distance is greater than 5
distance = Math.hypot(this.getLocation().x - this.chasingAnimal.getLocation().x,
this.getLocation().y - this.chasingAnimal.getLocation().y);
if(distance < 1) {
break; // eaten
}
//here set new rabbit's location according to rabbit's location
}
}
}
public class Fox extends Carnivore {
private IForest forest = null ;
public Fox(IForest forest) {
this.forest = forest;
this.setSpeed(60);
}
#Override
public void chase(Animal animal) {
this.targetAnimal = animal;
this.run();
}
#Override
public void run() {
double distance = 10000; //default,
this.targetAnimal.runAway(this); // notify rabbit that it has to run away
while(distance < 5){ // fox gives chasing up when distance is greater than 5
distance = Math.hypot(this.getLocation().x - this.targetAnimal.getLocation().x,
this.getLocation().y - this.targetAnimal.getLocation().y);
if(distance < 1) {
feed();
break;
}
//here set new fox's location according to rabbit's location
}
}
#Override
public void runAway(Animal animal) {
// same as rabbit's
}
#Override
public void feed() {
// remove from forest's animal list for the this.targetAnimal
}
#Override
void search4Feed() {
// here fox searches for closest omnivore
double distance = -1;
Animal closestFeed = null;
List<Animal> l = this.forest.getAnimals();
for (Animal a : l) {
double d = Math.hypot(this.getLocation().x - a.getLocation().x, this.getLocation().y - a.getLocation().y);
if (distance != -1) {
if(d < distance){
this.chase(a);
}
}
else{
distance = d ;
}
}
}
}
init method below
public static void main(String[] args) {
// you can use abstract factory pattern instead.
IForest forest = new Forest();
forest.addAnimalToEcoSystem(new Rabbit(forest));
forest.addAnimalToEcoSystem(new Fox(forest));
forest.init();
}
if you want to make this more complicated such as collabration or something else
you need to use observable pattern.
It can be used to create animals,forest via abstract factory pattern.
Sorry for the messy code due to the fact that I dont have much time.
I hope this helps you.
The competition between rabbits, foxes and possibly other animals can be modeled using discrete event simulation, which could be considered a design pattern per se (simulation clock, event queue, …).
The objects may implement Strategy pattern. The execute method could be named decideAction in this case – it would get the old state of the world (read-only) and produce a decision (description of an action).
The simulation would plan the event that results from the decision, then. When the event is processed, the simulation will change the state of the world. Thus, the simulation could be considered an instance of Mediator pattern because it isolates the agents from direct interaction – they just see the state of the world and produce decisions, while production of new state of the world and evaluation of rules (such as velocities and detection of successful bite or escape) is left to the simulation.
To make all agents’ (animals’) decisions simultaneous, plan all events to happen simultaneously (in the simulation time) and update the world state only after all events occurring at the same simulation time have been processed (the decisions have been made).
You would not need the event queue and simulation clock, then. Just a loop that gathers all the decisions and finally updates the state of the world in each iteration would be enough.
This may not be what you want, though, e.g. because initially, it might take some time to a rabbit to notice that a fox is approaching. It might be more interesting if the timeout between events for an animal (reaction time) varies with its state (alert, sleeping, etc.).
The amount of activity per “turn” cannot be limited, when the animal can directly change the world state and is implemented using almost arbitrary code. If the animal just describes its action, its type and parameters can be validated by the simulation and possibly rejected.
Related
my app mostly work with local database for this i am using room Prepopulate database for my project with Hilt and other jetpack component . Using DB Browser to create db file
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
.createFromAsset("database/myapp.db")
//.fallbackToDestructiveMigration()
//.addMigrations(MIGRATION_1_2)
.build()
database is simple with 3 column id name and isAlive , isAlive is a boolean type and this will toggle as true or false .
suppose - initially their will be 10 rows only , in next update their will be 5 more rows and 1 new column strength, and this new column will be different for all 15 rows . How to migrate this without loosing previous data and adding new data
if i use .fallbackToDestructiveMigration() then all 15 rows with 4 column will be visible but isAlive value will be lost
if i use .addMigrations(MIGRATION_1_2) then my new 5 row are not getting view and strength column is set to 0
val MIGRATION_1_2 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("alter table user add column strength not null default 0")
}
}
You could, in the Migration (as you need both the existing data and the new asset data), in addition to ALTERING the structure, open the asset as a database extract the data and then on a per row basis,
try to insert the data, but to IGNORE the insert if the row exists (i.e. duplicate id)
if the id exists to instead update the columns that are not user changeable (i.e. the isAlive column should be left asis).
I believe that you would have issues/complexities if you attempted this via Room.
The following is a working solution that instead uses the good old SQliteDatabase to handle the prepackgaed database and do the above.
#Database(entities = [User::class], exportSchema = false, version = 2 /* CHANGED FOR V2 */)
abstract class AppDatabase: RoomDatabase() {
abstract fun getTheDAOs(): TheDAOs
companion object {
private var instance: AppDatabase?=null
const val workingCopyExtension = "_wc" /* FOR MIGRATION */
const val databaseName = "Sample.db" /* ADDED/SUGGESTED as value is used more than once */
const val assetFileName = "database/myapp.db" /* ADDDED SUGGESTED as value is used more than once */
lateinit var appContext: Context
fun getInstance(context: Context): AppDatabase {
appContext = context
if (instance == null) {
instance = Room.databaseBuilder(context,AppDatabase::class.java, databaseName)
.allowMainThreadQueries() /* For brevity and convenience of demo */
.addMigrations(MIGRATION_1_2)
.createFromAsset(assetFileName)
.build()
}
return instance as AppDatabase
}
val MIGRATION_1_2 = object: Migration(1,2) {
#SuppressLint("Range")
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("alter table user add column strength integer not null default 0")
/* cope the asset file */
getAssetFileCopy(context = appContext, assetFileName, databaseName)
/* open the asset as an SQLiteDatabase */
val asset = SQLiteDatabase.openDatabase(appContext.getDatabasePath(databaseName +workingCopyExtension).path,null,0)
/* Extract all the data from the asset (now database) */
val csr = asset.query("user",null,null,null,null,null,null,null)
val cv = ContentValues()
/* Loop through the extracted asset data */
while (csr.moveToNext()) {
/* Prepare to INSERT OR IGNORE row as per Cursor */
cv.clear()
cv.put("id",csr.getInt(csr.getColumnIndex("id")))
cv.put("name",csr.getString(csr.getColumnIndex("name")))
cv.put("isAlive",csr.getInt(csr.getColumnIndex("isAlive")))
cv.put("strength",csr.getInt(csr.getColumnIndex("strength")))
/* Do the INSERT OR IGNORE testing the returned value (-1 if not inserted else 1 or greater) */
/* if inserted then as row did not exist then values are as per the asset so no need to do anything*/
/* if not inserted then the row existed so the strength should be applied i.e. as per the asset update */
if (database.insert("user",SQLiteDatabase.CONFLICT_IGNORE,cv) <= 0) {
cv.clear()
cv.put("strength",csr.getInt(csr.getColumnIndex("strength")))
database.update("user",OnConflictStrategy.IGNORE,cv,"id=?", arrayOf<String>(csr.getString(csr.getColumnIndex("id"))))
}
}
/* Clean up (close the Cursor and delete the )*/
csr.close()
asset.close() /* not too worried about closing it as it has not been changed */
File(appContext.getDatabasePath(databaseName + workingCopyExtension).path).delete()
}
}
/* As it says create a copy of the asset in the device's databases folder */
fun getAssetFileCopy(context: Context,assetFileName: String, databaseName: String) {
val assetInputStream = context.assets.open(assetFileName)
val workingCopy = File(context.getDatabasePath(databaseName + workingCopyExtension).path)
if (workingCopy.exists()) {
workingCopy.delete()
}
assetInputStream.copyTo(workingCopy.outputStream())
}
}
}
Note that to reduce the possibility of typos repeated names/values have largely been assigned to val's.
Note run on the mainThread (aka .alloMainThreadQueries) for the convenience of testing
Testing
V1 was originally loaded from the asset based upon:-
After loading the isAlive values were all flipped using #Query("UPDATE user SET isAlive= NOT isAlive")
So the database then being (via App Inspection):-
i.e. isAlive values have been flipped (true to false and false to true) to reflect user changes.
The asset then changed to:-
note that the isAlive is as per the original asset (even rows are true aka not flipped)
Using the changed asset, the new strength column and V2 the resultant database (via App Inspection) is:-
5 new rows added
10 existing rows have the flipped isAlive
10 existing rows have the strength applied as per the asset
Final test App is uninstalled and rerun at V2. The database:-
i.e. the new install is with data as per the asset (isAlive aren't flipped)
I'm upgrating from IText 5 to IText 7. The code below is from version 5 which has a method to get the actual number of lines written. How can I accomplish the same using IText 7?
Paragraph p = new Paragraph(veryLongText, font);
ColumnText column1 = new ColumnText(writer.DirectContent);
column1.SetSimpleColumn(bottomX, bottomY, topX, 100);
column1.AddElement(p);
column1.Go(true);
noOfLines = column1.LinesWritten; <---- No of Lines
Layout mechanism in iText 7 is much more complex and feature-rich than mechanism in iText 5, and notion of written lines might be very much opinion-based in many complex layout cases. That's why the number of written lines is not maintained by the layout engine and is not available for query. However, it's very easy to extend your elements/renderers to support calculating the number of written lines. Here is how to do it. First, you need to override a Paragraph to aggregate the number of lines and ParagraphRenderer to provide the info of the lines written back to Paragraph:
private static class LineCountingParagraph extends Paragraph {
private int linesWritten = 0;
public LineCountingParagraph(String text) {
super(text);
}
public void addWrittenLines(int toAdd) {
linesWritten += toAdd;
}
public int getNumberOfWrittenLines() {
return linesWritten;
}
#Override
protected IRenderer makeNewRenderer() {
return new LineCountingParagraphRenderer(this);
}
}
private static class LineCountingParagraphRenderer extends ParagraphRenderer {
public LineCountingParagraphRenderer(LineCountingParagraph modelElement) {
super(modelElement);
}
#Override
public void drawChildren(DrawContext drawContext) {
((LineCountingParagraph)modelElement).addWrittenLines(lines.size());
super.drawChildren(drawContext);
}
#Override
public IRenderer getNextRenderer() {
return new LineCountingParagraphRenderer((LineCountingParagraph) modelElement);
}
}
Now, just use the customized classes instead of the standard ones and query the information after an element was added to a Document or Canvas:
LineCountingParagraph p = new LineCountingParagraph("text");
document.add(p);
System.out.println(p.getNumberOfWrittenLines());
Note that this mechanism also allows you to calculate the number of lines written that satisfy some condition. You can analyze elements in lines list.
I am using the XMLUnit in JUnit to compare the results of tests. I have a problem wherein there is an Element in my XML which gets the CURRENT TIMESTAMP as the tests run and when compared with the expected output, the results will never match.
To overcome this, I read about using org.xmlunit.diff.NodeFilters, but do not have any examples on how to implement this. The code snippet I have is as below,
final org.xmlunit.diff.Diff documentDiff = DiffBuilder
.compare(sourcExp)
.withTest(sourceActual)
.ignoreComments()
.ignoreWhitespace()
//.withNodeFilter(Node.ELEMENT_NODE)
.build();
return documentDiff.hasDifferences();
My problem is, how do I implement the NodeFilter? What parameter should be passed and should that be passed? There are no samples on this. The NodeFilter method gets Predicate<Node> as the IN parameter. What does Predicate<Node> mean?
Predicate is a functional interface with a single test method that - in the case of NodeFilter receives a DOM Node as argument and returns a boolean. javadoc of Predicate
An implementation of Predicate<Node> can be used to filter nodes for the difference engine and only those Nodes for which the Predicate returns true will be compared. javadoc of setNodeFilter, User-Guide
Assuming your element containing the timestamp was called timestamp you'd use something like
.withNodeFilter(new Predicate<Node>() {
#Override
public boolean test(Node n) {
return !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart()));
}
})
or using lambdas
.withNodeFilter(n -> !(n instanceof Element &&
"timestamp".equals(Nodes.getQName(n).getLocalPart())))
This uses XMLUnit's org.xmlunit.util.Nodes to get the element name more easily.
The below code worked for me,
public final class IgnoreNamedElementsDifferenceListener implements
DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode()
.getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
I am trying to send mixed message types down a single channel with protobuf-net. I put together the following example from various sources, and it throws a StackOverflow exception on the first deserialization.
Am I going about this the right way?
FWIW the hex content of the file it creates is "A2 06 02 08 02 08 01 AA 06 02 08 04 08 03"
Thanks, Greg
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
[ProtoInclude(100, typeof(Derived1))]
[ProtoInclude(101, typeof(Derived2))]
public class Base { public int Old; }
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Derived1 : Base { public int New1; }
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Derived2 : Base { public int New2; }
class Program
{
static void Main(string[] args)
{
Base b1 = new Derived1() { Old = 1, New1 = 2 };
Base b2 = new Derived2() { Old = 3, New2 = 4 };
using (var fs = File.Create(#"C:\test.bin"))
{
Serializer.Serialize(fs, b1);
Serializer.Serialize(fs, b2);
}
Base msg3, msg4;
using (var fs = File.OpenRead(#"C:\test.bin"))
{
msg3 = Serializer.Deserialize<Base>(fs);
msg4 = Serializer.Deserialize<Base>(fs);
}
Console.WriteLine(((Derived1)msg3).New1);
Console.WriteLine(((Derived2)msg4).New2);
Console.ReadLine();
}
}
I expect the problem here is framing; protobuf (the format, not the library) was designed by google to be appendable, where append===merge. If you serialize message A, then immediately serialize message B, then deserialize the whole lot: you get one message, not two. This obviously has lots of potential to cause unexpected results, incorrectly interpreted data, and errors.
The trick, then, is to frame the messages so that you can process them separately. Fortunately, protobuf-net provides the SerializeWithLengthPrefix and DeserializeWithLengthPrefix methods for exactly this purpose. During serialization, this prepends each message with a marker to indicate the length of the data that follows. During deserialization, the length-prefix is read first, allowing the correct amount of data to be consumed for each message.
Multiple layouts and styles of length-prefix are supported; the most important thing is that they match between the serialize and deserialize step. If you want the data to be "pure protobuf" (i.e. parseable as a repeated field on an outer message on another platform), then "base-128, field 1" is a good choice.
This works fine:
using (var fs = File.Create(#"test.bin"))
{
Serializer.SerializeWithLengthPrefix(fs, b1, PrefixStyle.Base128, 1);
Serializer.SerializeWithLengthPrefix(fs, b2, PrefixStyle.Base128, 1);
}
Base msg3, msg4;
using (var fs = File.OpenRead(#"test.bin"))
{
msg3 = Serializer.DeserializeWithLengthPrefix<Base>(fs, PrefixStyle.Base128, 1);
msg4 = Serializer.DeserializeWithLengthPrefix<Base>(fs, PrefixStyle.Base128, 1);
}
I had the same issue while deserializing, the release v2.1.0-alpha-1 fixes this.
https://github.com/mgravell/protobuf-net/releases
Regards,
Pluc
We are using backbone.paginator;backgrid;backgrid-filter ;backgrid-paginator it works great we have small issue when trying sort - at server side mode -the grid by one (or more) of its columns
For Server side with are using Spring with org.springframework.data.web.PageableHandlerMethodArgumentResolver
When debugging the app it seems that the order from client side does NOT get parsed well on spring side and it falls to the default value
Two questions:
Does any one know what is the parameters that should be sent to PageableHandlerMethodArgumentResolver?
How can Backbone.PageableCollection can be tweak in order to achieve that?
Our Initialize Paginator Code
Backbone.PageableCollection.extend({
state : {
pageSize : 15,
firstPage : 0, /* Spring paging is 0-based */
},
mode : "server",
/**
* override default queryParams to fit spring pageable var names
*/
queryParams : {
pageSize:"size",
totalRecords:"totalElements",
sortKey:"sort",
order:"sort_order",
directions : { "-1": "asc", "1": "desc" }
},
})
P.S:
It seems that spring expect to get the data as array separated by comma instead regular. any idea how to it with backbone.paginator? or how to change spring to be able to parse paginator to support several of sorting parameters.
After doing some digging at Spring source PageableHandlerMethodArgumentResolver and at SortHandlerMethodArgumentResolver.java (can be found here) it Seems that Spring expect sort parameters to be with the format of
sort="column1,column2,column3...,order"&sort="column4,column5,...,order"
It seems that backbone.paginator does not support multiply ordering but in order to make paginator to support SortHandlerMethodArgumentResolver with singal ordering, one can override sync function to setup the vars.
Example
var sync = Backbone.PageableCollection.prototype.sync;
Backbone.PageableCollection.prototype.sync = function(method, model,
options) {
options.type = 'POST' // this help with unicode on tomcat and can be removed..
/**
* #override sync Add some code to support parsing of sorting parameters
* by SortHandlerMethodArgumentResolver
*/
if (!options.data) {
sync.apply(this, arguments)
}
var sortKey = _.result(this.queryParams,"sortKey");
if (!sortKey in options.data) {
sync.apply(this, arguments)
}
options.data[STR_SPRING_SORT] = options.data[sortKey]
var orderKey = _.result(this.queryParams,"order");
var STR_SPRING_SORT = "sort";
var STR_SEPERATOR = ",";
if (orderKey in options.data) {
options.data[STR_SPRING_SORT] = options.data[STR_SPRING_SORT] + STR_SEPERATOR
+ options.data[orderKey]
if (sortKey !== STR_SPRING_SORT) {
delete options.data[sortKey];
}
delete options.data["order"];
}
sync.apply(this, arguments);
};
Remark
One can force spring to change the comma and the sort string.