I am currently working on a train simulation project for uni.
This is my class hierarchy:
RollingStock
Coach
FreightCoach
PassengerCoach
SpecialCoach
Engine
DieselEngine
ElectricEngine
SteamEngine
Trainset
My questions:
Every coach has a unique ID. However, Engines and Trainsets share their ID-Space ("series-name"). "Name" is inherited by RollingStock and both Trainset and Engine have the attribute "series".
I've created a class "SharedIdSpace" to implement this feature. But I am not quite sure how to solve this nicely (TreeMap, ..., ?).
Now, my main problem is I have to implement the following feature:
"Rolling stock can be composed into a train. The following restrictions must be observed when composing:
There must always be at least one locomotive/train set at the beginning or end of a valid train.
When composing, it must always be considered whether the rolling stock has a suitable coupling at the desired composition point.
The rolling stock that is being composed has not yet been used in another train.
[...]"
How can I implement this? I'm afraid I have no useful idea.
Im not sure about what are you asking, but I will try to give you my aproximation:
You need to create a composite object where every object has an unique ID and need to pass some validations.
I would implement an "StoregeManager" a "ComposerManager" and add an abstract validator method in "RollingStock" that validate if the vagon can be added.
The flow would be something like this:
DISCLAIMER This is written in Java, but with notepad++, please dont check the sintaxis.
RollingStock freightCoach = StoregeManager.getFreightCoach();
RollingStock specialCoach = StoregeManager.getSpecialCoach();
RollingStock dieselEngine = StoregeManager.getDieselEngine();
// Check if they are null or throw an exception if has no more elements. Maybe from BBDD or from where you want
Composer.compone()
.add(dieselEngine)
.add(freightCoach)
.add(specialCoach)
.build()
And inside the componer, something like this:
public class Composer {
private StoregeManager storeManager; //Injected or initialized, as you want.
private static Train train;
public Composer build(){
train = new Train;
return this;
}
public Composer add(RollingStock rs) {
if(rs.isValid(train))
train.add(rs);
return this;
}
public RollingStock[] build() {
storageManager.ckeckTrain(train);
return train;
}
}
You can put the storage inside the Composer and pass as argument the classname of the vagon if you need another aproximation to your problem.
I hope this helps you.
Related
I'm very new to programming language. My question might not even make sense. My environment is using java and trying to implement both ios and android apps in the same automation testing framework.
So, the idea is that any test script should be able to run on both the apps. Ex: one signin test script should be run for both ios and android.
I've decided to use interface and class implementation approach. The problem I'm facing is with test data. My company doesn't want to use excel. They want to use json for test data.
Here's my problem, look at the following line of code:
ValidBuy goodBuy = JsonFileReader.loadDaTa(TestBase.DATA_PATH, "good-buy.json", ValidBuy.class);
As you can see I have a class "ValidBuy" that has all the getters for a particular json file. I have another class "JsonFileReader" which takes the json filePath, fileName, and a class as an input and returns the data for that class name that I passed in. For this example I've passed ValidBuy.class
So, when I run a positive test, I'm passing "goodBuy" variable which is of type "ValidBuy". The problem starts here.
The test case is now specified with the data from goodBuy because it's type is "ValidBuy" and I'm passing goodBuy as a parameter.
Look at one of my extracted methods:
private void enterBuyInfo(ValidBuy goodBuy) {
itemPage = nativeApp.getItemPage(goodBuy);
itemPage.setItemName(goodBuy.getItemName());
itemPage.setItemSize(goodBuy.getItemSize());
itemPage.setItemDigitSSN(goodBuy.getSsn());
itemPage.clickContinue();
}
You can see those getters I'm using are coming from ValidBuy class.
If I run this test with the data for a badBuy:
InvalidBuy badBuy = JsonFileReader.loadDaTa(TestBase.DATA_PATH, "bad-buy.json", InvalidBuy.class);
It fails because now I have to change "ValidBuy" class with "InvalidBuy" class. Since, changing the parameter in the extracted method in every run is not possible, how can I make it more generic?
I want something like this:
TestData data = JsonFileReader.loadDaTa(RESOURCES_PATH, "good-client.json", InvalidBuy.class);
Here, TestData is generic. It could either be a class or interface (I don't know if that's possible) and the return type will be specified by whichever class I pass into the loadData() method. In this case InvalidBuy.class
The extracted method should look like this:
private void enterBuyInfo(TestData data) {
itemPage = nativeApp.getItemPage(data);
itemPage.setItemName(data.getItemName());
itemPage.setItemSize(data.getItemSize());
itemPage.setItemDigitSSN(data.getSsn());
itemPage.clickContinue();
}
If I can do this, I can use those extracted methods to create more tests.
I know I wrote a lot. I've only tried to make it as clear as possible. If it doesn't make any sense, just disregard it.
Any suggestions, ideas, code samples will be highly appreciated.
Firstly let me see if I understand your question. I think you are saying that loadData may return a value of type ValidBuy or InvalidBuy and you want to pass into it the class that you want returned. You then want to know how to use an interface that might represent either of these classes in your test methods so you can test various return values (both valid and invalid). You use the term "generic" in your question but I'm guessing you don't mean to use it in the specific way it's used in Java.
If I've understood your question correctly, then here's an answer:
Passing the class you wish to have returned into a method is an unusual usage and almost certainly not ideal. Better OOD would be to extract the common methods for all objects returned from loadData into an interface.
So:
interface Buy {
String getItemName();
boolean isValid();
}
class ValidBuy implements Buy {
#Override
public boolean isValid() {
return true;
}
...
}
class InvalidBuy implements Buy {
#Override
public boolean isValid() {
return false;
}
...
}
class JsonFileReader {
Buy loadData(Path path) {
...
}
}
Then your tests can look like:
#Test
void testValidBuy() {
assertTrue(reader.loadData(validPath).isvalid());
}
#Test
void testInvalidBuy() {
assertFalse(reader.loadData(invalidPath).isValid());
}
I realise I've simplified it a bit but hopefully you get the idea.
I am not sure yet if I'm on the wrong track or not. There is an example on the Micronaut Getting Started page for a V8 Engine and injecting a Vehicle.
Defining Beans (often used Engine interface example)
With that example in mind. What is the most straightforward way to implement "Model A" with Micronaut using Java? If there's no direct approach, what is the closest hands-off method with Micronaut?
My simple vision of vanilla field injection stepping-on with such an example is as so (using Java), I'm labelling it "Model A" ...
Model A
import io.micronaut.context.*
public class MyApp { // (A)
#Inject
Vehicle vehicle;
public void runApp( String... args ){
println( vehicle.start() )
}
public static main( String... args ){
// whatever set-up and steps need // (B)
// for auto-inject / auto-wiring.
MyApp body = new MyApp( args );
body.runApp(); // (C)
}
}
Where the annotation processor uses provides an instance of the #Singleton Vehicle in this example. Or creates a new instance in the case of non-singleton-s.
Either way the result of the process would be that I don't need to write code to 'instantiate' the code or find a factory to do so explicitly.
The example itself goes on to demonstrate the method I'll label "Model B" (using Groovy)...
Model B
import io.micronaut.context.*
...
Vehicle vehicle = BeanContext.run().getBean(Vehicle)
println( vehicle.start() )
Which in fact is MORE typing than just writing:
Vehicle vehicle = new Vehicle();
// OR
Vehicle vehicle = Vehicle.getInstance();
With some libraries you need to initialise the scopes or context, I see that. The question boils donw to what must I do to inject Vehicle as shown in my code.
I made a #Singleton and tried to #Inject the field. The reference is NULL. I then made a #Providerand set a break point. That isn't called.
can I do "Model A"?
If yes, what needs to happen?
I've scanned lots of examples doing great things. I'd love to get into those fancy things too. Right now I'm in the basement looking for a way up to the ground floor. Many thanks for you guidance.
I am creating Client API in Java using :+ Apache Jena FrameWork+ Hydra(for Hypermedia driven) + my private vocab similar to Markus Lanther Event-API Vocab instead of schema.org(for Ontology/Vocabulary part)
Section 1 :
After looking this Markus Lanther EventDemo repo and hydra-java.I found that they are creating classes for each hydra:Class that can break client in future .For example :
A Person class (Person.java)
public class Person
{
String name;
};
But in future requirement name is also a class eg:
public class Name
{
String firstName;
String LastName;
};
So to fulfill this requirement I have to update Person class like this:
public class Person
{
Name name;
};
Question 1:
Is my understanding correct or not of this Section? If yes then what is the way to deal with this part ?
Section 2:
To avoid above problem I created a GenericResource class(GenericResource.java)
public class GenericResource
{
private Model model;
public void addProperty(String propertyName,Object propertyValue)
{
propertyName = "myvocab:"+propertyName;
//Because he will pass propertyName only eg: "name" and I will map it to "myvocab:name"
//Some logic to add propertyName and propertyValue to model
}
public GenericResource retriveProperty(String propertyName)
{
propertyName = "myvocab:"+propertyName;
//Some logic to query and retrieve propertyName data from this Object add it to new GenericResource Object and return
}
public GenericResouce performAction(String actionName,String postData)
{
//Some logic to make http call give response in return
}
}
But again I stuck in lots of problem :
Problem 1: It is not necessary that every propertyName is mapped to myvocab:propertyName. Some may be mapped to some other vocab eg: hydra:propertyName, schema:propertyName, rdfs:propertyName, newVocab:propertyName, etc.
Problem 2: How to validate whether this propertyName belongs to this class ?
Suggestion: Put type field/variable in GenericResource class.And then check supportedProperty in vocab corresponding to that class.To more clarity assume above Person class which is also defined in vocab and having supportedProperty : [name,age,etc] .So my GenericResource have type "Person" and at time of addProperty or some other operation , I will query through vocab for that property is in supportedProperty list or in supportedOperation list in case of performAction().
Is it correct way ? Any other suggestion will be most welcomed?
Question 1: Is my understanding correct or not of this Section? If yes
then what is the way to deal with this part ?
Yes, that seems to be correct. Just because hydra-java decided to creates classes doesn't mean you have to do the same in your implementation though. I would rather write a mapper and annotate an internal class that can then stay stable (you need to update the mapping instead). Your GenericResource approach also looks good btw.
Problem 1: It is not necessary that every propertyName is mapped to
myvocab:propertyName. Some may be mapped to some other vocab eg:
hydra:propertyName, schema:propertyName, rdfs:propertyName,
newVocab:propertyName, etc.
Why don't you store and access the properties with full URLs, i.e., including the vocab? You can of course implement some convenience methods to simplify the work with your vocab.
Problem 2: How to validate whether this propertyName belongs to this
class
Suggestion: Put type field/variable in GenericResource class
JSON-LD's #type in node objects (not in #value objects) corresponds to rdf:type. So simply add it as every other property.
And then check supportedProperty in vocab corresponding to that class.
Please keep in mind that supportedProperty only tells you which properties are known to be supported. It doesn't tell you which aren't. In other words, it is valid to have properties other than the ones listed as supportedProperty on an object/resource.
Ad Q1:
For the flexibility you want, the client has to be prepared for semantic and structural changes.
In HTML that is possible. The server can change the structure of an html form in the way outlined by you, by having a firstName and lastName field rather than just a name field. The client does not break, rather it adjusts its UI, following the new semantics. The trick is that the UI is generated, not fixed.
A client which tries to unmarshal the incoming message into a fixed representation, such as a Java bean, is out of luck, and I do not think there is any solution how you could deserialize into a Java bean and survive a change like yours.
If you do not try to deserialize, but stick to reading and processing the incoming message into a more flexible representation, then you can achieve the kind of evolvability you're after. The client must be able to handle the flexible representation accordingly. It could generate UIs rather than binding data to fixed markup, which means, it makes no assumptions about the semantics and structure of the data. If the client absolutely has to know what a data element means, then the server cannot change the related semantics, it can only add new items with the new semantics while keeping the old ones around.
If there were a way how a server could hand out a new structure with a code-on-demand adapter for existing clients, then the server would gain a lot of evolvability. But I am not aware of any such solutions yet.
Ad Q2:
If your goal is to read an incoming json-ld response into a Jena Model on the client side, please see https://jena.apache.org/documentation/io/rdf-input.html
Model model = ModelFactory.createDefaultModel() ;
String base = null;
model.read(inputStream, base, "JSON-LD");
Thus your client will not break in the sense that it cannot read the incoming response. I think that is what your GenericResource achieves, too. But you could use Jena directly on the client side. Basically, you would avoid unmarshalling into a fixed type.
Looking through the Play documentation for Java I noticed the following block of code:
public static Result show(Long id) {
Client client = Client.findById(id);
return ok(views.html.Client.show(client));
}
Source: http://www.playframework.com/documentation/2.1.0/JavaRouting
I am having some trouble understanding the second line, my understanding of Java Object creation is a typical constructor looks like the following:
Person john = new Person();
What is the second line doing? Creating a Object called client from Class called Client, also what is Client? It doesn't appear to be a part of the Play Framework, certainly I cannot find anything in JavaDocs.
Thanks
Edit:
I found this to be a good point of reference for the answer (http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html)
Also I think the class Client comes from the following documentation (http://www.playframework.com/documentation/1.1.1/controllers) with Client being just a example model class, the new documentation probably needs updating to clear up this confusion.
Pretty clearly, the class Client has a static function of findById, which takes a Long and returns a Client. Static functions are functions that are defined without any access to object properties, and therefore can be accessed through the class name, rather than having to be accessed through an object. Most likely, the class has a static property containing a collection of all clients in the system by index, and findById grabs an existing Client from that list.
I really have no idea where the class Client is defined, however. I've also made a quick look around for it, and couldn't find it in the obvious places.
There must be a static method called show(Client) on the views.html.Client class that returns some object. That object is passed into an ok(whatever) method, and that ok method returns a Result object.
You're missing some basic knowledge/experience. The sample you gave has nothing to do with routes and in this snippet only first line is important, second is just some hypothetical usage. De facto it could be just...
public static Result show(Long id) {
return ok("You want to display details of client with ID: " + id);
}
Although #BenBarden explained what is that mean correctly , this static method isn't declared anywhere, it's (again) hyphotetical usage of some ORM. For an example the real usage with Ebean's model will be:
Client = Client.find.byId(id);
Of course you can also declare own method in your Client model and name it the same as in the sample, however it will be just only wrapper:
public static Finder<Long, Client> find
= new Finder<>(Long.class, Client.class);
public Client findById(Long id) {
return find.byId(id);
}
Conclusions
You need to examine some samples available with your Play sources to get familiar with some basic syntax, fortunately you'll find it easy.
DO NOT MIX documentation from Play 1.x with Play 2.x they are not compatible!
Say I follow the Single Responsibility Principle and I have the following classes.
public class Extractor {
public Container extract(List<Container> list) {
... some extraction
}
}
public class Converter {
public String convert(Container container) {
... some conversion
}
}
As you can see it's following the principle and all the names of the classes/methods tell what they do. Now I have another class that has a method like this.
public class SomeClass {
private Extractor extractor = new Extractor();
private Converter converter = new Converter();
private Queue queue = new Queue();
public void someMethod(List<Container> list) {
Container tmp = extractor.extract(list);
String result = converter.convert(tmp);
queue.add(result);
}
}
As you can see the "someMethod"-Method does call extract, convert and add. My question is now, how do you call such a class/method? It's not actually extracting, converting or adding but it's calling those?
If you name the method after its responsibility what would that be?
Well since you seem to add to a queue and you don't return anything I'd call it addToQueue. The fact that you convert + extract is implementation detail that I don't think needs to be exposed.
What about processAndQueueMessage?
Also (not related), you shouldn't create (using new) the Extractor and Converter in your SomeClass, you should rather inject them (at construction or in setters), and use interfaces to them. That will make it easier to test, and reduce coupling between implementations.
// Assuming Converter and Extractor are interfaces to the actual implementations
public class SomeClass {
private final Extractor extractor ;
private final Converter converter;
private Queue queue = new Queue();
public SomeClass(Extractor extractor, Converter converter) {
this.converter = converter;
this.extractor = extractor;
}
public void someMethod(List<Container> list) {
Container tmp = extractor.extract(list);
String result = converter.convert(tmp);
queue.add(result);
}
}
And you create it using:
final SomeClass myProcessor = new SomeClass(new MyExtractorImplementation(), new MyConverterImplementation());
(Or use a DI container, like Spring or Pico)
What you do is think about the composite meaning of the sequence of method calls, turn that into a concise verb or verb phrase and use that as the name. If you can't come up with a concise name then you could use a generic / neutral name (like "process") or use something completely bogus (like "sploddify").
If you want the name to be really generic, I'd go with addToQueue() or populateQueue() since getting something into that object seems to be the point of the method.
But really at that level I'd call it by what business logic it's trying to accomplish, in which case the name really depends on what it's being used for.
If you can't come up with a good name, it is an indication that your procedural abstraction is rather arbitrary / artificial, and a possible hint that there might be a better way to do it. Or maybe not.
Sounds like some kind of builder class. You get data in one format, convert it and then create some kind of output format. So how about "SomethingSomethingBuilder"?
I'm assuming someone downvoted me because I forgot to provide a good name for the method. Sorry about that.
So this method adds incrementally data into your builder class. I would call it, "Add", "AddData" or "Push" (I'd probably go with push because that has very similar meaning in many standard classes).
Alternative to "Builder" could potentially be "SomeKindOfCreator". Obviously you would name it based on whatever it is your class is actually creating.