Let's say we have the following three classes:
[ProtoContract]
[ProtoInclude(10, typeof(FirstType))]
[ProtoInclude(20, typeof(SecondType))]
public class Base
{
[ProtoMember(1)]
public int ClassId {get;set;}
}
public class FirstClass : Base
{
...
}
public class SecondClass : Base
{
...
}
And there's relationship between the class Id (in the base class) and the type of a matching child class. For example,
var obj1 = new FirstClass() {ClassId = 1}
var obj2 = new SecondClass() {ClassId = 2}
Now let's suppose we have serialized those objects. The question is: is there any good way to deserialize the serialized protobuf based the class Id value by looking over the ClassId field? i.e., if the value of classId in the serailized protobuf is 1, then use FirstClass to deserialize remaining stream bytes.
thanks!
If you are using ProtoInclude, then protobuf-net is already taking care of which subclass to use: that is the entire point of ProtoInclude. In some cases it is not possible to use inheritance, in which case there are ways to read the proto-stream via either ProtoReader, or by using a second model which only reads that property, then resetting the source and reading again. There is an example of that here: https://stackoverflow.com/a/14572685/23354
Related
I have an application that gets a car entity from a third party database. I call the entity ThirdPartyCar. My application needs to create a Car entity by using data from a ThirdPartyCar. However, the Car entity must also derive some of its data from my application's database. For example, a status of a ThirdPartyCar might be _BOUGHT and through a database lookup my application must transform to Sold.
I currently have a Car constructor that has a ThirdPartyCar argument. But the Car constructor cannot populate the lookup data since it is an entity and entities should not have a reference to a repositories. So, I also have a service to populate the remaining data:
public class ThirdPartyCar {
#Id
private Long id;
private String vin;
private String status;
// more props + default constructor
}
public class Car {
#Id
private Long id;
private String vin;
private CarStatus status;
// more props (some different than ThirdPartyCar) + default constructor
public Car(ThirdPartyCar thirdPartyCar) {
this.vin = thirdPartyCar.getVin();
// more props set based on thirdPartyCar
// but props leveraging database not set here
}
public class CarStatus {
#Id
private Long id;
private String status;
}
public class CarBuilderService {
private final CarStatusMappingRepository repo;
public Car buildFrom(ThirdPartyCar thirdPartyCar) {
Car car = new Car(thirdPartyCar);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
}
}
The logical place to create a Car based on a ThirdPartyCar seems to be the constructor. But I have a disjointed approach b/c of the need of a repo. What pattern can I apply such that all data is created in the constructor but still not have the entity be aware of repositories?
You should avoid linking two POJO classes from different domains in constructor. These two classes should not know anything about each other. Maybe they represent the same concept in two different systems but they are not the same.
Good approach is creating Abstract Factory interface which will be used everywhere where Car should be created from ThirdPartyCar:
interface ThirdPartyCarFactory {
Car createNewBasedOn(ThirdPartyCar source);
}
and one implementation could be your RepositoryThirdPartyCarFactory:
class RepositoryThirdPartyCarFactory implements ThirdPartyCarFactory {
private CarStatusMappingRepository repo;
private CarMapper carMapper;
public Car createNewBasedOn(ThirdPartyCar thirdPartyCar) {
Car car = new Car();
carMapper.map(thirdPartyCar, car);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
return car;
}
}
In above implementation you can find CarMapper which knows how to map ThirdPartyCar to Car. To implement this mapper you can use Dozer, Orika, MapStruct or your custom implementation.
Other question is how you got ThirdPartyCar object. If you load it by ID from ThirdPartyRepository you can change your abstract factory to:
interface CarFactory {
Car createNew(String id);
}
and given implementation loads by ID ThirdPartyCar and maps it to Car. Everything is hidden by factory which you can easily exchanged.
See also:
Performance of Java Mapping Frameworks
I have been struggling with a task how to tell Orika to map an inherited structure that is flattened to DTO so that it may correctly resolve the implementation on reconstruction of an object. Here is an example of a simple structure with many nested objects:
abstract class Document {
// common values
}
class LegalDocument extends Document {
// complex object with many nested objects
}
class PersonalDocument extends Document {
// complex object with many nested objects
}
And let's say I have a reason to have an object flattened of the structure above:
class FlattenedDocument {
private String documentType = "LEGAL"; // "LEGAL" or "PERSONAL"
// flattened properties of Document and both its subclasses
}
I am able to tell Orika via CustomMapper<Document, FlattenedDocument> to map correctly the property documentType with a correct value based on an actual type (class) of the input document, but what I don't know how to do is the reverse situation. I need to tell Orika that when it converts from FlattenedDocument to one of the implementations of abstract Document, whether it should create the former or the latter by the value of documentType property. I can do that via CustomConverter or ObjectFactory but in both cases I am losing the benefit of byDefault().
Is there any way how to use the standard ClassMap with byDefault() option
factory.classMap(Document.class, FlattenedDocument.class).byDefault().register();
but with the possibility to tell Orika that it should re-instantiate the object based on the value of documentType field?
Thanks.
You can create a CustomConverter, that decides the type based on your field:
public class ShapeReverseConverter extends CustomConverter<ShapeDTO, Shape> {
#Override
public Shape convert(ShapeDTO source, Type<? extends Shape> destinationType, MappingContext mappingContext) {
if (Circle.class.getSimpleName().equals(source.type)) {
return mapperFacade.map(source, Circle.class);
} else {
return mapperFacade.map(source, Rectangle.class);
}
}
}
In Config you can map setting the type:
DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Shape.class, ShapeDTO.class).byDefault()
.field("class.simpleName", "type")
.register();
mapperFactory.getConverterFactory().registerConverter(new ShapeReverseConverter());
I am trying to map following domain model using union-subclass strategy and FluentNHibernate. Here is how my classes look (with unneeded parts removed)
public class Benefit
{
}
public class Leave : Benefit
{
}
public class SeasonTicketLoan : Benefit
{
}
And here is my mapping code
public class BenefitMappings : ClassMap<Benefit>
{
public BenefitMappings()
{
UseUnionSubclassForInheritanceMapping();
}
}
public class LeaveMappings : SubclassMap<Leave>
{
}
public class SeasonTicketLoanMappings : SubclassMap<SeasonTicketLoan>
{
}
When I generate a database script using SchemaExport for the above mapping, I get a table for Leave and another one for SeasonTicketLoan but none for Benefit. Am I missing anything here?
...Am I missing anything here?
Yes, you are using mapping Table Per Concrete Class (TPC), Which is intended to create
separate table per each class and
NO table for parent.
To get really deep and clear understanding, you should read this comprehensive article:
Inheritance mapping strategies in Fluent Nhibernate
Where you can read:
Table Per Concrete Class (TPC)
In TPC inheritance, every class in an inheritance hierarchy will have its own table. The inheritance hierarchy masks the fact that there are several independent underlying tables representing each subtype.
code snippet extract:
// mapping of the TPCBaseEntity base class
public class TPCBaseEntityMap : ClassMap<TPCBaseEntity>
{
public TPCBaseEntityMap()
{
// indicates that this class is the base
// one for the TPC inheritance strategy and that
// the values of its properties should
// be united with the values of derived classes
UseUnionSubclassForInheritanceMapping();
In case, we would like to have also table per base class(es), we need:
Table Per Type(TPT)
TPT is an inheritance described in the database with separate tables. Every table provides additional details that describe a new type based on another table which is that table’s parent.
again some mapping snippet extract:
// mapping of the TPTAnimal base class
public class TPTAnimalMap : ClassMap<TPTAnimal>
{
public TPTAnimalMap()
{
// the name of the schema that stores the table corresponding to the type
Schema("dbo");
// the name of the table corresponding to the type
Table("TPT_Animal");
...
// mapping of the TPTHorse class
public class TPTHorseMap : SubclassMap<TPTHorse>
{
public TPTHorseMap()
{
// the name of the schema that stores the table corresponding to the type
Schema("dbo");
// the name of the table corresponding to the type
Table("TPT_Horse");
I wanted to know if there is a known pattern or convention for the following scenario:
I have two classes: MAT (name:String, address:String) & MATversion(type:String, version:int)
Now I have a DataGrid (DataTable) which will take a generic List of objects for the column mapping and data filling.
The columns should be name, type, version. (Which are distributed in MAT and MATversion)
So I create a class to make this work. This class will merge the needed properties from each class (MAT, MATversion).
-> MAT_MATversion (name:String, type:String, version:int).
Does there exist a naming convention for such an class like MAT_MATversion? Any pattern that mirrors that?
Thanks!
Is there any specific reason why the merged result has to be a unique class?
I'm assuming every MAT object has a single MATversion
you can add a couple of custom properties who will return the type and version of the underlying MATversion object
In C# this would result in something like this
public class MAT{
public String name{ get;set;};
public String adress{ get;set;};
public MATversion myVersion;
public String type {
get{
return myVersion.type;
}
set{
myVersion.type = value;
}
}
public int version {
get{
return myVersion.version;
}
set{
myVersion.version = value;
}
}
}
I'm aware that this doesn't answer the question about design patterns, but I couldn't ask/suggest another approach in a comment since I don't have that right yet.
I have at least two different classes like following :
//NOTE : these two classes have getter and setter also
class Artist {
String artistName;
String artistWebsite;
String artistDbpedia;
String artistImage;
List<String> astistAlbumsName;
List<String> astistAlbumsUrl;
}
class Venu {
String VenuName;
String VenuWebsite;
String VenuDbpdia;
String VenuImage;
String VenuDescription;
List<String> venuFans;
}
I want to have a producer class to get an xml file as an input and detect the type of xml (venu/artist) then start to create a product object based on the input.
the problem :
I want to create an interface for aggregate the similarity between above two classes so my interface would be:
interface Model {
public String getImage();
public String getName();
public String getWebsite();
public String getdbpedia();
}
Then I can implement this interface in my builder class and above two classes but how about those different methods?
such as getVenuFans / getArtistAlbumName / etc....?
How can I call them from my producer?
this is my builder :
Class Builder implements Model {
public String getImage(){}
public String getName(){}
public String getWebsite(){}
public String getdbpedia(){}
}
and this can be my producer :
Class Producer {
public Producer()
{
Builder b = null;
//assume Venu and Artist implements Model
b = (Builder) new Venu();
//I don't have access to getVenuFans()!
b = (Builder) new Artist();
//I don't have access to getArtistAlbumsName() / etc...
}
}
You don't have access to those methods because you're casting the objects to a Builder, and Builder doesn't have those methods.
I see what you're trying to do, but I don't think it will work. For example, getVenueFans (I'm assuming you mean venue) is only appropriate for the Venue class. It doesn't make sense to try and abstract that into an interface that other non-Venue classes will implement.
I think what you have is good: You've abstracted the common methods into an interface. To call the methods on Venue and Artist, the consuming code will need to cast the objects to the appropriate type, then call the methods on it. And that's not as bad as you might think. It's the consuming code that knows what type it's dealing with (otherwise, why would it be trying to call getVenueFans?), so that's the point where it makes sense to cast and call the method directly.