I am creating some forms and I need to create masks and validation for some fields.
Is it implemented in anyway in JavaFX?
My example of the mask.
Using:
<MaskField mask="+7(DDD)DDD-DDDD"/>
<MaskField mask="AA DDD AAA" placeholder="__ ### ___"/>
etc
Restricting input from Richard's fxexperience post:
TextField field = new TextField() {
#Override public void replaceText(int start, int end, String text) {
// If the replaced text would end up being invalid, then simply
// ignore this call!
if (!text.matches("[a-z]")) {
super.replaceText(start, end, text);
}
}
#Override public void replaceSelection(String text) {
if (!text.matches("[a-z]")) {
super.replaceSelection(text);
}
}
};
If you want to create your use a mask and create your own control, take a look at Richard's MoneyField, which also includes a sample project and source. Along the same lines there are controls to restict input to Integers, Doubles or formatted web colors (e.g. #rrggbb) in the fxexperience repository. All of these follow a common theme where they subclass Control, provide some properties to be get and set which define the public interface and then also define a private backing skin which handles rendering of the UI based on the values set through the public interface.
I had the same needs. I created this field, called it SpecialTextField, and pushed into GitHub. Example also there. Hope this help.
NOTE: this only works correctly with JRE 1.8.0_25 or lower. With JRE 1.8.0_48 or 0_51, the caret position is always set to 0 after each character input.
No, this is not implemented in standard JavaFX. You need to use some library or do it yourself.
This is my implementation of static mask for text fields. It works for date, phone and other types of static masks:
/**
* Adds a static mask to the specified text field.
* #param tf the text field.
* #param mask the mask to apply.
* Example of usage: addMask(txtDate, " / / ");
*/
public static void addMask(final TextField tf, final String mask) {
tf.setText(mask);
addTextLimiter(tf, mask.length());
tf.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
String value = stripMask(tf.getText(), mask);
tf.setText(merge(value, mask));
}
});
tf.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(final KeyEvent e) {
int caretPosition = tf.getCaretPosition();
if (caretPosition < mask.length()-1 && mask.charAt(caretPosition) != ' ' && e.getCode() != KeyCode.BACK_SPACE && e.getCode() != KeyCode.LEFT) {
tf.positionCaret(caretPosition + 1);
}
}
});
}
static String merge(final String value, final String mask) {
final StringBuilder sb = new StringBuilder(mask);
int k = 0;
for (int i = 0; i < mask.length(); i++) {
if (mask.charAt(i) == ' ' && k < value.length()) {
sb.setCharAt(i, value.charAt(k));
k++;
}
}
return sb.toString();
}
static String stripMask(String text, final String mask) {
final Set<String> maskChars = new HashSet<>();
for (int i = 0; i < mask.length(); i++) {
char c = mask.charAt(i);
if (c != ' ') {
maskChars.add(String.valueOf(c));
}
}
for (String c : maskChars) {
text = text.replace(c, "");
}
return text;
}
public static void addTextLimiter(final TextField tf, final int maxLength) {
tf.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
if (tf.getText().length() > maxLength) {
String s = tf.getText().substring(0, maxLength);
tf.setText(s);
}
}
});
}
See also:
JavaFX 2.2 TextField maxlength
Supported by current javafx-2 platform by default - No, but go through this link , it has many insights and sample code for Form validation in javaFX
public class NumberTextField extends TextField {
private int maxLenght;
public NumberTextField(int maxLenght) {
super();
this.maxLenght = maxLenght;
}
#Override
public void replaceText(int start, int end, String text) {
if (validate(text)) {
super.replaceText(start, end, text);
}
}
#Override
public void replaceSelection(String text) {
if (validate(text)) {
super.replaceSelection(text);
}
}
private boolean validate(String text) {
if (this.getText() != null) {
}
boolean status = ("".equals(text) || text.matches("[0-9]"));
if (this.getText() == null) {
return status;
} else {
return (status && this.getText().length() < maxLenght);
}
}
}
In some cases I would validate the text property:
myTextField
.textProperty()
.addListener(
(obs, oldVal, newVal) ->
{
if(!newVal.matches("\\d+"))
textField.setText(oldV);
});
Unlucky: textField.setText(oldV); will enter the same function again, testing unnecessarily if oldVal matches.
If the TextField becomes a value that doesn't matches before this listener is added to the TextField, enter a not matching new value will cause a loop!!!
To avoid this, it will be safer to write:
String acceptableValue = "0";
myTextField
.textProperty()
.addListener(
(obs, oldVal, newVal) ->
{
if(!newVal.matches("\\d+"))
textField.setText(oldVal.matches("\\d+") ? oldV : acceptableValue);
});
I wrote a class that extends the TextField and apply the mask.
package com.model;
import java.text.NumberFormat;
import java.util.Locale;
/**
* ATENTION
* DO NOT FORGUET TO IMPORT IN FXML
* <?import com.view.TextFieldMoney?>
*
* */
import javafx.scene.control.TextField;
public class TextFieldMoney extends TextField {
private int maxlength;
private String valor = "";
public TextFieldMoney() {
this.maxlength = 11;
}
public void setMaxlength(int maxlength) {
this.maxlength = maxlength;
}
#Override
public void replaceText(int start, int end, String text) {
// Delete or backspace user input.
if (getText() == null || getText().equalsIgnoreCase("")) {
valor = "";
}
if (text.equals("")) {
super.replaceText(start, end, text);
} else{
text = text.replaceAll("[^0-9]", "");
valor += text;
super.replaceText(start, end, text);
if (!valor.equalsIgnoreCase(""))
setText(formata(valor));
}
}
#Override
public void replaceSelection(String text) {
// Delete or backspace user input.
if (text.equals("")) {
super.replaceSelection(text);
} else if (getText().length() < maxlength) {
// Add characters, but don't exceed maxlength.
// text = MascaraFinanceira.show(text);
if (text.length() > maxlength - getText().length()) {
// text = MascaraFinanceira.show(text);
text = text.substring(0, maxlength - getText().length());
}
super.replaceSelection(text);
}
}
/*
*Return the number without money mask
**/
public String getCleanValue(){
String cleanString = getText().replaceAll("[^0-9]", "");
Double cleanNumber = new Double(cleanString);
return String.valueOf(cleanNumber/100);
}
private String formata(Double valor) {
Locale locale = new Locale("pt", "BR");
NumberFormat nf = NumberFormat.getInstance(locale);
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
return nf.format(valor);
}
public String formata(String valor) {
double v = new Double(valor);
return formata(v/100);
}
}
And in the FXML where is
<TextField fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />
put
<TextFieldMoney fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />
Related
This Is Main Fragment
Fragment:
private void getStock() {
dialog.show();
Retrofit retrofit = RetrofitClient.getRetrofitInstance();
apiInterface api = retrofit.create(apiInterface.class);
Call<List<Blocks>>call = api.getVaccineBlocks();
call.enqueue(new Callback<List<Blocks>>() {
#Override
public void onResponse(Call<List<Blocks>>call, Response<List<Blocks>> response) {
if (response.code() == 200) {
block = response.body();
spinnerada();
dialog.cancel();
}else{
dialog.cancel();
}
}
#Override
public void onFailure(Call<List<Blocks>> call, Throwable t) {
dialog.cancel();
}
});
}
private void spinnerada() {
String[] s = new String[block.size()];
for (int i = 0; i < block.size(); i++) {
s[i] = block.get(i).getBlockName();
final ArrayAdapter a = new ArrayAdapter(getContext(), android.R.layout.simple_spinner_item, s);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
spinner.setAdapter(a);
}
}
This Is Blocks Model
model:
package com.smmtn.book.models;
import java.io.Serializable;
public class Blocks implements Serializable {
public String id;
public String blockName;
public String blockSlug;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBlockName() {
return blockName;
}
public void setBlockName(String blockName) {
this.blockName = blockName;
}
public String getBlockSlug() {
return blockSlug;
}
public void setBlockSlug(String blockSlug) {
this.blockSlug = blockSlug;
}
}
here i need onitemclick with blockslug please any one can help, am new to android so i need some example.when on click i want take blockslug and load another method with that blockslug,like will get data from u "http://example.com/block/"+blockslug
i want to get blockslug from selected block
i hope guys i will get help
and sorry for my bad English,
First of all, you need to implement setOnItemSelectedListener. Refer to this https://stackoverflow.com/a/20151596/9346054
Once you selected the item, you can call them by making a new method. Example like below
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"OnItemSelectedListener : " + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_SHORT).show();
final String itemSelected = parent.getItemAtPosition(pos).toString();
showBlockSlug(itemSelected);
}
And then, at the method showBlockSlug() , you can call Retrofit.
private void showBlockSlug(final String blockslug){
final String url = "http://example.com/block/"+ blockslug;
//Do your stuff...
}
My 2D array has 5x3. In array I have stored id, name, image source string. I trying to put these values in Adapter to make newInstance, but all values in Fragment are passed as null.
My Adapter:
private class ScreenSlidePagerAdapter extends FragmentStateAdapter {
ScreenSlidePagerAdapter(FragmentActivity fa) {
super(fa);
}
#Override
public Fragment createFragment(int position) {
if (position < q_question.length) {
int i = 0;
int id = 0;
String name = "";
String src = "";
while (i < 5) {
if (!TextUtils.isEmpty(q_question[i][0]) && TextUtils.isDigitsOnly(q_question[i][0])) {
id = Integer.parseInt(q_question[i][0]);
}
name = q_question[i][1];
src = q_question[i][2];
i++;
}
return ScreenSlidePageFragment.newInstance2(id, name, src);
}else
return null;
}
#Override
public int getItemCount() {
return q_question.length;
}
}
My Fragment:
public class ScreenSlidePageFragment extends Fragment {
private static final String ARG_RESOURCE_ID = "resource_id";
private static final String ARG_RESOURCE_NAME = "resource_name";
private static final String ARG_RESOURCE_SRC = "resource_src";
private int id;
private String Name;
private String Src;
public ScreenSlidePageFragment() {
// Required empty public constructor
}
public static Fragment newInstance2(int id, String name, String src) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt(ARG_RESOURCE_ID, id);
args.putString(ARG_RESOURCE_NAME, name);
args.putString(ARG_RESOURCE_SRC, src);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
id = getArguments().getInt(ARG_RESOURCE_ID);
Name = getArguments().getString(ARG_RESOURCE_NAME);
Src = getArguments().getString(ARG_RESOURCE_SRC);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_screen_slide_page, container, false);
// assign our image's resource id here
ImageView imageView = view.findViewById(R.id.question_image);
Button button = view.findViewById(R.id.answer_one);
imageView.setImageDrawable(Drawable.createFromPath(Src));
button.setText(Name);
Log.e("test", id + Src +"//"+ Name); // There id always are 3, and src and name null
return view;
}
}
Have no time to answer, but i managed it myself.
Removing while (i < 5) statement from ScreenSlidePagerAdapter and leave all code in it outside statement, and all working.
I want data to be displayed as shown in imageenter image description here
I want to add multiple item of same date in single card view instead of creating another card view for the item of same date
I have tried in Android Studio grouping recycler view called as sanctioned Recycler view where I used date as header but it's not the solution
My Adapter Class
private Context mContext;
List<ListItem> consolidatedList = new ArrayList<>();
public AttendanceAdapter(Context context, List<ListItem>
consolidatedList) {
this.consolidatedList = consolidatedList;
this.mContext = context;
}
#Override
public RecyclerView.ViewHolder
onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater =
LayoutInflater.from(parent.getContext());
switch (viewType) {
case ListItem.TYPE_GENERAL:
View v1 =
inflater.inflate(R.layout.attendance_adapter_layout, parent,
false);
viewHolder = new GeneralViewHolder(v1);
break;
case ListItem.TYPE_DATE:
View v2 =
inflater.inflate(R.layout.attn_item_header, parent, false);
viewHolder = new DateViewHolder(v2);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder
viewHolder, int position)
{
switch (viewHolder.getItemViewType()) {
case ListItem.TYPE_GENERAL:
GeneralItem generalItem = (GeneralItem)
consolidatedList.get(position);
GeneralViewHolder generalViewHolder=
(GeneralViewHolder) viewHolder;
//generalViewHolder.txt_date.setText(
generalItem.getAttendance_data().getDate());
generalViewHolder.txt_month.setText(
generalItem.getAttendance_data().getMonth_name());
generalViewHolder.txt_date.setText(
generalItem.getAttendance_data().getDate_no());
generalViewHolder.txt_out.setText(
generalItem.getAttendance_data().getAttn_out_time());
generalViewHolder.txt_in.setText(
generalItem.getAttendance_data().getAttn_In_time());
generalViewHolder.txtreason.setText
(generalItem.getAttendance_data().getRemark());
break;
case ListItem.TYPE_DATE:
DateItem dateItem = (DateItem)
consolidatedList.get(position);
DateViewHolder dateViewHolder = (DateViewHolder) viewHolder;
dateViewHolder.txtTitle.setText(dateItem.getDate());
// Populate date item data here
break;
}
}
class DateViewHolder extends RecyclerView.ViewHolder {
protected TextView txtTitle;
public DateViewHolder(View v) {
super(v);
this.txtTitle = (TextView)
v.findViewById(R.id.attn_date);
}
}
// View holder for general row item
class GeneralViewHolder extends RecyclerView.ViewHolder {
protected TextView
txt_in,txtreason,txt_out,txt_date,txt_month;
public GeneralViewHolder(View v) {
super(v);
this.txt_in =v.findViewById(R.id.attn_in_txt);
this.txt_out=v.findViewById(R.id.attn_out_txt);
this.txtreason=v.findViewById(R.id.attn_reason_txt);
this.txt_date=v.findViewById(R.id.date_view);
this.txt_month=v.findViewById(R.id.month_view);
}
}
#Override
public int getItemViewType(int position) {
return consolidatedList.get(position).getType();
}
#Override
public int getItemCount() {
return consolidatedList != null ? consolidatedList.size() : 0;
}
}
MainActivity.Java
public class CurrentMonth extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... voids) {
attn_list_data_cur_month();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
updateUi();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
public void attn_list_data_cur_month(){
try {
this.connection=createConnection();
Statement stmt=connection.createStatement();
Calendar current_month_data = Calendar.getInstance();
current_month_data.add(Calendar.MONTH, 0);
//Calendar current_month_date = Calendar.getInstance();
//current_month_date.set(Calendar.DAY_OF_MONTH,0);
n=current_month_data.get(Calendar.DAY_OF_MONTH);
String current_month_year = new SimpleDateFormat("MMM-
yyyy").format(current_month_data.getTime());
String month_name=currentMonth.getText().toString();
for (int i=1;i<=n;i++) {
String date = i + "-" + current_month_year;
ResultSet resultSet = stmt.executeQuery("Select * from
MATTN_MAS where ATTN_DATE='" + date + "' and Username='" +
Username + "'");
String Attn_Type;
if (resultSet.next()) {
while (resultSet.next()) {
Attn_Type = resultSet.getString(8);
String Time = null;
String Reason = resultSet.getString(11);
if (Attn_Type.equals("I")) {
String Attn_Type_In = "I";
String Attn_Type_Out = null;
StringBuilder stringBuilder = new StringBuilder("" + i);
String date_no = stringBuilder.toString();
myOptions.add(new Attendance_Data(Attn_Type_In,
date, Reason, Attn_Type_Out, i, date_no, month_name));
} else {
String Attn_Type_Out = "O";
String Attn_Type_In = null;
StringBuilder stringBuilder = new StringBuilder("" + i);
String date_no = stringBuilder.toString();
myOptions.add(new Attendance_Data(Attn_Type_In,
date, Reason, Attn_Type_Out, i, date_no, month_name));
}
}
} else {
Attn_Type = "Absent";
String Time = null;
String Reason = null;
String out = null;
StringBuilder stringBuilder = new StringBuilder("" + i);
String date_no = stringBuilder.toString();
myOptions.add(new Attendance_Data(Attn_Type, date, Reason,
out, i, date_no, month_name));
}
}
}catch (Exception e){
System.out.println("my Error"+e);
}
}
public void updateUi(){
//sortedData= (List<PojoOfJsonArray>)
PojoOfJsonArray.sortList(myOptions);
HashMap<String, List<Attendance_Data>> groupedHashMap =
groupDataIntoHashMap(myOptions);
for (String date1 : groupedHashMap.keySet()) {
DateItem dateItem = new DateItem();
dateItem.setDate(date1);
consolidatedList.add(dateItem);
for (Attendance_Data pojoOfJsonArray : groupedHashMap.get(date1))
{
GeneralItem generalItem = new GeneralItem();
generalItem.setAttendance_data(pojoOfJsonArray);
consolidatedList.add(generalItem);
}
}
adapter = new AttendanceAdapter(this, consolidatedList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
attn_report_view.setLayoutManager(layoutManager);
attn_report_view.setAdapter(adapter);
}
private HashMap<String, List<Attendance_Data>>
groupDataIntoHashMap(List<Attendance_Data> listOfPojosOfJsonArray) {
HashMap<String, List<Attendance_Data>> groupedHashMap = new HashMap<>
();
for (Attendance_Data pojoOfJsonArray : listOfPojosOfJsonArray) {
String hashMapKey = pojoOfJsonArray.getDate();
if (groupedHashMap.containsKey(hashMapKey)) {
// The key is already in the HashMap; add the pojo object
// against the existing key.
groupedHashMap.get(hashMapKey).add(pojoOfJsonArray);
} else {
List<Attendance_Data> list = new ArrayList<>();
list.add(pojoOfJsonArray);
groupedHashMap.put(hashMapKey, list);
}
}
return groupedHashMap;
}
I want to add multiple items of same date in same single single card view but instead it is creating multiple Card View for multiple items of same date
You have to use RecyclerView Multiple ViewTypes. for detail please check this example.
Also visit this example.
Yeah I found the solution it worked perfect for Me.....we
have to just make changes to the card View by removing
spaces..
.
like this below...
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardMaxElevation="0.1dp"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:background="#303030"
card_view:cardElevation="5dp"
android:foreground="?android:attr/selectableItemBackground"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginLeft="#dimen/dp_2"
android:layout_marginRight="#dimen/dp_2">
<...Your All Text Boxes and further Layout inside this
cardView...>
</android.support.v7.widget.CardView>
and I have add Header for each CardView....and it looks like
this
Outout is shown in below image
Using Spark 1.6 and the ML library I am saving the results of a trained RandomForestClassificationModel using toDebugString():
val rfModel = model.stages(2).asInstanceOf[RandomForestClassificationModel]
val stringModel =rfModel.toDebugString
//save stringModel into a file in the driver in format .txt
So my idea is that in the future read the file .txt and load the trained randomForest, is it possible?
thanks!
That won't work. ToDebugString is merely a debug info to understand how it's got calculated.
If you want to keep this thing for later use, you can do the same we do, which is (although we are in pure java) simply serialise RandomForestModel object. There might be version incompatibilities with default java serialisation, so we use Hessian to do it. It worked through versions update - we started with spark 1.6.1 and it still works with spark 2.0.2.
If you're ok with not sticking to ml, juste use mllib's implementation: the RandomForestModel you get with mllib has a save function.
At least for Spark 2.1.0 you can do this with the following Java (sorry - no Scala) code. However, it may not be the smartest idea to rely on an undocumented format that may change without notice.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.nio.charset.StandardCharsets.US_ASCII;
/**
* RandomForest.
*/
public abstract class RandomForest {
private static final Logger LOG = LoggerFactory.getLogger(RandomForest.class);
protected final List<Node> trees = new ArrayList<>();
/**
* #param model model file (format is Spark's RandomForestClassificationModel toDebugString())
* #throws IOException
*/
public RandomForest(final URL model) throws IOException {
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(model.openStream(), US_ASCII))) {
Node node;
while ((node = load(reader)) != null) {
trees.add(node);
}
}
if (trees.isEmpty()) throw new IOException("Failed to read trees from " + model);
if (LOG.isDebugEnabled()) LOG.debug("Found " + trees.size() + " trees.");
}
private static Node load(final BufferedReader reader) throws IOException {
final Pattern ifPattern = Pattern.compile("If \\(feature (\\d+) (in|not in|<=|>) (.*)\\)");
final Pattern predictPattern = Pattern.compile("Predict: (\\d+\\.\\d+(E-\\d+)?)");
Node root = null;
final List<Node> stack = new ArrayList<>();
String line;
while ((line = reader.readLine()) != null) {
final String trimmed = line.trim();
//System.out.println(trimmed);
if (trimmed.startsWith("RandomForest")) {
// skip the "Tree 1" line
reader.readLine();
} else if (trimmed.startsWith("Tree")) {
break;
} else if (trimmed.startsWith("If")) {
// extract feature index
final Matcher m = ifPattern.matcher(trimmed);
m.matches();
final int featureIndex = Integer.parseInt(m.group(1));
final String operator = m.group(2);
final String operand = m.group(3);
final Predicate<Float> predicate;
if ("<=".equals(operator)) {
predicate = new LessOrEqual(Float.parseFloat(operand));
} else if (">".equals(operator)) {
predicate = new Greater(Float.parseFloat(operand));
} else if ("in".equals(operator)) {
predicate = new In(parseFloatArray(operand));
} else if ("not in".equals(operator)) {
predicate = new NotIn(parseFloatArray(operand));
} else {
predicate = null;
}
final Node node = new Node(featureIndex, predicate);
if (stack.isEmpty()) {
root = node;
} else {
insert(stack, node);
}
stack.add(node);
} else if (trimmed.startsWith("Predict")) {
final Matcher m = predictPattern.matcher(trimmed);
m.matches();
final Object node = Float.parseFloat(m.group(1));
insert(stack, node);
}
}
return root;
}
private static void insert(final List<Node> stack, final Object node) {
Node parent = stack.get(stack.size() - 1);
while (parent.getLeftChild() != null && parent.getRightChild() != null) {
stack.remove(stack.size() - 1);
parent = stack.get(stack.size() - 1);
}
if (parent.getLeftChild() == null) parent.setLeftChild(node);
else parent.setRightChild(node);
}
private static float[] parseFloatArray(final String set) {
final StringTokenizer st = new StringTokenizer(set, "{,}");
final float[] floats = new float[st.countTokens()];
for (int i=0; st.hasMoreTokens(); i++) {
floats[i] = Float.parseFloat(st.nextToken());
}
return floats;
}
public abstract float predict(final float[] features);
public String toDebugString() {
try {
final StringWriter sw = new StringWriter();
for (int i=0; i<trees.size(); i++) {
sw.write("Tree " + i + ":\n");
print(sw, "", trees.get(0));
}
return sw.toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static void print(final Writer w, final String indent, final Object object) throws IOException {
if (object instanceof Number) {
w.write(indent + "Predict: " + object + "\n");
} else if (object instanceof Node) {
final Node node = (Node) object;
// left node
w.write(indent + node + "\n");
print(w, indent + " ", node.getLeftChild());
w.write(indent + "Else\n");
print(w, indent + " ", node.getRightChild());
}
}
#Override
public String toString() {
return getClass().getSimpleName() + "{numTrees=" + trees.size() + "}";
}
/**
* Node.
*/
protected static class Node {
private final int featureIndex;
private final Predicate<Float> predicate;
private Object leftChild;
private Object rightChild;
public Node(final int featureIndex, final Predicate<Float> predicate) {
Objects.requireNonNull(predicate);
this.featureIndex = featureIndex;
this.predicate = predicate;
}
public void setLeftChild(final Object leftChild) {
this.leftChild = leftChild;
}
public void setRightChild(final Object rightChild) {
this.rightChild = rightChild;
}
public Object getLeftChild() {
return leftChild;
}
public Object getRightChild() {
return rightChild;
}
public Object eval(final float[] features) {
Object result = this;
do {
final Node node = (Node)result;
result = node.predicate.test(features[node.featureIndex]) ? node.leftChild : node.rightChild;
} while (result instanceof Node);
return result;
}
#Override
public String toString() {
return "If (feature " + featureIndex + " " + predicate + ")";
}
}
private static class LessOrEqual implements Predicate<Float> {
private final float value;
public LessOrEqual(final float value) {
this.value = value;
}
#Override
public boolean test(final Float f) {
return f <= value;
}
#Override
public String toString() {
return "<= " + value;
}
}
private static class Greater implements Predicate<Float> {
private final float value;
public Greater(final float value) {
this.value = value;
}
#Override
public boolean test(final Float f) {
return f > value;
}
#Override
public String toString() {
return "> " + value;
}
}
private static class In implements Predicate<Float> {
private final float[] array;
public In(final float[] array) {
this.array = array;
}
#Override
public boolean test(final Float f) {
for (int i=0; i<array.length; i++) {
if (array[i] == f) return true;
}
return false;
}
#Override
public String toString() {
return "in " + Arrays.toString(array);
}
}
private static class NotIn implements Predicate<Float> {
private final float[] array;
public NotIn(final float[] array) {
this.array = array;
}
#Override
public boolean test(final Float f) {
for (int i=0; i<array.length; i++) {
if (array[i] == f) return false;
}
return true;
}
#Override
public String toString() {
return "not in " + Arrays.toString(array);
}
}
}
To use the class for classification, use:
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* RandomForestClassifier.
*/
public class RandomForestClassifier extends RandomForest {
public RandomForestClassifier(final URL model) throws IOException {
super(model);
}
#Override
public float predict(final float[] features) {
final Map<Object, Integer> counts = new HashMap<>();
trees.stream().map(node -> node.eval(features))
.forEach(result -> {
Integer count = counts.get(result);
if (count == null) {
counts.put(result, 1);
} else {
counts.put(result, count + 1);
}
});
return (Float)counts.entrySet()
.stream()
.sorted((o1, o2) -> Integer.compare(o2.getValue(), o1.getValue()))
.map(Map.Entry::getKey)
.findFirst().get();
}
}
For regression:
import java.io.IOException;
import java.net.URL;
/**
* RandomForestRegressor.
*/
public class RandomForestRegressor extends RandomForest {
public RandomForestRegressor(final URL model) throws IOException {
super(model);
}
#Override
public float predict(final float[] features) {
return (float)trees
.stream()
.mapToDouble(node -> ((Number)node.eval(features)).doubleValue())
.average()
.getAsDouble();
}
}
I'm trying to implement pagination for a project that loads a large set of data from the database.
I've done a lot of searching on the internet already to get db-pagination to work, but for some reason I still don't get it working the way I want.
I've followed the example as described in this topic:
JSF, RichFaces, pagination
The data is loaded, so that works; cache also seems to work. However, it seems to still load all the data. The sr.getRows() in the walk-method is always -1, so the call to the database also uses -1 for maxResults. I get all my data, but no pagination.
I don't want to introduce another dependency if I can avoid it.
Some of my data:
BatchDataModel
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> {
private SequenceRange cachedRange;
private Integer cachedRowCount;
private List<T> cachedList;
private Object rowKey;
public abstract List<T> getDataList(int firstRow, int numRows);
public abstract Object getKey(T t);
public abstract int getTotalCount();
#Override
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument) {
SequenceRange sr = (SequenceRange) range;
if (cachedList == null || !equalRanges(cachedRange, sr)) {
cachedList = getDataList(sr.getFirstRow(), sr.getRows());
cachedRange = sr;
}
for (T t : cachedList) {
if (getKey(t) == null) {
/*
* the 2nd param is used to build the client id of the table
* row, i.e. mytable:234:inputname, so don't let it be null.
*/
throw new IllegalStateException("found null key");
}
dv.process(ctx, getKey(t), argument);
}
}
/*
* The rowKey is the id from getKey, presumably obtained from
* dv.process(...).
*/
#Override
public void setRowKey(Object rowKey) {
this.rowKey = rowKey;
}
#Override
public Object getRowKey() {
return rowKey;
}
#Override
public boolean isRowAvailable() {
return (getRowData() != null);
}
#Override
public int getRowCount() {
if (cachedRowCount == null) {
cachedRowCount = getTotalCount();
}
return cachedRowCount;
}
#Override
public T getRowData() {
for (T t : cachedList) {
if (getKey(t).equals(this.getRowKey())) {
return t;
}
}
return null;
}
protected static boolean equalRanges(SequenceRange range1, SequenceRange range2) {
if (range1 == null || range2 == null) {
return range1 == null && range2 == null;
} else {
return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows();
}
}
/*
* get/setRowIndex are used when doing multiple select in an
* extendedDataTable, apparently. Not tested. Actually, the get method is
* used when using iterationStatusVar="it" & #{it.index}.
*/
#Override
public int getRowIndex() {
if (cachedList != null) {
ListIterator<T> it = cachedList.listIterator();
while (it.hasNext()) {
T t = it.next();
if (getKey(t).equals(this.getRowKey())) {
return it.previousIndex() + cachedRange.getFirstRow();
}
}
}
return -1;
}
#Override
public void setRowIndex(int rowIndex) {
int upperBound = cachedRange.getFirstRow() + cachedRange.getRows();
if (rowIndex >= cachedRange.getFirstRow() && rowIndex < upperBound) {
int index = rowIndex % cachedRange.getRows();
T t = cachedList.get(index);
setRowKey(getKey(t));
}
}
#Override
public Object getWrappedData() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void setWrappedData(Object data) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<T> getCachedList() {
return cachedList;
}
Bean (part)
private ListState state;
private BatchDataModel<Batch> model;
public BatchDataModel<Batch> getModel(){
return model;
}
public int getCurrentPage() {
return state.getPage();
}
public void setCurrentPage(int page) {
state.setPage(page);
}
public void setBatchService(BatchService batchService) {
this.batchService = batchService;
}
/**
* Initialize the variables, before the page is shown.
*/
#PostConstruct
private void init() {
filter = new Filter();
sorter = new Sorter();
state = getFromSession("batchList", null);
if (state == null) {
state = new ListState();
storeInSession("batchList", state);
}
}
public void loadBatches(boolean search) {
BatchDataModel<Batch> model = new BatchDataModel<Batch>(){
#Override
public List<Batch> getDataList(int firstRow, int numRows) {
try {
List <Batch> test;
test = batchService.selectBatches(userBean.getUser(), firstRow, numRows);
return test;
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return null;
}
}
#Override
public Object getKey(Batch batch) {
return batch.getBatchId();
}
#Override
public int getTotalCount() {
try {
return batchService.countBatches(userBean.getUser());
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return 0;
}
}
};
}
xhtml (part)
<rich:dataTable id="batchesTable" rows="2"
value="#{batchBean.model}" var="batch" first="#{batchBean.currentPage}"
styleClass="table" rowClasses="odd-row, even-row"
onrowmouseover="this.style.backgroundColor='#88B5F9'"
onrowmouseout="this.style.backgroundColor='#{a4jSkin.rowBackgroundColor}'">
(...)
<f:facet name="footer">
<rich:dataScroller page="#{batchBean.currentPage}" />
</f:facet>
ArrangeableModel is the key. This class needs to be implemented in the BatchDataModel class, together with a method and function. This way the same state is used and the walk-method gets the correct values in SequenceRange.
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> implements Arrangeable {
private ArrangeableState arrangeableState;
public void arrange(FacesContext context, ArrangeableState state) {
arrangeableState = state;
}
protected ArrangeableState getArrangeableState() {
return arrangeableState;
}
}