How to change the html of a HTMLPanel - java

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.

Related

I want to make universal method in CLASS for all enums

public class TableContent {
public static String EXCEL_SHEET_NAME = Nit.THEAD.getName();
public static String FILENAME= Nit.FILENAME.getName();
public enum Nit {
FILENAME("Nit-workorder-list"),
THEAD("NIT WORKORDER"),
TENDERSPECNO("TENDER SPECFICATION NO."),
FEE("TENDER FEE"),
SDAMOUNT("SD AMOUNT"),
TYPE("NIT TYPE"),
PRE_BID("PRE BIDDING DATE"),
OPEN_DATE("OPENING DATE"),
STATUS("CONTRACTOR STATUS");
private final String name;
public String getName() {
return name;
}
private Nit(String name) {
this.name = name;
}
public static Nit getNitHeadByName(String name)
{
Nit[] nit=Nit.values();
if(nit==null)
{
return null;
}
for(Nit nitHead:nit)
{
if(nitHead.getName().equals(name))
return nitHead;
}
return null;
}
public enum NitWorkOrder {
}
public enum NitList {
}
My objective is:
I want to export excel sheet from my application, every time I need to hardcode the table headings, which was not good programming practice.
So I use enum to overcome the hardcode problem. Now there are different table heading according to the list, then I enclosed all the required ENUMS in single class.
I used to write getXXXByName() and getXXXByValue() to access the enum, by name or by value.
But he problem is I need to write getXXXByName() and getXXXByValue() everytime inside each enum. I want to write these methods inside the class and outside the enums, and access those methods with the help of class name.
I just want to declare my constants inside enum.
Please kindly suggest me an idea or a way so I can make this method universal which will work for each and every enum. I want to write these methods in such a way so it can be accessed for all enums enclosed in my class. I thought about generics but I have little knowledge.
You can use generics to push functionality up to a parent class by telling the parent class that the type is an enum that implements an interface.
// Use an interface to inform the super class what the enums can do.
public interface Named {
public String getName();
}
// Super class of all Tables.
public static class Table<E extends Enum<E> & Named> {
private final Class<E> itsClass;
private final String sheetName;
private final String fileName;
public Table(Class<E> itsClass) {
this.itsClass = itsClass;
// Walk the enum to get filename and sheet name.
String sheetName = null;
String fileName = null;
for ( E e: itsClass.getEnumConstants() ){
if ( e.name().equals("FILENAME")) {
fileName = e.getName();
}
if ( e.name().equals("THEAD")) {
sheetName = e.getName();
}
}
this.sheetName = sheetName;
this.fileName = fileName;
}
// Use the interface and the enum details to do your stuff.
public E getByName (String name) {
for ( E e: itsClass.getEnumConstants() ){
if ( e.getName().equals(name)) {
return e;
}
}
return null;
}
}
// Extend Table and tell it about your enum using the super constructor.
public static class TableContent extends Table<TableContent.Nit> {
public TableContent() {
super(TableContent.Nit.class);
}
public enum Nit implements Named{
FILENAME("Nit-workorder-list"),
THEAD("NIT WORKORDER"),
TENDERSPECNO("TENDER SPECFICATION NO."),
FEE("TENDER FEE"),
SDAMOUNT("SD AMOUNT"),
TYPE("NIT TYPE"),
PRE_BID("PRE BIDDING DATE"),
OPEN_DATE("OPENING DATE"),
STATUS("CONTRACTOR STATUS");
private final String name;
Nit(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}

Detecting Class of an object implementing an interface

I'm writing a game, as part of this players should be able to click on various GUI items and see further details on a specific area of the GUI. I'm mangaing this through an interface Detailable which is implemented by suitable game obects and sends the appropriate information to the JPanel
There are also containers (all of which implement Detailable) that contain other (Detailable implementing) objects. The goal being it is possible to click on a container and, amongst its stats, see its contents which can then be in turn clicked on to see their stats, etc.
The problem I am having is in writing the addToContents(Detailable d) method of my containers. Each container as an ArrayList<String> of the "type" of container - wardrobe, bookcase, etc. I want to be able to add only certain classes to a given container - so a container with a type of "bookcase" will only accept objects of class Book or Curio for example.
What I currently have is:
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
But this feels like the wrong way of doing it. Is there a better way? Ideally, for sake of easy code, I'd have something like (pseudocode)
Constructor:
private ArrayList<Class> classesAccepted = <list of classes>
addToContents:
if (classesAccepted.contains(d.getClass()){
add the thingie to contents
return true
}
else{
return false;
}
but I can't seem to find a way of adding a list of classes to the constructor - of translating the ArrayList of class names to an ArrayList of references to the actual class.
Containers are currently read from a JSON so comprise two classes:
public class FurnitureType {
private String name;
private List<String> type;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
//plus getters for all the above
}
public class Furniture implements Detailable, ListSelectionListener{
private String name;
private List<String> types;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
private ArrayList<Detailable> contents;
private transient DetailPanel dp = null;
public Furniture (FurnitureType type){
this.name=type.getName();
this.types = type.getType();
this.cost = type.getCost();
this.description = type.getDescription();
this.comfortBonus = type.getComfortBonus();
this.capacity = type.getCapacity();
this.contents = new ArrayList();
}
//appropriate getters
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
#Override
public String toString(){
return description;
}
#Override
public Icon getBigPic() {
return null;
}
#Override
public JComponent getStats() {
Object [] objectContents = contents.toArray();
JList contentList = new JList(objectContents);
contentList.setPreferredSize(new Dimension (400, 300));
contentList.setFixedCellHeight(50);
contentList.addListSelectionListener(this);
contentList.setCellRenderer(new CustomCellRenderer());
//the CustomCellRenderer class simply makes long descriptions into multiline cells
return contentList;
}
#Override
public void addPanel(DetailPanel dp) {
this.dp = dp;
}
#Override
public void valueChanged(ListSelectionEvent lse) {
Detailable d = contents.get(lse.getFirstIndex());
dp.updatePanel(d);
}
You can actually use a Map as shown below:
private static Map<String, List<Class<? extends Detailable>>>
bookcaseContainer = new HashMap<>();
static {
//load the bookcaseContainer Map from properties/database
bookcaseContainer.put("bookcase", list1);
bookcaseContainer.put("wardrobe", list2);
}
if(bookcaseContainer.get("bookcase") != null &&
bookcaseContainer.get("bookcase").contains(d.getClass())) {
//do something here
} else if(bookcaseContainer.get("wardrobe") != null &&
bookcaseContainer.get("wardrobe").contains(d.getClass())) {
//do something here
}
If I understand your question correctly, you are looking for something like this
ArrayList <Class<? extends Detailable>> acceptedClasses = new ArrayList<>();
acceptedClasses.add(Bookcase.class);
acceptedClasses.add(OtherAcceptable.class);
and then do something akin to
boolean test =
acceptedClasses.stream().anyMatch(clazz -> aClass.isInstance(detailableInstance));
to check if the instance is of an acceptable type

Java JAXB unmarshaling Enum

My Enum type ProductType is properly saving to XML but it doesn't want to unmarshal when opening the file.
I made EnumAdapter:
public class EnumAdapter extends XmlAdapter<String, ProductType>
{
#Override
public ProductType unmarshal(String value) throws Exception {
try {
return ProductType.valueOf(value);
}
catch(Exception e) {
throw new JAXBException(e);
}
}
#Override
public String marshal(ProductType value) {
return value.toString();
}
}
My Product class:
public class Product {
private final IntegerProperty ilosc; //quantity
private final StringProperty nazwa; //name
private final ObjectProperty<ProductType> typ; //type
private final BooleanProperty dostepnosc;
public Product()
{
this(null, 0, ProductType.ALKOHOL, true);
}
public Product(String nazwa, int ilosc, ProductType typ, boolean dostepnosc) {
this.nazwa = new SimpleStringProperty(nazwa);
this.ilosc = new SimpleIntegerProperty(ilosc);
this.typ = new SimpleObjectProperty<>(typ);
this.dostepnosc = new SimpleBooleanProperty(dostepnosc);
}
.
.
.
#XmlJavaTypeAdapter(EnumAdapter.class)
public ProductType getTyp() {
return typ.get();
}
After opening the XML in my app enum is always setting to the value from default constructor (which is ALCOHOL, if I change it, enum is setting to whatever it is). I also know that marshalling from EnumAdapter works properly, I can change it to whatever I want. Please help.
I solved it, I was missing proper setting function:
public void setTyp(ProductType type){
this.typ.setValue(type);

Design - Check a condition before executing every method

I have a POJO named Document.java with 100+ member variables. There is a transformation layer, where I get the required data, transform it and store it in the Document class.
In the tranformation layer, I would like to set a member variable only if satisfies a certain criteria (based on available context).
So it would look something like this:
if(shouldGetExecuted1(context.getXXX())){
document.setField1(tranformDataForField1(availableData1));
}
if(shouldGetExecuted2(context.getXXX())){
document.setField2(tranformDataForField2(availableData2));
}
I want to do this for all the 100+ fields. Is there a clean way to do this?
Additional information
I don't want to use Strategy here as it would create too many classes as the no of strategies grow.
Try to use AOP. AspectJ allows you to define pointcuts (for example, some filtered set of methods) and control their execution via advices (before method call, after, around):
#Aspect
class ClassName {
...
#PointCut("call(public void ClassName.*(..))") //includes all void methods of ClassName object
public void myPointCut(){}
#Around("myPointCut()")
public void myLogicMethod(ProceedingJoinPoint thisJoinPoint) {
if(shouldGetExecuted1(context.getXXX())){
thisJoinPoint.proceed()
}
}
}
Here thisJoinPoint.proceed() will execute the body of the intercepted method.
Read docs about how to define pointcuts. In this example the same logic will be applied to all void methods of this class. You can define more accurate pointcuts via special expressions to provide different logic for each.
No, there is no clean way to do it in Java. You can find methods using reflection but there is no way to find variables such as "availableDataN". So you necessarily need to make "availableDataN" a field in order to find it using reflection.
The final code would be something as ugly as the following:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class X {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Method shouldGetExecuted = X.class.getMethod("shouldGetExecuted" + i, String.class);
boolean b = (boolean) shouldGetExecuted.invoke(null, context.getXXX());
if (b) {
Method tranformDataForField = X.class.getMethod("tranformDataForField");
Field data = X.class.getField("availableData" + i);
Object result = tranformDataForField.invoke(null, data.get(null));
Method set = X.class.getMethod("setField" + i, TransformDataType.class);
set.invoke(null, result);
}
}
}
}
You need to adapt to your specific case. For instance, here I am assuming all fields and methods are static. If they are not, then you need to replace null with an instance reference.
If you are consistent in the naming of your methods, reflection could help a lot.
The following code assumes the following:
A Document class with fields like xxx or xxYy (getters/setters would be usually present but are not required for the code to work)
A Transformer class that has
the capability to determine based on context information, if a field should be processed. These methods are named shouldTransformXxx(context).
the capability to transform the content of the field (with input and output of the same type as the corresponding field in Document). These methods are named T transformXxx(T).
A DataProvider class that has methods to provide the untransformed data. these methods are named findXxx()
The code below is pretty optimistic - it will fail, if a shouldTransformXxx for any field misses, or if it returns true, the same applies for the findXxx and transformXxx methods. So you would have to create classes with 100 methods each, which seems non-ideal for me. But on the other hand, having a class with 100 members seems to lead to awkward situations anyway...
So here's the code:
public class Document {
private String name;
private int size;
#Override
public String toString() {
return "Document [name=" + name + ", size=" + size + "]";
}
}
public class Transformer {
public enum ContextType {
NAME, SIZE
}
public boolean shouldTransformName(Set<ContextType> context) {
return context.contains(ContextType.NAME);
}
public boolean shouldTransformSize(Set<ContextType> context) {
return context.contains(ContextType.SIZE);
}
public String transformName(String name) {
return "::" + name;
}
public int transformSize(int size) {
return size + 1;
}
}
public class DataProvider {
private final String name;
private final int size;
public DataProvider(String name, int size) {
this.name = name;
this.size = size;
}
public String findName() {
return name;
}
public int findSize() {
return size;
}
}
public class Main {
private static final String TRANSFORM_METHOD_PREFIX = "transform";
private static final String CHECK_METHOD_PREFIX = "shouldTransform";
private static final String DATAPROVIDER_METHOD_PREFIX = "find";
private final DataProvider dataProvider;
private final Transformer transformer;
public Main(DataProvider dataProvider, Transformer transformer) {
this.dataProvider = dataProvider;
this.transformer = transformer;
}
public Document transformFields(Set<ContextType> context)
throws ReflectiveOperationException {
Document document = new Document();
for (Field field : Document.class.getDeclaredFields()) {
String capitalizedfieldName = capitalize(field.getName());
Class<?> fieldType = field.getType();
if (shouldTransform(context, capitalizedfieldName)) {
Object data = findData(capitalizedfieldName);
Object transformed = transformData(capitalizedfieldName,
fieldType, data);
// in presence of a security manager, a reflective call of the
// setter could be performed
field.setAccessible(true);
field.set(document, transformed);
}
}
return document;
}
private Object transformData(String capitalizedfieldName,
Class<?> fieldType, Object data)
throws ReflectiveOperationException {
String methodName = TRANSFORM_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, fieldType);
return method.invoke(transformer, data);
}
private Object findData(String capitalizedfieldName)
throws ReflectiveOperationException {
String methodName = DATAPROVIDER_METHOD_PREFIX + capitalizedfieldName;
Method method = DataProvider.class.getMethod(methodName);
return method.invoke(dataProvider);
}
private boolean shouldTransform(Set<ContextType> context,
String capitalizedfieldName) throws ReflectiveOperationException {
String methodName = CHECK_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, Set.class);
return (Boolean) method.invoke(transformer, context);
}
private String capitalize(String fieldName) {
char upperCaseFirstChar = Character.toUpperCase(fieldName.charAt(0));
if (fieldName.length() > 1) {
return upperCaseFirstChar + fieldName.substring(1);
} else {
return Character.toString(upperCaseFirstChar);
}
}
public static void main(String[] args) throws ReflectiveOperationException {
DataProvider dataProvider = new DataProvider("sample", 1);
Set<ContextType> context = EnumSet.of(ContextType.NAME,
ContextType.SIZE);
Main main = new Main(dataProvider, new Transformer());
Document document = main.transformFields(context);
System.out.println(document);
}
}

Suggestions how to re-write the following Java code snippet

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);
}

Categories

Resources