I was trying to convert this code into a more elegant or efficient way to code it.
final ContentSlotForPageModel rel = modelService.create(ContentSlotForPageModel.class);
rel.setUid("rel_1");
rel.setPosition("no");
rel.setCatalogVersion(catalogVersionModel);
rel.setPage(firstContentPage);
rel.setContentSlot(slot);
modelService.save(rel);
final ContentSlotForTemplateModel relTemplate = modelService.create(ContentSlotForTemplateModel.class);
relTemplate.setUid("relTemplate_1");
relTemplate.setPosition("no");
relTemplate.setCatalogVersion(catalogVersionModel);
relTemplate.setPageTemplate(template);
relTemplate.setContentSlot(slot);
modelService.save(rel);
Where ContentSlotForPageModel and ContentSlotForTemplateModel are subtypes of CMSRelationModel. So I tried to create a method that sets these attributes by using its supertype like this:
private void setRelationModel(final CMSRelationModel rel, final ContentSlotModel slot, final String id)
{
rel.setUid(id);
rel.setCatalogVersion(catalogVersionModel);
if (rel instanceof ContentSlotForPageModel)
{
((ContentSlotForPageModel) rel).setPage(firstContentPage);
((ContentSlotForPageModel) rel).setContentSlot(slot);
((ContentSlotForPageModel) rel).setPosition("no");
}
else if (rel instanceof ContentSlotForTemplateModel)
{
((ContentSlotForTemplateModel) rel).setPageTemplate(template);
((ContentSlotForTemplateModel) rel).setContentSlot(slot);
((ContentSlotForTemplateModel) rel).setPosition("no");
}
modelService.save(rel);
}
However, many methods are not defined on CMSRelationModel and therefore I need to create a validation to make the right call. I cant define this methods on its superclass. Is there a nicer way to write this?
Thank you
Do the following.
No instanceof, strongly typed, minimisation of duplicated code.
private void setRelationModel(ContentSlotForPageModel rel, ContentSlotModel slot, String id) {
rel.setPage(firstContentPage);
rel.setContentSlot(slot);
rel.setPosition("no");
setCMSRelationModel(rel);
}
private void setRelationModel(ContentSlotForTemplateModel rel, ContentSlotModel slot, String id) {
rel.setPageTemplate(template);
rel.setContentSlot(slot);
rel.setPosition("no");
setCMSRelationModel(rel);
}
private void setCMSRelationModel(CMSRelationModel rel, String id) {
rel.setUid(id);
rel.setCatalogVersion(catalogVersionModel);
modelService.save(rel);
}
I also removed final from the parameters to reduce "code noise".
Could you create a new superclass in between them?
public abstract class SuperContentSlotModel extends CMSRelationModel{
private String position;
private ContentSlotModel slot;
//...
}
class ContentSlotForPageModel extends SuperContentSlotModel{
private int page;
//...
}
Also, you could use method overloading instead of instanceof:
private void setRelationModel(final ContentSlotForPageModel rel, final ContentSlotModel slot, final String id){
//...
}
private void setRelationModel(final ContentSlotForTemplateModel rel, final ContentSlotModel slot, final String id){
//...
}
Could you please try this..
First of all, you populate the fields which are inherited from CMSRelationModel, then populate the fields based on your child classes such as using instanceof operator.
Here is sample
private void setRelationModel(final CMSRelationModel rel, final ContentSlotModel slot, final String id)
{
rel.setUid(id);
rel.setCatalogVersion(catalogVersionModel);
rel.setContentSlot(slot); // assume this is inherited method from CMSRelationModel
rel.setPosition("no"); // assume this is inherited method from CMSRelationModel
if (rel instanceof ContentSlotForPageModel)
{
((ContentSlotForPageModel) rel).setPage(firstContentPage);
}
else if (rel instanceof ContentSlotForTemplateModel)
{
((ContentSlotForTemplateModel) rel).setPageTemplate(template);
}
modelService.save(rel);
}
Related
I have this class and need to know which constructor is needed to create an object that may immediately use all its methods without error
public class Robot {
private boolean fuelEmpty = true;
private int roboID;
private String greeting;
private String securityProtocol;
//insert robot constructor here
public void destroyAllHumans(){
while (fuelEmpty == false) {
//robot begins to destroy all humans
}
}
public int getRoboID(){
return roboID;
}
public void greet(){
System.out.println(greeting);
}
public void setSecurityProtocol(String proto){
securityProtocol = proto;
}
}
For example should look like this:
public Robot(int id, String greet) {
roboID = id;
greeting = greet;
}
or this:
public Robot(int id, String greet) {
roboID = id;
greeting = greet;
fuelEmpty = false;
}
or:
public Robot(boolean full, int id, String greet, String proto) {
roboID = id;
greeting = greet;
fuelEmpty = full;
securityProtocol = proto;
}
Which of these (or something else different) is needed so that all the other methods can run without an error?
You can overload the constructor as much as you need, the important thing is
the object gets properly instantiated after you create a new one...
a way can be:
public Robot() {
this(false, 0, "", "");
}
public Robot(int id) {
this(false, id, "", "");
}
public Robot(boolean fuelEmpty, int roboID, String greeting, String securityProtocol) {
this.fuelEmpty = fuelEmpty;
this.roboID = roboID;
this.greeting = greeting;
this.securityProtocol = securityProtocol;
}
so look how all other constructors will at the end call internally the
public Robot(boolean fuelEmpty, int roboID, String greeting, String securityProtocol)
that will give you the waranty that no matter which constructor is invoked, the Robot is fully created and can invoke all those methods without crashing
The solution works like this:
you look at each of your methods
you check which fields each method is using
you check more closely, if the method breaks when that field has its default value (like null for Objects, or false for booleans)
When you do that for all methods, you get a list of those fields that you need to initialize somehow. Then you could go forward and define a corresponding constructor.
But of course, that is the wrong approach.
The real answer goes like this: you don't put fields into a class because you can. You add them because they are required so that this class can implement the requirements (responsibilities) that you want it to implement. Meaning: you focus on the methods that your class should provide. Then you clarify which fields you need in order to implement these methods.
In other words: you have exactly those fields in your class that your class needs. If you have fields in there that go unused - then you get rid of them.
I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}
I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.
CLARIFICATION:
I do not know the objects name. That is where the problem comes in. I am creating an object like such:
`new Object(String attributes);
I am trying to run code in another class such as:
***.getStuff();
the trick to it is, there is no name for the Object. but i do know what String attributes is
The question: Is there any way to accomplish this without using the dreaded for loop?
This question is a bit tricky to word, but I will try my best. What I want to is get an object that matches a particular field without making a messy for loop. Something along the lines of:
Object A has the field String name.
String nameObj = "Tickle";
Object A has the name "Tickle"
if(nameObj.equals(Object A)){
//bla bla
}
Very confusing wording, yes. Sorry about that. I want to use Object A in my code without having to figure out which object it is, assuming all I have is its name. I am looking for a shortcut around using a for loop, I suppose.
Feel free to ask questions about what I am looking for. Sorry about the terribly worded question.
Poor coding, but this is what I am looking for...
nameObj.getName().getObjectA();
If you have a bunch of objects with names, and you want to grab an object by its name, I suggest you look up the class HashMap. HashMap lets you put in objects under keys, and when you give the hash map a key it returns the object associated with that key. So in your example, the keys would be string names.
Take at this implementation, that demonstrates what #Patashu said, create a map to the objects, in this case I just add an abstract class at the top of all.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
Factory.add(new NiceGuy("first one"));
Factory.add(new FirstChild("ok im late"));
System.out.println(Factory.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
}
public String getId(){
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}
class Factory {
private static HashMap allTheObjects = new HashMap();
public static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
This is another version, of the same implementation with a more transparent aproach, without the Factory class, the Parent itself will keep track of the instances and save in a list.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
NiceGuy foo = new NiceGuy("first one");
FirstChild bar = new FirstChild("ok im late");
System.out.println(ParentOfAll.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
add(this);
}
public String getId() {
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
private static HashMap allTheObjects = new HashMap();
private static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}
I want do declare a Subclass of an HTMLPanel.
In its constructor I want to give it a few paramters to construct the containing html.
Because I have to call the super-constructor as first statement, I have to change the html later in the constructor.
How can I do this?
public class MyHTMLPanel extends HTMLPanel
{
public MyHTMLPanel(String id, int anotherParameter)
{ super("");
String html=""
// ... some code th construct the html
//??? this.setHtml(html);
}
}
You can find below an example I used and worked well for me.
I don't remember why I don't sub-class HTMLPanel, whether a good reason or not.
You will notice a mechanism to randomize the html ids in case you include several objects of the same type in a single page.
public abstract class HtmlPanelBase extends Composite
{
private String _dynPostfix = "";
protected final String id(final String staticId) { return staticId + _dynPostfix; }
private final String wrapId(final String id) { return "id=\"" + id + "\""; }
private final String wrapDynId(final String refId) { return wrapId(id(refId)); }
private String _htmlAsText = null;
public String getHtmlAsText() { return _htmlAsText; }
abstract protected String htmlPanelBundleHtmlText();
abstract protected List<String> idList();
protected HTMLPanel _holder = null;
private HTMLPanel createHtmlPanel(final boolean defineGloballyUniqueIds)
{
// Referent HTML panel text containing the reference id's.
_htmlAsText = htmlPanelBundleHtmlText();
if (defineGloballyUniqueIds)
{
// List of id's in the HTML Panel reference page to replace with dynamic/unique id's.
final List<String> refIdList = idList();
// Replace the reference id's with dynamic/unique id's.
for (String refId : refIdList)
_htmlAsText = _htmlAsText.replace(wrapId(refId), wrapDynId(refId));
}
// Return the HTMLPanel containing the globally unique id's.
return new HTMLPanel(_htmlAsText);
}
public HtmlPanelBase(final boolean defineGloballyUniqueIds)
{
setup(defineGloballyUniqueIds);
initWidget(_holder);
}
private void setup(final boolean defineGloballyUniqueIds)
{
if (defineGloballyUniqueIds)
_dynPostfix = "_" + UUID.uuid().replace("-", "_");
_holder = createHtmlPanel(defineGloballyUniqueIds);
}
}
And now how you could sub-class from the above base:
public class HtmlPanelTemplate extends HtmlPanelBase
{
private final static boolean _defineGloballyUniqueIds = false;
private final static int _numIdCapacity = 40;
public HtmlPanelTemplate()
{
super(_defineGloballyUniqueIds);
setup();
}
#Override
protected String htmlPanelBundleHtmlText()
{
return YourClientBundle.INSTANCE.getYourFileHtml().getText();
}
#Override
protected List<String> idList()
{
final List<String> idList = new ArrayList<String>(_numIdCapacity);
return idList;
}
private void setup()
{
}
}
You don't need to subclass HTMLPanel. You can create a simple Composite widget:
public class myPanel extends Composite {
private HTMLPanel panel = new HTMLPanel();
public myPanel(String id, int anotherParameter) {
// set HTML to panel based on your parameters
initWidget(panel);
}
}
htmlPanel.getElement().setInnerHTML(...)
Don't know whether this works in derived class' constructor. But setting up a class for specific content text isn't really a good solution.