I have the following Sample object being created and adding it to a map as follows.
Is there a way I could have added these set values to Sample object without having to create
an object and directly add it to the map?
Note that I can't change Sample class thus can't be adding constructors nor builder pattern in there.
I am using Java 8
The following works where I create the Sample object and assign it to a variable first and then
add it to a map.
Sample SampleHeader = new Sample();
SampleHeader.setOrder(null);
SampleHeader.setHeader(HEADER_DATA);
data.getAllSamples().put("info", SampleHeader);
Looking for something like this (syntatically wrong)
data.getAllSamples().put(
"info", new Sample().setOrder(null).setHeader(HEADER_DATA)
);
You can use a builder, like this, to allow you to create the object via method chaining:
public class SampleBuilder {
private Sample sample = new Sample();
public SampleBuilder setHeader(Object header) {
sample.setHeader(header);
return this;
}
public SampleBuilder setOrder(Object order) {
sample.setOrder(order);
return this;
}
public Sample build() {
Sample built = sample;
sample = new Sample();
return built;
}
// OR this
public static Sample build(Object header, Object order) {
Sample built = new Sample();
built.setHeader(header);
built.setOrder(order);
return built;
}
}
Then you can call:
data.getAllSamples().put(
"info", new SampleBuilder().setOrder(null).setHeader(HEADER_DATA).build()
);
// OR this
data.getAllSamples().put(
"info", new SampleBuilder(null, HEADER_DATA).build()
);
Related
I'm used to see in MVC Pattern view, controller and model separated and now in many How To I can see model implemented in controller and for me this practice doesn't respect MVC Pattern.
In my case, what I want is for example :
a POJO Car :
public class Car
{
private int price;
private int doors;
public Car (int px, int dr)
{
this.price = px;
this.doors = dr;
}
}
And after instanciation in my java programme
Car car = new Car(1000, 4);
Now, how can I to put this object into Angular's model please ?
Thanks in advance.
I usually use the following pattern
angular.module('yourServiceName.car.model', [])
.factory('Car', function() {
function Car(car) {
/* extend with lodash.
* Since this is a POJO, don't transform anything you dont need.
*/
_.assign(this, car, this);
}
Car.Enums = {SOME:1, ENUM:2, YOU:3, MIGHT:4, NEED:5};
Car.prototype.method = function() {
/* some model specific method.
* don't throw REST or UI things here tho.
*/
}
Car.create = {
fromJSON: function(json) {
/* only use this for JSON missing transformations, like
* 'Y'|'N' to true|false
* dateString to Date instance
*/
json.startDate = Date.parse(json.startDate); or something.
// I want to see 'Car' in my debug window, instead of 'Object'
return new Car(json);
}
}
return Car;
});
Then on your API service
angular.module('yourService.car.rest', [
'yourService.car.model'
])
.factory('carApi', function(baseURL, Car) {
var path = baseURL+'/car'
var Routes = {
CREATE : path,
LIST : path+'/%s',
DETAILS: path+'/%d'
};
function getCar(id, params) {
// this should blowup if id is not a number
var url = sprintf(Routes.DETAILS, id);
return $http.get(url, params).then(function(response.data) {
// if now JSON transformations are done
// return new Car(response.data);
return Car.create.fromJSON(response.data);
});
}
function listCars(ids, params) {
ids = ids || [];
var _ids = ids.join(',');
var url = sprintf(Routes.LIST, _ids);
return $http.get(url, params).then(function(response) {
return _.map(response.data, Car.create.fromJSON);
});
}
function createCar(oCar) {
/* Hungarian notation indicates I expect an instance of 'Car'
* And not just any object
*/
$http.post(Routes.CREATE, {data: oCar});
}
return {list:listCars, get:getCar, create:createCar};
});
So finally in your controller, you would have something like
angular.module('yourProject.ui.car.list', [
'yourServiceName.car.model',
'yourServiceName.car.rest'
])
.controller('ListCarsController', function ListCarsCtrlr(carsApi, Car) {
$scope.ids = [1, 2, 3];
$scope.load = function() {
var params = {}; // anything else you need to pass
carsApi.list(ids, params).then(function(cars) {
$scope.cars = cars; // all of these are now instanceof Car
})
}
});
Your controller ends up as simple as this:
You can even take it up a nodge if you need Viewmodel
angular.module('yourProject.ui.car.list.viewmodel', [
'yourService.car.model'
])
.factory('CarItemViewmodel', function CarItemVM() {
function CarItemViewmodel(oCar) {
// do some flattening or something you can unit test
this.price = oCar.additionalAttributes.somethingDeep.price;
this.ammount = oCar.someOtherStuff[0].quantity;
};
return CarItemViewmodel;
});
MVC patter of angularjs means that all layer(M,V,C) are in client side.
In this pattern, Server side normally return simple json file which are requested by ajax wheter you implement your server side code with MVC pattern or not.
Therefore If you prefer to use POJO on your server side code, I suggest to conver POJO to json format and serve it as json file.
In the client angularjs code, you can convert json to javascript simple object and use it as model.
You don't. And you can't.
You can make a web service in Java. You can make Angular to call that web service. But you can't push data from Java into "Angular's model", because that's not how the web works.
override the tostring method of your Car class
public String toString(){
return new JSONObject(this).toString();
}
And you can put that object in json and return it as a json
Car car = new Car(1000, 4);
JSONObject jsonReturn = new JSONObject();
jsonReturn.put("car ", car );
Basically, i have a class where i have my arrays in, which is like this
public final class DepotDatabase {
private Driver[] arrayDrivers;
public DepotDatabase() {
arrayDrivers = new Driver[4];
arrayDrivers[0] = new Driver(1234, 1234, 0); // sample driver
arrayDrivers[1] = new Driver(4444, 4444, 0); // sample driver
arrayDrivers[2] = new Driver(1337, 1337, 1); // sample manager
arrayDrivers[3] = new Driver(1234, 1234, 0); // sample driver
}
and i want to print this array in another class, i did set up the array in another class
public Driver(int username, int password, int managerCheck) {
this.username = username;
this.password = password;
this.managerCheck = managerCheck;
}
but now i want to be able to print out all the drivers, but in another class which will be called ViewDrivers or something similar
You can create a method inside DepotDatabase to print the array, then create an object from and call print method.
public final class DepotDatabase {
private Driver[] arrayDrivers;
public void printArray() {
for (int i = 0; i < arrayDrivers.length; i++) {
Driver d = arrayDrivers[i];
System.out.println("Username : " + d.getUsername());
System.out.println("Password : " + d.getPassword());
System.out.println(" Manager Check: " + d.getManagerCheck());
}
}
the from the test class you can do:
public void execute() {
DepotDatabase ddb = new DepotDatabase();
ddb.printArray();
}
That's why you'll need to have getters and setters. You should have:
public Driver[] getDrivers() {
return arrayDrivers;
}
and in the other class, you simply call it (and print it or whatever).
Read this tutorial.
If you plan to print your array in another class you show create an accessor to it.
The common pattern for Java is to use "get plus name off attribute", getDrivers() you should also avoid the class name in such geter as it may changed due to application life.
public final class DepotDatabase {
//your code
public Driver[] getDrivers() {
return this.arrayDrivers;
}
}
Next question to answer is a returning the whole array is good idea. When you return it as above you loose control on it. And every one that call that method will be able to change the content of it.
To prevent this you should use so called Defensive copying
public Driver[] getDrivers() {
return Arrays.copyOf(arrayDrivers, arrayDrivers.length);
}
Then person will get an copy of it an will not harm your class.
The issue with this is that consumer of your class will have to call this method every time to get fresh list of cars.
To solve this issue you may want to user the [collection framework] where instead of array you cold define:
List<Driver> drivers new ArrayList<>();
and provide the drivers as [immutable] list
public Iterable<Driver> getDrivers() {
return java.util.Collections.unmodifiableList(drivers);
}
Iterable is an interface, that allow you to obtain an interator the the list consumer of class wold have possibility to traverse it. IF you wan to allow him to check that list contains some driver you can set the return type as Collection
class Storage {
private String items[] = new String[10];
public String[] getItems() {
return Arrays.copyOf(items, items.length);
}
}
class Store {
Storage storage = new Storage();
private void printStorage() {
String[] items = storage.getItems();
for (String item : items) {
}
}
}
I created an eclipse-rcp's project's plugin.xml with a new command with a parameter.
ArrayList<parameterization> parameters = new ArrayList<parameterization>();
IParameter iparam;
//get the command from plugin.xml
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
ICommandService cmdService = (ICommandService)window.getService(ICommandService.class);
Command cmd = cmdService.getCommand("org.ipiel.demo.commands.click");
//get the parameter
iparam = cmd.getParameter("org.ipiel.demo.commands.click.paramenter1");
Parameterization params = new Parameterization(iparam, "commandValue");
parameters.add(params);
//build the parameterized command
ParameterizedCommand pc = new ParameterizedCommand(cmd, parameters.toArray(new Parameterization[parameters.size()]));
//execute the command
IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
handlerService.executeCommand(pc, null);
I tried this example to pass parameters and it worked.
The issue in this example that I could pass only parameters of type String. ( because Parameterization )
I want to pass parameter of hash map and in general to pass any object.
I tried this code
IServiceLocator serviceLocator = PlatformUI.getWorkbench();
ICommandService commandService = (ICommandService) serviceLocator.getService(ICommandService.class);
ExecutionEvent executionEvent = new ExecutionEvent(cmd, paramArray, null, null);
cmd.executeWithChecks(executionEvent);
but it didn't work the parameters didn't move ( it was null)
Could you please help to to move object as parameter in command ?
Since it would get confusing to add another solution to my first answer, I'll provide another one for a second solution.
The choices I gave were " A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context."
A) can be used in your Handler if your object is the selection of a Structured Object like a Tree:
MyObject p = (MyObject) ((IStructuredSelection) HandlerUtil.getCurrentSelection(event)).getFirstElement();
B) The usage of a Source provider is a bit more tricky. The main idea is, that you add your object to the application context. The important snippets for Eclipse 3.x from a project that I set up after I read this blog (note: it is in german and the example it provides doesn't work):
In your plugin.xml add:
<extension point="org.eclipse.ui.services">
<sourceProvider
provider="com.voo.example.sourceprovider.PersonSourceProvider">
<variable
name="com.voo.example.sourceprovider.currentPerson"
priorityLevel="activePartId">
</variable>
</sourceProvider>
Set up your own SourceProvider. Calling the "getCurrentState" you can get the variable (your Person object in this case) of that SourceProvider:
public class PersonSourceProvider extends AbstractSourceProvider{
/** This is the variable that is used as reference to the SourceProvider
*/
public static final String PERSON_ID = "com.voo.example.sourceprovider.currentPerson";
private Person currentPerson;
public PersonSourceProvider() {
}
#Override
public void dispose() {
currentPerson = null;
}
**/**
* Used to get the Status of the source from the framework
*/
#Override
public Map<String, Person> getCurrentState() {
Map<String, Person> personMap = new HashMap<String, Person>();
personMap.put(PERSON_ID, currentPerson);
return personMap;
}**
#Override
public String[] getProvidedSourceNames() {
return new String[]{PERSON_ID};
}
public void personChanged(Person p){
if (this.currentPerson != null && this.currentPerson.equals(p)){
return;
}
this.currentPerson = p;
fireSourceChanged(ISources.ACTIVE_PART_ID, PERSON_ID, this.currentPerson);
}
}
In your View you register to the SourceProvider and set the Object to the object you want to transfer to your Handler.
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent);
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setContentProvider(new ViewContentProvider());
viewer.setInput(rootPerson);
getSite().setSelectionProvider(viewer);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(SelectionChangedEvent event) {
Person p = null;
if (event.getSelection() instanceof TreeSelection) {
TreeSelection selection = (TreeSelection) event.getSelection();
if (selection.getFirstElement() instanceof Person) {
p = (Person) selection.getFirstElement();
}
}
if (p==null) {
return;
}
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
ISourceProviderService service = (ISourceProviderService) window.getService(ISourceProviderService.class);
PersonSourceProvider sourceProvider = (PersonSourceProvider) service.getSourceProvider(PersonSourceProvider.PERSON_ID);
sourceProvider.personChanged(p);
}
});
}
And in your Handler you can just call the PersonSourceProvider#getCurrentState to get your Objects back.
Advantage of this method is, that you can use the Objectd anywhere you want. E.g. you can even set up a PropertyTester to enable/disable UI elements according to the currently selected Object.
The Parameterized Command does only accept Strings.
Here is an example for smaller objects:
Disclaimer: this is for Eclipse 3.x. I am not using Eclipse 4.x a lot, so you might have to adapt there in case you need it.
Create a Pluginproject (com.voo.example.commandparameter.advanced) with a View (com.voo.example.commandparameter.advanced.view) , a Command (com.voo.example.commandparameter.advanced.sysoCommand) with menu entry and Handler(com.voo.example.commandparameter.advanced.sysoCommand), and a universal Object (MyTestObject).
The Command needs a Parameter and a Parametertype in the plugin.xml, that gets passed to it:
<extension
point="org.eclipse.ui.commands">
<command
id="com.voo.example.commandparameter.advanced.sysoCommand"
name="SysoCommand">
<commandParameter
id="myObject"
name="object"
optional="true"
typeId="com.voo.example.commandparameter.advanced.testType">
</commandParameter>
</command>
<commandParameterType
id="com.voo.example.commandparameter.advanced.testType"
type="com.voo.example.commandparameter.advanced.MyTestObject">
</commandParameterType>
In the Object you set atrtibutes like name and street and define a convertToString method like that:
public String convertToString() {
return getName() +",,,"+ getStreet();
}
(you can override the toString method, too. I just used that method to set weired delimiters to the returned String)
And in a Class MyParamterConverter you can transfer it back:
public class MyParameterConverter extends AbstractParameterValueConverter {
public MyParameterConverter() {
}
#Override
public String convertToString(Object parameterValue)
throws ParameterValueConversionException {
return parameterValue.toString();
}
/**
* This will always create a new object. Just keep that in mind
* if you're trying to work with the objects.
*/
#Override
public Object convertToObject(String parameterValue)
throws ParameterValueConversionException {
//Split the String to get the attributes back
String delimiter =",,,";
String[] split = parameterValue.split(delimiter);
String name = split[0];
String street = split [1];
return new MyTestObject(name, street);
}
}
Now you can call the command with a buttonclick in your view, for example:
btnGo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
MyTestObject testObject = new MyTestObject(textName.getText(),textStreet.getText());
ICommandService cS = (ICommandService)getSite().getService(ICommandService.class);
IHandlerService hS = (IHandlerService)getSite().getService(IHandlerService.class);
Command sysoComm = cS.getCommand("com.voo.example.commandparameter.advanced.sysoCommand");
HashMap<String, String> params = new HashMap<String, String>();
params.put("myObject", testObject.convertToString());
ParameterizedCommand pC = ParameterizedCommand.generateCommand(sysoComm, params);
try {
hS.executeCommand(pC, null);
} catch (Exception e) {
e.printStackTrace();
}
}
});
And the Handler can transform the passed parameters back :
public class MyObjectHandler extends AbstractHandler {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
String param1 = event.getParameter("myObject");
MyParameterConverter converter = new MyParameterConverter();
Object convertToObject = null;
try {
convertToObject = converter.convertToObject(param1);
} catch (ParameterValueConversionException e) {
e.printStackTrace();
}
if (convertToObject instanceof MyTestObject) {
MyTestObject to = (MyTestObject) convertToObject;
System.out.println(to.toString());
}
return null;
}
}
This should work for most smaller sized objects that do not change while you pass them. If you need to pass bigger objects, you will have two choices: A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context.
For a long time I have been focused on delivering an object via a command parameter. But in the end, the easiest workaround is to simply ignore the parameter stuff and put the desired object in a new child IExclipseContext and execute the command with that context. That way your handler gets your object injected.
Caller:
ECommandService commandService = // get commandService...
EHandlerService handlerService = // get handlerService...
IEclipseContext context = // get active or application context...
IEclipseContext childCtx = context.createChild();
childCtx.set(MyObject.class, instancOfMyObject);
ParameterizedCommand command = commandService.createCommand("my.command.id", null);
handlerService.executeHandler(command, childCtx);
In your handler:
#Execute
public void execute(#Optional MyObject myObject) {
if(myObject != null) {
// work with your object
}
}
Voila, no converters or callbacks (i.e. SelectionService) needed...
I am not really familiar with this as passing parameters to commands is quite rare. It looks like you have to use commandParameterType in the org.eclipse.ui.commands command definition to define code based on AbstractParameterValueConverter to convert between objects and the string for the parameter value.
I'm trying to create two objects of a Silo class in a SiloManager class, so that I can access both objects' methods. But I can't seem to make the SiloManager constructor work, nor to instance the classes properly. (I'm a beginner in java). Here's my code:
public class GrainSiloManager {
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
private void showStatus() {
System.out.println("The current grain in silo1 is: " + silo1.getGrain());
System.out.println("The current grain in silo2 is: " + silo2.getGrain());
}
}
As I say i'm a beginnger so go easy heh, thanks for any help.
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
This will get compiled as:
public GrainSilo silo1;
public GrainSilo silo2;
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = new GrainSilo(100);
this.silo2 = new GrainSilo(50);
this.silo1 = silo1;
this.silo2 = silo2;
}
which as you can see makes little to no sense. You're overwriting the object that you make, with the objects passed into the constructor.
Your constructor is going to replace the "public!" silo1 and silo2 objects with whatever is passed in. You could change your constructor like this
public GrainSiloManager() {
super();
}
or the even shorter (but equivalent)
public GrainSiloManager() {
}
And then call it like this
new GrainSiloManager().showStatus();
or you can use your existing approach (which will replace the GrainSoloManager.silo1 and GrainSoloManager.silo2 in your constructor)
GrainSilo silo1 = new GrainSilo(100);
GrainSilo silo2 = new GrainSilo(50);
new GrainSiloManager(silo1, silo2).showStatus();
I'm Using Flex + java .. in that i have two Sub mxml files Sub1.mxml and Sub2.mxml
Sub1.mxml code..
[Bindable] private var editTimetableVO:TimetableVO;
public function forwardToCreateEvent(event:MouseEvent):void
{
editTimetableVO = new TimetableVO();
editTimetableVO=editDataGrid.selectedItem as TimetableVO;//editDataGrid is DataGrid id
Alert.show("value "+editTimetableVO.startDate);
}
Hear Alert is Print some date it is good... then my Second Mxml file..
Sub2.mxml code..
public var myEditEvent:Sub1 = new Sub1();
private var timetableVO:TimetableVO = new TimetableVO();
// private var editTimetableVO:TimetableVO = new TimetableVO();
protected function init(event:FlexEvent):void
{
Alert.show("Show");
timetableVO=myEditEvent.editDataGrid.selectedItem as TimetableVO;
Alert.show("value "+timetableVO.startDate);
}
But in that time Alert not Printing ....
Is their any other way to access to editTimetableVO in Sub1.mxml to Sub2.mxml file...
Try to create a modelLocator (singleton class and put reference of "editTimetableVO" in that file). This way only a single instance of "editTimetableVO" variable exist in whole application lifecycle, as you have declared this variable as Bindable so changes happen anywhere in application will reflect instantly.
package
{
public class ModelLocator{
public static var instance:ModelLocator;
public var editTimetableVO:*;
public function ModelLocator(instance:SingletonEnforcer){}
public static function getInstance():ModelLocator{
if(!instance){
instance = new ModelLocator(new SingletonEnforcer());
}
return instance;
}
}
}class SingletonEnforcer{}
// sub1.mxml
[Bindable]private var model:ModelLocator = ModelLocator.getInstance();
public function forwardToCreateEvent(event:MouseEvent):void
{
model.editTimetableVO = new TimetableVO();
model.editTimetableVO=editDataGrid.selectedItem as TimetableVO;//editDataGrid is DataGrid id
Alert.show("value "+model.editTimetableVO.startDate);
}
// Sub2.mxml
[Bindable]private var model:ModelLocator = ModelLocator.getInstance();
protected function init(event:FlexEvent):void
{
Alert.show("Show");
model.timetableVO=myEditEvent.editDataGrid.selectedItem as TimetableVO;
Alert.show("value "+model.timetableVO.startDate);
}