I have a problem in getting checkbox's value from JSP.
I used SpringMVC, and my related class as follows:
Form:
#Getter #Setter
public class Sample3Form extends AbstractForm {<
private List<Sample1Bean> sampleList; //all data
private ValidPagedListHolder<Sample1Bean> samplePagedList;//1 page data
}
the class to control changing page:
ValidPagedListHolder:
#SuppressWarnings("serial")
public class ValidPagedListHolder<E> extends PagedListHolder<E> implements
Serializable {
...
...
/**
* Return a sub-list representing the current page.
*/
#Override
#Valid
public List<E> getPageList() {
return super.getPageList();
}
/**
* コンストラクタ生成時の初期化処理を行うメソッド
*/
protected void init() {
setPageSize(DEFAULT_PAGE_SIZE);
}
}
Sample1Bean:
#Getter #Setter
public class Sample1Bean extends AbstractOnlineDataBean {
private String keiyakuno;
private String keiyakunm;
private String torisakino;
}
Parent Bean Class:
#Getter
#Setter
public abstract class AbstractOnlineDataBean extends AbstractDataBean {
private Integer selectedIndex;
private String maskPattern;
}
Controller:
#Controller
#RequestMapping(value = "app/sample3")
#SessionAttributes(value = "sample3Form")
#NotCheckToken
public class SampleController3 extends AbstractController {
private static Logger logger = LoggerFactory.getLogger(UserUtil.class);
#ModelAttribute(value = "sample3Form")
public Sample3Form getForm() {
return new Sample3Form();
}
......
......
#RequestMapping(value = "delete")
public String delete(Model model, #Validated Sample3Form form, BindingResult result, HttpServletRequest request) throws GdcSystemException {
List<Sample1Bean> list = new ArrayList<Sample1Bean>();
int size = form.getSampleList().size();
ValidPagedListHolder<Sample1Bean> plist = form.getSamplePagedList();
list = plist.getPageList();
for (int i = 0 ; i < size; i ++) {
if (form.getSampleList().get(i).getSelectedIndex() == null ) {
} else {
//I cannot arrive here even though I checked in JSP
list.add(form.getSampleList().get(i));
}
}
...
...
}
JSP:
<ab:form id="sample3" action="submit" modelAttribute="sample3Form">
<table width="100%" class="tableborder" cellpadding="0" cellspacing="0">
...
...
<ab:tr index="${row.index}">
<td width="2%" class="data_list_area">
<ab:checkbox path="${sample3Form.samplePagedList.pageList[row.index].selectedIndex}" fwformat='NONE'
value="${sample3Form.samplePagedList.page * sample3Form.samplePagedList.pageSize + row.index }" name="checkedids"/>
</td>
<td width="5%" class="data_list_area">
<!--ab:out value="${sample3Form.samplePagedList.pageList[row.index].keiyakuno}" /-->
<ab:label path="" fwformat='NONE'>${sample3Form.samplePagedList.pageList[row.index].keiyakuno}</ab:label>
</td>
...
...
In above JSP, I set checkboxes and bind the checkboxes to selectedIndex property for for every row data.but i cannot get selected row in controller as follows:
form.getSampleList().get(i).getSelectedIndex()
The return value is always null.
why? Could who please tell me how i can get the selectedIndex in controller?
By the way, I can get checked row in controller like below:
String[] arr = request.getParameterValues("checkedids");
Remarks: in JSP, These added checkboxes is defined by name "checkedids".
and <ab:checkbox> is a tag class extends AbstractSingleCheckedElementTag.
the src for CheckboxTagImpl is here:
public class CheckboxTagImpl extends AbstractSingleCheckedElementTag {
private String maskPatterns = null;
private boolean escapeMaskFlg = false;
/**
*
* #return
*/
public String getMaskPatterns() {
return maskPatterns;
}
/**
*
* #param maskPatterns
*/
public void setMaskPatterns(String maskPatterns) {
this.maskPatterns = maskPatterns;
}
/**
* #return
*/
public Boolean isEscapeMaskFlg() {
return escapeMaskFlg;
}
/**
* #param escapeMaskFlg
*/
public void setEscapeMaskFlg (Boolean escapeMaskFlg) {
this.escapeMaskFlg = escapeMaskFlg;
}
#Override
protected int writeTagContent(TagWriter tagWriter) throws JspException {
if (maskPatterns != null) {
FormTagImpl formTag = TagUtil.getFormTag(this);
String formClassName = formTag.getModelAttribute();
String maskPattern = TagUtil.getMaskPattern(formClassName, pageContext);
if (maskPattern != null) {
String[] maskPatternArray = maskPatterns.split(",");
for (int i = 0; i < maskPatternArray.length; i++) {
if (maskPattern.equals(maskPatternArray[i])) {
setDisabled(true);
break;
}
}
}
}
FormTagImpl formTag = TagUtil.getFormTag(this);
String formClassName = formTag.getModelAttribute();
Boolean maskFlg = TagUtil.getMaskFlg(formClassName, pageContext);
if (maskFlg == true && escapeMaskFlg == false) {
setDisabled(true);
}
if (!isDisabled()) {
// Write out the 'field was present' marker.
tagWriter.startTag("input");
tagWriter.writeAttribute("type", "hidden");
String name = WebDataBinder.DEFAULT_FIELD_MARKER_PREFIX + getName();
tagWriter.writeAttribute("id", getId());
tagWriter.writeAttribute("name", name);
tagWriter.writeAttribute("value", processFieldValue(name, SystemConstant.FLAG_OFF, getInputType()));
tagWriter.endTag();
}
super.writeTagContent(tagWriter);
return SKIP_BODY;
}
#Override
protected void writeTagDetails(TagWriter tagWriter) throws JspException {
tagWriter.writeAttribute("type", getInputType());
Object boundValue = getBoundValue();
Class<?> valueType = getBindStatus().getValueType();
if (Boolean.class.equals(valueType) || boolean.class.equals(valueType)) {
// the concrete type may not be a Boolean - can be String
if (boundValue instanceof String) {
boundValue = Boolean.valueOf((String) boundValue);
}
Boolean booleanValue = (boundValue != null ? (Boolean) boundValue : Boolean.FALSE);
renderFromBoolean(booleanValue, tagWriter);
} else if (String.class.equals(valueType) && getValue() == null) {
renderFromValue(SystemConstant.FLAG_ON, tagWriter);
}
else {
Object value = getValue();
if (value == null) {
throw new IllegalArgumentException("Attribute 'value' is required when binding to non-boolean values");
}
Object resolvedValue = (value instanceof String ? evaluate("value", value) : value);
renderFromValue(resolvedValue, tagWriter);
}
}
#Override
public void doFinally() {
if (PropertiesUtil.getProperty("cleanAtDoFinally").equals("true")) {
super.doFinally();
this.maskPatterns = null;
this.escapeMaskFlg = false;
setDisabled(false);
}
}
#Override
protected String getInputType() {
return "checkbox";
}
#Override
protected String getName() throws JspException {
if (getPath()==null) {
return super.getName();
} else {
return getPath();
}
}
#Override
protected BindStatus getBindStatus() throws JspException {
BindStatus bindStatus = null;
if (bindStatus == null) {
// HTML escaping in tags is performed by the ValueFormatter class.
String nestedPath = getNestedPath();
String pathToUse = (nestedPath != null ? nestedPath + getPath() : getPath());
if (pathToUse.endsWith(PropertyAccessor.NESTED_PROPERTY_SEPARATOR)) {
pathToUse = pathToUse.substring(0, pathToUse.length() - 1);
}
bindStatus = new BindStatus(getRequestContext(), pathToUse, false);
}
return bindStatus;
}
}
Thanks.
Related
i'm trying to implement a lucene filter to remove a prefix from a term in a query.
It seems that sometime after multiple queries, the filter has been reused so the char buffer is dirty.
Code below is simplified, prefix is an external parameter.
public static class PrefixFilter extends TokenFilter {
private final PackedTokenAttributeImpl termAtt = (PackedTokenAttributeImpl) addAttribute(CharTermAttribute.class);
public PrefixFilter(TokenStream in) {
super(in);
}
#Override
public final boolean incrementToken() throws IOException {
if (!input.incrementToken()) {
return false;
}
String value = new String(termAtt.buffer());
value = value.trim();
value = value.toLowerCase();
value = StringUtils.removeStart(value, "prefix_");
if (value.isBlank()) {
termAtt.setEmpty();
} else {
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
}
return true;
}
}
So after 10 or twelve queries, the value "prefix_a" became "abcde".
So i'm trying to add termBuffer offset end value in this way:
termAtt.setEmpty();
termAtt.resizeBuffer(value.length());
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
termAtt.setOffset(0, value.length());
But i don't know if it's correct. Can anyone help me?
Thanks.
See if this helps you,
/**
* Standard number token filter.
*/
public class StandardnumberTokenFilter extends TokenFilter {
private final LinkedList<PackedTokenAttributeImpl> tokens;
private final StandardnumberService service;
private final Settings settings;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private State current;
protected StandardnumberTokenFilter(TokenStream input, StandardnumberService service, Settings settings) {
super(input);
this.tokens = new LinkedList<>();
this.service = service;
this.settings = settings;
}
#Override
public final boolean incrementToken() throws IOException {
if (!tokens.isEmpty()) {
if (current == null) {
throw new IllegalArgumentException("current is null");
}
PackedTokenAttributeImpl token = tokens.removeFirst();
restoreState(current);
termAtt.setEmpty().append(token);
posIncAtt.setPositionIncrement(0);
return true;
}
if (input.incrementToken()) {
detect();
if (!tokens.isEmpty()) {
current = captureState();
}
return true;
} else {
return false;
}
}
private void detect() throws CharacterCodingException {
CharSequence term = new String(termAtt.buffer(), 0, termAtt.length());
Collection<CharSequence> variants = service.lookup(settings, term);
for (CharSequence ch : variants) {
if (ch != null) {
PackedTokenAttributeImpl token = new PackedTokenAttributeImpl();
token.append(ch);
tokens.add(token);
}
}
}
#Override
public void reset() throws IOException {
super.reset();
tokens.clear();
current = null;
}
#Override
public boolean equals(Object object) {
return object instanceof StandardnumberTokenFilter &&
service.equals(((StandardnumberTokenFilter)object).service) &&
settings.equals(((StandardnumberTokenFilter)object).settings);
}
#Override
public int hashCode() {
return service.hashCode() ^ settings.hashCode();
}
}
https://github.com/jprante/elasticsearch-plugin-bundle/blob/f63690f877cc7f50360faffbac827622c9d404ef/src/main/java/org/xbib/elasticsearch/plugin/bundle/index/analysis/standardnumber/StandardnumberTokenFilter.java
I have created a Custom JavaFX Control, Call it ComboBoxTablePopup, it's a Generic Control witch takes a list of items of type S from the user.
Internally, i have used some sort of filtering in the TableView(a child of ComboboxTablePopup Contrl).So i have used :
FiltredList.setPridcate(S -> {
if (pr == null || pr.isEmpty() || pr.length() == 0)
return true;
if (((Engine) S).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
return true;
} else
return false;).
Because i'm using generic class and the list can be of any type i have to cast filtredlist items to well known object in ordre to get filtring work.
So, how can i make the predicate function generic, so i can work with any object and filtre it ?
Here is the code of my CustomControl:
public class ComboBoxTablePopup<S> extends ComboBoxBase {
private
ObservableList<TableColumn> columns = FXCollections.emptyObservableList();
public ObservableList<TableColumn> getColumns() {
return columns;
}
public void setColumns(ObservableList<TableColumn> columns) {
this.columns = columns;
}
/***************************************************************************
* *
* Static properties and methods *
* *
**************************************************************************/
private static <T> StringConverter<T> defaultStringConverter() {
return new StringConverter<T>() {
#Override
public String toString(T t) {
return t == null ? null : t.toString();
}
#Override
public T fromString(String string) {
return (T) string;
}
};
}
/***************************************************************************
* *
* Constructors *
* *
**************************************************************************/
/**
* Creates a default ComboboxTablePopup instance with an empty
* {#link #itemsProperty() items} list and default
* {#link #selectionModelProperty() selection model}.
*/
public ComboBoxTablePopup() {
this(FXCollections.<S>emptyObservableList());
}
/**
* Creates a default ComboboxTablePopup instance with the provided items list and
* a default {#link #selectionModelProperty() selection model}.
*/
public ComboBoxTablePopup(ObservableList<S> items) {
setItems(items);
getStyleClass().add(DEFAULT_STYLE_CLASS);
setEditable(true);
setPromptText("Plz Search for a pirticular term");
}
public ComboBoxTablePopup(ObservableList<S> items, ObservableList<TableColumn> columns) {
this(items);
this.columns = columns;
}
private static final String DEFAULT_STYLE_CLASS = "combobox-table-popup";
private ReadOnlyObjectWrapper<TextField> editor;
private ObjectProperty<ObservableList<S>> items = new SimpleObjectProperty<ObservableList<S>>(this, "items");
public final void setItems(ObservableList<S> value) {
itemsProperty().set(value);
}
public final ObservableList<S> getItems() {
return items.get();
}
public ObjectProperty<ObservableList<S>> itemsProperty() {
return items;
}
// Converter
public ObjectProperty<StringConverter<S>> converterProperty() {
return converter;
}
private ObjectProperty<StringConverter<S>> converter =
new SimpleObjectProperty<StringConverter<S>>(this, "converter", ComboBoxTablePopup.<S>defaultStringConverter());
public final void setConverter(StringConverter<S> value) {
converterProperty().set(value);
}
public final StringConverter<S> getConverter() {
return converterProperty().get();
}// Create a symmetric (format/parse) converter with the default locale.
// Editor
public TextField getEditor() {
return editorProperty().get();
}
public ReadOnlyObjectProperty<TextField> editorProperty() {
if (editor == null) {
editor = new ReadOnlyObjectWrapper<TextField>(this, "editor");
editor.set(new ComboBoxListViewSkin.FakeFocusTextField());
}
return editor.getReadOnlyProperty();
}
#Override
protected Skin<?> createDefaultSkin() {
return new ComboBoxTablePopupSkin<>(this);
}
}
public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl {
private ComboBoxTablePopup comboBoxTablePopup;
private ObservableList<S> comboboxTablePopupItems;
private TextField displayNode;
private TableView<S> tableViewPopupContent;
FilteredList<S> filtredList;
private SortedList<S> sortedList;
private Predicate<S> predicate;
private final InvalidationListener itemsObserver;
private final ListChangeListener<S> tableViewItemsListener = new ListChangeListener<S>() {
#Override
public void onChanged(ListChangeListener.Change<? extends S> c) {
getSkinnable().requestLayout();
}
};
private final WeakListChangeListener<S> weakListViewItemsListener =
new WeakListChangeListener<S>(tableViewItemsListener);
public ComboBoxTablePopupSkin(ComboBoxTablePopup comboBoxTablePopup) {
super(comboBoxTablePopup, new ComboBoxTablePopupBehavior(comboBoxTablePopup));
this.comboBoxTablePopup = comboBoxTablePopup;
setupTablePredicate();
updateComboBoxTablePopupItems();
itemsObserver = observable -> {
updateComboBoxTablePopupItems();
updateTableViewItems();
};
this.comboBoxTablePopup.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));
tableViewPopupContent = createTableView();
tableViewPopupContent.setManaged(false);
getChildren().add(tableViewPopupContent);
updateTableViewItems();
getEditor().textProperty().addListener((obv, oldValue, newValue) -> {
if (!newValue.isEmpty())
comboBoxTablePopup.show();
filtreData(newValue);
});
registerChangeListener(comboBoxTablePopup.itemsProperty(), "ITEMS");
registerChangeListener(comboBoxTablePopup.valueProperty(), "VALUE");
registerChangeListener(comboBoxTablePopup.editorProperty(), "EDITABLE");
}
private void setupTablePredicate() {
}
private void updateTableViewItems() {
filtredList = new FilteredList<S>(comboboxTablePopupItems, p -> true);
sortedList = new SortedList<S>(filtredList);
sortedList.comparatorProperty().bind(tableViewPopupContent.comparatorProperty());
tableViewPopupContent.setItems(sortedList);
}
private void filtreData(String pr) {
String data = pr;
filtredList.setPredicate(engine -> {
if (pr == null || pr.isEmpty() || pr.length() == 0)
return true;
if (((Engine) engine).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
return true;
} else
return false;
});
}
public void updateComboBoxTablePopupItems() {
comboboxTablePopupItems = comboBoxTablePopup.getItems();
comboboxTablePopupItems = comboboxTablePopupItems == null ? FXCollections.<S>emptyObservableList() : comboboxTablePopupItems;
}
private TableView<S> createTableView() {
final TableView<S> tableView = new TableView<>();
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tableView.setFocusTraversable(false);
tableView.getSelectionModel().selectedItemProperty().addListener(o -> {
int index = tableView.getSelectionModel().getSelectedIndex();
System.out.println("selected item changed");
});
for (TableColumn tblColumn : tableColumns()) {
tableView.getColumns().add(tblColumn);
}
tableView.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ENTER ||
e.getCode() == KeyCode.ESCAPE ||
e.getCode() == KeyCode.SPACE) {
S selectedItem = tableView.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
System.out.println(((Engine) selectedItem).getDesignation());
getEditor().setText(((Engine) selectedItem).getDesignation());
comboBoxTablePopup.setValue(selectedItem);
comboBoxTablePopup.hide();
}
}
});
return tableView;
}
private ObservableList<TableColumn> tableColumns() {
return ((ComboBoxTablePopup) getSkinnable()).getColumns();
}
#Override
protected Node getPopupContent() {
return this.tableViewPopupContent;
}
#Override
protected TextField getEditor() {
return ((ComboBoxTablePopup) getSkinnable()).getEditor();
}
#Override
protected StringConverter getConverter() {
return ((ComboBoxTablePopup) getSkinnable()).getConverter();
}
#Override
public Node getDisplayNode() {
if (displayNode == null) {
displayNode = getEditableInputNode();
displayNode.getStylesheets().add("ComboBoxTable-display-node");
updateDisplayNode();
}
displayNode.setEditable(comboBoxTablePopup.isEditable());
return displayNode;
}
#Override
protected void handleControlPropertyChanged(String p) {
super.handleControlPropertyChanged(p);
if ("TEXT".equals(p)) {
if (!getEditor().textProperty().get().isEmpty()) {
comboBoxTablePopup.show();
}
filtreData(getEditor().textProperty().get());
} else if ("ITEMS".equals(p)) {
updateComboBoxTablePopupItems();
} else if ("EDITABLE".equals(p)) {
getEditableInputNode();
}
}
}
Use the StringConverter to convert the item to a String or use a similar property.
public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl<S> {
...
private static final StringConverter DEFAULT_CONVERTER = new StringConverter() {
#Override
public String toString(Object o) {
return o == null ? null : o.toString();
}
#Override
public Object fromString(String s) {
throw new UnsupportedOperationException();
}
};
public final StringConverter<S> getConverter() {
StringConverter<S> converter = converterProperty().get();
// fix in case the property is set to a null
return converter == null ? DEFAULT_CONVERTER : converter;
}
private void filtreData(String pr) {
if (pr == null || pr.isEmpty()) {
filtredList.setPredicate(null);
} else {
final StringConverter<S> converter = ((ComboBoxTablePopup<S>) getSkinnable()).getConverter();
final String data = pr.toLowerCase();
filtredList.setPredicate(object -> {
String s = converter.toString(object);
return s != null && s.toLowerCase().contains(data);
});
}
}
I have created a method in which i have multiple if conditions. Now i want to refactor these if conditions. What would be the best design pattern/strategy to overcome multiple if conditions?
if
(
poConfiguration.strSampleLoaderPluginClass != null
&& poConfiguration.strSampleLoaderPluginClass.equals("") == false
)
{
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
if
(
poConfiguration.strPreprocessingPluginClass != null
&& poConfiguration.strPreprocessingPluginClass.equals("") == false
)
{
setPreprocessingPluginClass(poConfiguration.strPreprocessingPluginClass);
}
if
(
poConfiguration.strFeatureExtractionPluginClass != null
&& poConfiguration.strFeatureExtractionPluginClass.equals("") == false
)
{
setFeatureExtractionPluginClass(poConfiguration.strFeatureExtractionPluginClass);
}
if
(
poConfiguration.strClassificationPluginClass != null
&& poConfiguration.strClassificationPluginClass.equals("") == false
)
{
setClassificationPluginClass(poConfiguration.strClassificationPluginClass);
}
Please share your thoughts with implementations, if possible. Thanks in advance
My first idea would be the polymorphism (Click here for more info), it depends from the concrete situation:
interface MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration);
public void process(PoConfiguration poConfiguration);
}
public class SampleLoader implements MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration) {
return poConfiguration.strSampleLoaderPluginClass != null
&& !poConfiguration.strSampleLoaderPluginClass.isEmpty();
}
public void process(PoConfiguration poConfiguration) {
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
}
public class ClientAPI {
public void caller() {
for (MyInterface current : this.myInterfaces) {
if (current.checkCondition(current)) {
current.process();
}
}
}
You might try something like the following:
Create a Configuration class that contains ConfigurationItems
Each ConfigurationItem would have a name, value and a default value
As an improvement, you may want to create static values for the configuration items instead of using Strings.
TestConfig main Class
package com.example.config;
public class TestConfig {
static TestConfig me;
static String[][] confSettings = {{"sampleLoader","loaderDefault"}
,{"preProcessing","preProcessingDefualt"}
,{"featureExtraction","featureExtractionDefault"}
,{"classification","classificationDefault"}
};
// Object fields
Configuration configuration;
public static void main(String[] args) {
// TODO Auto-generated method stub
me = new TestConfig();
me.doWork();
}
private void doWork() {
configuration = new Configuration();
for (int i=0; i < confSettings.length; i++) {
configuration.addConfigurationItem(confSettings[i][0], confSettings[i][1], null);
}
configuration.setConfigurationItemDefault("classification", "newValue");
System.out.println("sampleLoader = " + configuration.getConfigurationItemValue("sampleLoader"));
System.out.println("classification = " + configuration.getConfigurationItemValue("classification"));
}
}
Configuration Class
package com.example.config;
import java.util.ArrayList;
import java.util.HashMap;
public class Configuration {
// Class fields
// Object fields
HashMap<String,Integer> itemNames;
ArrayList<ConfigurationItem> items;
public Configuration() {
items = new ArrayList<ConfigurationItem>();
itemNames = new HashMap<String,Integer>();
}
public Configuration addConfigurationItem(String name, String defaultValue, String value) {
if (itemNames.containsKey(name)) {
// handle duplicate configuration item
} else {
items.add(new ConfigurationItem(name, defaultValue, value));
Integer loc = new Integer(items.size()-1);
itemNames.put(name, loc);
}
return this;
}
public void setConfigurationItemDefault(String name, String defaultValue) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
items.get(loc).setDefaultValue(defaultValue);
}
}
public String getConfigurationItemValue(String name) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
return items.get(loc).getValue();
} else {
// handle unknown parameter
return null;
}
}
private int getConfigurationItemIndex(String name) {
if (itemNames.containsKey(name)) {
return itemNames.get(name);
} else {
// handle unknown parameter
return -1;
}
}
}
ConfigurationItem Class
package com.example.config;
public class ConfigurationItem {
// Object fields
String name;
String value;
String defaultValue;
public ConfigurationItem(){};
public ConfigurationItem(String name, String defaultValue, String value) {
this.setName(name).setDefaultValue(defaultValue).setValue(value);
}
public ConfigurationItem setName(String name) {
this.name = name;
return this;
}
public ConfigurationItem setValue(String value) {
this.value = value;
return this;
}
public ConfigurationItem setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public String getValue() {
if (value == null || value.length() == 0) {
return defaultValue;
} else {
return value;
}
}
}
I have an object CategoryBean where are defined a list of other objects CategoryBean (its children) and another object CategoryBean (its parent).
Cloning its children is not a problem, but cloning its parent isn't working. Indeed, when I have my object A and its parent P, when I go through P and get the list of its children (where I should fine A), A has not the same reference than the child of P. The objects equal ("attributly" speaking) but are not the same.
Here is my class and its attributes :
public class CategoryBean implements Externalizable, Cloneable {
public static final boolean ACTIVE = true;
public static final boolean INACTIVE = false;
public static final int VALIDATED = 1;
public static final int NON_OBSERVED = 2;
public static final int IN_PROGRESS = 3;
public static final int PARTIEL = 4;
private String perimetre;
private CategoryBean parentCategory;
private List<CategoryBean> categoryList = new LinkedList<CategoryBean>();
protected String title;
/**
* Category validée ou non
*/
protected int state = NON_OBSERVED;
/**
* Category active ou inactive
*/
protected boolean activated = ACTIVE;
/**
* #return the parentCategory
*/
public CategoryBean getParentCategory() {
return parentCategory;
}
/**
* #param parentCategory
* the parentCategory to set
*/
public void setParentCategory(CategoryBean parentCategory) {
this.parentCategory = parentCategory;
}
/**
* #return the perimetre
*/
public String getPerimetre() {
return perimetre != null ? perimetre.trim() : null;
}
/**
* #param perimetre
* the perimetre to set
*/
public void setPerimetre(String perimetre) {
this.perimetre = perimetre != null ? perimetre.trim() : null;
}
/**
* #return the category
*/
public List<CategoryBean> getCategoryList() {
return categoryList;
}
/**
* #param category
* the category to set
*/
public void setCategoryList(List<CategoryBean> categoryList) {
this.categoryList = categoryList;
}
/**
* #return the title
*/
public String getTitle() {
return title != null ? title.trim() : null;
}
/**
* #param title
* the title to set
*/
public void setTitle(String title) {
this.title = title != null ? title.trim() : null;
}
/**
* #return the state
*/
public int getState() {
return state;
}
/**
* #param state
* the state to set
*/
public void setState(int state) {
this.state = state;
}
/**
* #return the activated
*/
public boolean isActivated() {
return activated;
}
/**
* #param activated
* the activated to set
*/
public void setActivated(boolean activated) {
this.activated = activated;
}
#Override
public int hashCode() {
if (parentCategory != null && categoryList != null && title != null) {
return parentCategory.hashCode() + categoryList.hashCode() + title.hashCode();
} else if (categoryList != null && title != null) {
return parentCategory.hashCode() + categoryList.hashCode() + title.hashCode();
} else {
return super.hashCode();
}
}
#Override
public boolean equals(Object o) {
if (o != null && o instanceof CategoryBean) {
CategoryBean o2 = (CategoryBean) o;
if (getPerimetre() != null && getTitle() != null && getParentCategory() != null) {
return getPerimetre().equals(o2.getPerimetre()) && getTitle().equals(o2.getTitle())
&& getParentCategory().equals(o2.getParentCategory());
} else if (getPerimetre() != null && getTitle() != null && getPerimetre().equals(getTitle())) {
return getPerimetre().equals(o2.getPerimetre()) && getTitle().equals(o2.getTitle());
}
}
return super.equals(o);
}
#SuppressWarnings("unchecked")
#Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
setPerimetre((String) input.readObject());
setParentCategory((CategoryBean) input.readObject());
setCategoryList((List<CategoryBean>) input.readObject());
setTitle((String) input.readObject());
setState((Integer) input.readObject());
setActivated((Boolean) input.readObject());
}
#Override
public void writeExternal(ObjectOutput output) throws IOException {
output.writeObject(getPerimetre());
output.writeObject(getParentCategory());
output.writeObject(getCategoryList());
output.writeObject(getTitle());
output.writeObject(getState());
output.writeObject(isActivated());
}
#Override
public CategoryBean clone() throws CloneNotSupportedException {
try {
CategoryBean clone = (CategoryBean) super.clone();
clone.setPerimetre(getPerimetre());
clone.setParentCategory(getParentCategory());
List<CategoryBean> categoryListClone = null;
if (getCategoryList() != null) {
categoryListClone = new LinkedList<CategoryBean>();
for (int i = 0; i < getCategoryList().size(); i++) {
categoryListClone.add(getCategoryList().get(i).clone());
}
}
clone.setCategoryList(categoryListClone);
clone.setTitle(getTitle());
clone.setState(getState());
clone.setActivated(isActivated());
return clone;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
}
Do you know what I do wrong in the clone method ?
Thanks for you help :)
(Edit) Solution :
public CategoryBean clone() throws CloneNotSupportedException {
try {
CategoryBean clone = (CategoryBean) super.clone();
clone.setPerimetre(getPerimetre());
List<CategoryBean> categoryListClone = null;
if (getCategoryList() != null) {
categoryListClone = new LinkedList<CategoryBean>();
for (int i = 0; i < getCategoryList().size(); i++) {
CategoryBean childClone = getCategoryList().get(i).clone();
childClone.setParentCategory(clone);
categoryListClone.add(childClone);
}
}
clone.setCategoryList(categoryListClone);
clone.setTitle(getTitle());
clone.setState(getState());
clone.setActivated(isActivated());
return clone;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
I think you need to cache the parent beans already cloned during the clone operation, so that when clone.setParentCategory is called in the child, this is the cloned parent that is injected in the property...
Not sure it's crystal clear :)... so... something like this (careful, no tested !) :
#Override
public CategoryBean clone() throws CloneNotSupportedException {
return cloneRecursive(new HashMap<CategoryBean, CategoryBean>());
}
private CategoryBean cloneRecursive(Map<CategoryBean, CategoryBean> categoryBeans) throws CloneNotSupportedException {
try {
CategoryBean clone = (CategoryBean) super.clone();
categoryBeans.put(this, clone);
clone.setPerimetre(getPerimetre());
clone.setParentCategory(categoryBeans.get(getParentCategory()));
List<CategoryBean> categoryListClone = null;
if (getCategoryList() != null) {
categoryListClone = new LinkedList<CategoryBean>();
for (int i = 0; i < getCategoryList().size(); i++) {
categoryListClone.add(getCategoryList().get(i).cloneRecursive(categoryBeans));
}
}
clone.setCategoryList(categoryListClone);
clone.setTitle(getTitle());
clone.setState(getState());
clone.setActivated(isActivated());
return clone;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
I have a form that looks somewhat like this:
public class MaintainForecastInputForm extends ActionForm {
private MainMenuForm mainMenuForm = new MainMenuForm();
public SelectProdLineAssociationForm selectProdLineAssociationForm = new SelectProdLineAssociationForm();
private EconometricDataForm econometricDataForm = new EconometricDataForm();
private EconometricImportDownloadForm econometricImportDownloadForm = new EconometricImportDownloadForm();
private String userAction;
private List<MaintainForecastInputForm.DemandForecast> demands = new ArrayList<MaintainForecastInputForm.DemandForecast>();
private List<MaintainForecastInputForm.DemandForecast> forecasts = new ArrayList<MaintainForecastInputForm.DemandForecast>();
private DemandForecast iimsForecast = new DemandForecast();
private DemandForecast econometricForecast = new DemandForecast();
public static class DemandForecast {
private String subType;
private String shortTermWtAvg="0.0";
private String midTermWtAvg="0.0";
private String longTermWtAvg="0.0";
private String shortTermPct="0.0";
private String midTermPct="0.0";
private String longTermPct="0.0";
private List yearDemands = new ArrayList();
public static class Year {
private String fyTotalValue="0.0";
private String fyPctChange="0.0";
private List monthDemands = new ArrayList();
public String getFyPctChange() {
return fyPctChange;
}
public void setFyPctChange(String fyPctChange) {
this.fyPctChange = fyPctChange;
}
public String getFyTotalValue() {
return fyTotalValue;
}
public void setFyTotalValue(String fyTotalValue) {
this.fyTotalValue = fyTotalValue;
}
} // Year
public static class Month {
private String demandValue="0.0";
private String demandQuantity="0.0";
public String getDemandQuantity() {
return demandQuantity;
}
public void setDemandQuantity(String demandQuantity) {
this.demandQuantity = demandQuantity;
}
public String getDemandValue() {
return demandValue;
}
public void setDemandValue(String demandValue) {
this.demandValue = demandValue;
}
} // Month
public String getLongTermPct() {
return longTermPct;
}
public void setLongTermPct(String longTermPct) {
this.longTermPct = longTermPct;
}
public String getLongTermWtAvg() {
return longTermWtAvg;
}
public void setLongTermWtAvg(String longTermWtAvg) {
this.longTermWtAvg = longTermWtAvg;
}
public String getMidTermPct() {
return midTermPct;
}
public void setMidTermPct(String midTermPct) {
this.midTermPct = midTermPct;
}
public String getMidTermWtAvg() {
return midTermWtAvg;
}
public void setMidTermWtAvg(String midTermWtAvg) {
this.midTermWtAvg = midTermWtAvg;
}
public String getShortTermPct() {
return shortTermPct;
}
public void setShortTermPct(String shortTermPct) {
this.shortTermPct = shortTermPct;
}
public String getShortTermWtAvg() {
return shortTermWtAvg;
}
public void setShortTermWtAvg(String shortTermWtAvg) {
this.shortTermWtAvg = shortTermWtAvg;
}
public String getSubType() {
return subType;
}
public void setSubType(String subType) {
this.subType = subType;
}
public List getYearDemands() {
return yearDemands;
}
public void setYearDemands(List yearDemands) {
this.yearDemands = yearDemands;
}
} // DemandForecast
}
and in my JSP I have the following:
<c:forEach items="${form.iimsForecast.yearDemands}" var="yearDemand" varStatus="year">
<tr>
<td>${yearDemand.fiscalYear}</td>
<c:forEach items="${yearDemand.monthDemands}" var="yearMonth" varStatus="month">
<c:choose>
<c:when test="${year.count == 1 && month.count < yearDemand.currentMonth}">
<td class="lightShaded dmnd">
<html-el:text property="form.iimsForecast.yearDemands.monthDemands.demandValue">
</td>
...
I'm getting a JSP exception - getter property is not been found in the form although it is there. Can somebody help me with this problem please?
Your code does not show whether you have a getIimsForecast() method on your form (it only shows iimsForecast property) - if you don't, you need to add it. However, that's not the only problem.
Your property path includes yearDemands and monthDemands and getter methods for both return Lists. That's illegal - nested property path must either have single beans or have indexed access for list elements (e.g. iimsForecast.yearDemands[0].monthDemands[0].demandValue).
Finally, you probably don't need to prefix your property path with form, although that depends on your configuration and whether you have an enclosing <html:form> tag.
This may sound obvious, but did you add the tag library to the page?
<%# taglib prefix="html" uri="http://struts.apache.org/tags-html-el" %>