/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package components;
import java.io.IOException;
import java.util.Iterator;
import javax.faces.application.FacesMessage;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UISelectItem;
import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.component.html.HtmlSelectBooleanCheckbox;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.validator.LengthValidator;
import org.apache.empire.commons.OptionEntry;
import org.apache.empire.commons.Options;
import org.apache.empire.data.DataType;
import org.apache.empire.db.DBRecord;
import org.apache.empire.db.DBTableColumn;
import org.apache.empire.jsf2.websample.web.FacesUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class control extends UIInput implements NamingContainer {
// Logger
private static final Logger log = LoggerFactory.getLogger(control.class);
private static final String LABEL_SUFFIX = "label";
private static final String INPUT_SUFFIX = "input";
public control()
{
super();
}
@Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
// add label and input components when the view is loaded for the first time
HtmlOutputLabel labelComponent = null;
UIInput inputComponent = null;
if (getChildCount() > 0)
{
labelComponent = (HtmlOutputLabel)getChildren().get(0);
inputComponent = (UIInput)getChildren().get(1);
}
if (labelComponent == null)
{
labelComponent = createOutputLabelForCol();
this.getChildren().add(labelComponent);
}
if (inputComponent == null)
{
inputComponent = createInputComponentForCol();
this.getChildren().add(inputComponent);
}
// render components
context.getResponseWriter().startElement("div", null);
labelComponent.encodeAll(context);
inputComponent.encodeAll(context);
context.getResponseWriter().endElement("div");
super.encodeBegin(context);
}
@Override
public void updateModel(FacesContext context) {
DBRecord rec = getRecord();
DBTableColumn col = getColumn();
// don't set automatically created cols or readOnly cols
if (!col.isAutoGenerated() && !isReadOnly()) {
UIInput inputComponent = (UIInput)getChildren().get(1);
rec.setValue(col, inputComponent.getValue());
}
super.updateModel(context);
}
@Override
public void validate(FacesContext context) {
// nothing submitted (AJAX part request, e.g. calendar component) or readonly (won't be set in updateModel())?
UIInput inputComponent = (UIInput)getChildren().get(1);
// component itself already checked validity, was it successful?
if (inputComponent == null || !inputComponent.isValid() || isReadOnly())
{
return;
}
DBRecord rec = getRecord();
DBTableColumn col = (DBTableColumn) rec.getDBColumn(rec
.getFieldIndex(getAttributes().get("column").toString()));
try {
col.checkValue(inputComponent.getValue());
} catch (Exception e) {
FacesContext.getCurrentInstance().addMessage(getClientId(), new FacesMessage(e.getLocalizedMessage()));
this.setValid(false);
}
super.validate(context);
}
private void addSelectItems(UIComponent component) {
Options options = getRecord().getFieldOptions(getColumn());
if (options != null) {
Iterator<OptionEntry> optionsIterator = options.iterator();
while (optionsIterator.hasNext()) {
OptionEntry optionEntry = optionsIterator.next();
UISelectItem selectItem = new UISelectItem();
selectItem.setItemValue(optionEntry.getValueString());
selectItem.setItemLabel(FacesUtils.getMessageForKey(optionEntry
.getText()));
component.getChildren().add(selectItem);
}
}
}
private UIInput createInputComponentForCol() {
DBTableColumn col = getColumn();
String controlType = col.getControlType();
// registerControl("text", new TextInputControl());
// registerControl("select", new SelectInputControl());
// registerControl("checkbox", new CheckboxInputControl());
// registerControl("phone", new PhoneInputControl());
// registerControl("radio", new RadioInputControl());
// registerControl("textarea", new TextAreaInputControl());
// registerControl("email", new EMailInputControl());
// registerControl("hlink", new HLinkInputControl());
// registerControl("password", new PasswordInputControl());
UIInput input = null;
if (controlType.equals("text")) {
// DATE_TIME
if (col.getDataType().equals(DataType.DATETIME))
{
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(isReadOnly() || col.isAutoGenerated());
inputText.setLabel(getLabelString());
input = inputText;
}
// AUTOINC
else if (col.getDataType().equals(DataType.AUTOINC))
{
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(true);
inputText.setLabel(getLabelString());
input = inputText;
}
// INTEGER
else if (col.getDataType().equals(DataType.INTEGER))
{
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(isReadOnly() || col.isAutoGenerated());
inputText.setLabel(getLabelString());
input = inputText;
}
// DATE
else if (col.getDataType().equals(DataType.TEXT) || col.getDataType().equals(DataType.DATE)) {
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(isReadOnly() || col.isAutoGenerated());
inputText.setLabel(getLabelString());
input = inputText;
}
// TEXT
else if (col.getDataType().equals(DataType.TEXT) || col.getDataType().equals(DataType.DATE)) {
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(isReadOnly() || col.isAutoGenerated());
inputText.setLabel(getLabelString());
inputText.setMaxlength((int) Math.round(col.getSize()));
input = inputText;
}
}
else if (controlType.equals("textarea")) {
HtmlSelectBooleanCheckbox inputSelectBooleanCheckbox = new HtmlSelectBooleanCheckbox();
inputSelectBooleanCheckbox.setReadonly(isReadOnly() || col.isAutoGenerated());
inputSelectBooleanCheckbox.setLabel(getLabelString());
input = inputSelectBooleanCheckbox;
} else if (controlType.equals("password")) {
HtmlSelectBooleanCheckbox inputSelectBooleanCheckbox = new HtmlSelectBooleanCheckbox();
inputSelectBooleanCheckbox.setReadonly(isReadOnly() || col.isAutoGenerated());
inputSelectBooleanCheckbox.setLabel(getLabelString());
input = inputSelectBooleanCheckbox;
} else if (controlType.equals("select")) {
HtmlSelectOneMenu inputSelectOneMenu = new HtmlSelectOneMenu();
inputSelectOneMenu.setReadonly(isReadOnly() || col.isAutoGenerated());
addSelectItems(inputSelectOneMenu);
inputSelectOneMenu.setLabel(getLabelString());
input = inputSelectOneMenu;
} else if (controlType.equals("checkbox")) {
HtmlSelectBooleanCheckbox inputSelectBooleanCheckbox = new HtmlSelectBooleanCheckbox();
inputSelectBooleanCheckbox.setReadonly(isReadOnly() || col.isAutoGenerated());
inputSelectBooleanCheckbox.setLabel(getLabelString());
input = inputSelectBooleanCheckbox;
}
else if (controlType.equals("phone")) {
HtmlInputText inputText = new HtmlInputText();
inputText.setReadonly(isReadOnly() || col.isAutoGenerated());
inputText.setLabel(getLabelString());
inputText.setMaxlength((int) Math.round(col.getSize()));
input = inputText;
}
// For testing purposes only
if (input == null) {
log.error("No matching control found for column "
+ col.getFullName());
input = new HtmlInputText();
}
// JSF2 Validator
switch (col.getDataType()) {
case TEXT: {
input.addValidator(new LengthValidator((int) Math.round(col
.getSize())));
break;
}
}
input.setRequired(col.isRequired() && !col.isAutoGenerated());
input.setId(this.getId() + INPUT_SUFFIX);
input.setValue(getRecord().getValue(col));
return input;
}
private HtmlOutputLabel createOutputLabelForCol() {
DBTableColumn col = getColumn();
HtmlOutputLabel label = new HtmlOutputLabel();
String colName = getLabelString()+":";
if (col.isRequired()) {
colName += "*";
}
label.setId(this.getId() + LABEL_SUFFIX);
label.setValue(colName);
return label;
}
private DBRecord getRecord() {
// if parent is a record tag, get the record from there
record recordComponent = getRecordComponent();
if (recordComponent != null)
{
return recordComponent.getRecord();
}
return (DBRecord) getAttributes().get("record");
}
private record getRecordComponent() {
// walk upwards the parent component tree and return the first record component found (if any)
UIComponent parent = this;
while ((parent = parent.getParent()) != null)
{
if (parent instanceof record)
{
return (record)parent;
}
}
return null;
}
private DBTableColumn getColumn() {
return (DBTableColumn) getRecord().getDBColumn(
getRecord().getFieldIndex(
getAttributes().get("column").toString()));
}
private boolean isReadOnly() {
// if readonly attribute is set, override column setting
Object readonlyString = getAttributes().get("readonly");
if (readonlyString != null)
{
return Boolean.parseBoolean(readonlyString.toString().toLowerCase());
}
return getColumn().isReadOnly();
}
private String getLabelString() {
String label = null;
// check attributes if default col label is overriden
if (getAttributes().get("label") != null) {
label = getAttributes().get("label").toString();
}
// not overriden: take label from column full name
else {
label = getColumn().getFullName();
}
return FacesUtils.getMessageForKey(label);
}
}