1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.primefaces.extensions.component.sheet;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30
31 import javax.el.ELContext;
32 import javax.el.ValueExpression;
33 import javax.faces.application.FacesMessage;
34 import javax.faces.application.ResourceDependencies;
35 import javax.faces.application.ResourceDependency;
36 import javax.faces.component.UIComponent;
37 import javax.faces.context.FacesContext;
38 import javax.faces.convert.Converter;
39 import javax.faces.convert.ConverterException;
40 import javax.faces.event.AjaxBehaviorEvent;
41 import javax.faces.event.FacesEvent;
42
43 import org.apache.commons.lang3.StringUtils;
44 import org.primefaces.PrimeFaces;
45 import org.primefaces.extensions.event.SheetEvent;
46 import org.primefaces.extensions.model.sheet.SheetRowColIndex;
47 import org.primefaces.extensions.model.sheet.SheetUpdate;
48 import org.primefaces.extensions.util.JavascriptVarBuilder;
49 import org.primefaces.model.BeanPropertyComparator;
50 import org.primefaces.model.SortOrder;
51 import org.primefaces.util.ComponentUtils;
52 import org.primefaces.util.Constants;
53 import org.primefaces.util.LangUtils;
54
55
56
57
58
59
60
61 @ResourceDependencies({@ResourceDependency(library = "primefaces", name = "components.css"),
62 @ResourceDependency(library = "primefaces", name = "jquery/jquery.js"),
63 @ResourceDependency(library = "primefaces", name = "core.js"),
64 @ResourceDependency(library = "primefaces", name = "components.js"),
65 @ResourceDependency(library = "primefaces-extensions", target = "head", name = "sheet/sheet.css"),
66 @ResourceDependency(library = "primefaces-extensions", name = "sheet/sheet.js")})
67 public class Sheet extends SheetBase {
68
69 public static final String EVENT_CELL_SELECT = "cellSelect";
70 public static final String EVENT_CHANGE = "change";
71 public static final String EVENT_SORT = "sort";
72 public static final String EVENT_FILTER = "filter";
73 public static final String EVENT_COLUMN_SELECT = "columnSelect";
74 public static final String EVENT_ROW_SELECT = "rowSelect";
75
76 public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.Sheet";
77
78 private static final Collection<String> EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList(EVENT_CHANGE,
79 EVENT_CELL_SELECT, EVENT_SORT, EVENT_FILTER, EVENT_COLUMN_SELECT, EVENT_ROW_SELECT));
80
81
82
83
84 private List<SheetColumn> columns;
85
86
87
88
89 private List<SheetInvalidUpdate> invalidUpdates;
90
91
92
93
94 private Map<SheetRowColIndex, String> submittedValues = new HashMap<>();
95
96
97
98
99 private Map<SheetRowColIndex, Object> localValues = new HashMap<>();
100
101
102
103
104 private String selection;
105
106
107
108
109 private String focusId;
110
111
112
113
114 private final List<SheetUpdate> updates = new ArrayList<>();
115
116
117
118
119
120 private Map<Integer, Integer> columnMapping;
121
122
123
124
125 private Map<String, Object> rowMap;
126
127
128
129
130 private Map<String, Integer> rowNumbers;
131
132 @Override
133 public String getFamily() {
134 return COMPONENT_FAMILY;
135 }
136
137
138
139
140 @Override
141 public Collection<String> getEventNames() {
142 return EVENT_NAMES;
143 }
144
145 @Override
146 public String getDefaultEventName() {
147 return EVENT_CHANGE;
148 }
149
150
151
152
153 @Override
154 public void queueEvent(final FacesEvent event) {
155 final FacesContext fc = FacesContext.getCurrentInstance();
156
157 if (isSelfRequest(fc) && event instanceof AjaxBehaviorEvent) {
158 final AjaxBehaviorEvent behaviorEvent = (AjaxBehaviorEvent) event;
159 final SheetEventheetEvent.html#SheetEvent">SheetEvent sheetEvent = new SheetEvent(this, behaviorEvent.getBehavior());
160 sheetEvent.setPhaseId(event.getPhaseId());
161 super.queueEvent(sheetEvent);
162 return;
163 }
164
165 super.queueEvent(event);
166 }
167
168 private boolean isSelfRequest(final FacesContext context) {
169 return this.getClientId(context).equals(context.getExternalContext().getRequestParameterMap()
170 .get(Constants.RequestParams.PARTIAL_SOURCE_PARAM));
171 }
172
173
174
175
176
177
178 public List<SheetColumn> getColumns() {
179 if (columns == null) {
180 columns = new ArrayList<>();
181 getColumns(this);
182 }
183 return columns;
184 }
185
186
187
188
189
190
191 private void getColumns(final UIComponent parent) {
192 for (final UIComponent child : parent.getChildren()) {
193 if (child instanceof SheetColumn) {
194 columns.add((SheetColumn) child);
195 }
196 }
197 }
198
199
200
201
202
203
204 public void setColumns(final List<SheetColumn> columns) {
205 this.columns = columns;
206 }
207
208
209
210
211
212
213 public List<SheetInvalidUpdate> getInvalidUpdates() {
214 if (invalidUpdates == null) {
215 invalidUpdates = new ArrayList<>();
216 }
217 return invalidUpdates;
218 }
219
220
221
222
223 public void resetSubmitted() {
224 submittedValues.clear();
225 updates.clear();
226 }
227
228
229
230
231 public void resetSort() {
232
233 getStateHelper().put(PropertyKeys.currentSortBy.name(), null);
234
235 final String origSortOrder = (String) getStateHelper().get(PropertyKeys.origSortOrder);
236 if (origSortOrder != null) {
237 setSortOrder(origSortOrder);
238 }
239 }
240
241
242
243
244 public void resetInvalidUpdates() {
245 getInvalidUpdates().clear();
246 }
247
248
249
250
251 public void reset() {
252 resetSubmitted();
253 resetSort();
254 resetInvalidUpdates();
255 localValues.clear();
256 for (final SheetColumn c : getColumns()) {
257 c.setFilterValue(null);
258 }
259 }
260
261
262
263
264
265
266
267
268
269 public void setSubmittedValue(final FacesContext context, final String rowKey, final int col, final String value) {
270 submittedValues.put(new SheetRowColIndex(rowKey, col), value);
271 }
272
273
274
275
276
277
278
279
280 public String getSubmittedValue(final String rowKey, final int col) {
281 return submittedValues.get(new SheetRowColIndex(rowKey, col));
282 }
283
284
285
286
287
288
289
290
291 public void setLocalValue(final String rowKey, final int col, final Object value) {
292 localValues.put(new SheetRowColIndex(rowKey, col), value);
293 }
294
295
296
297
298
299
300
301
302 public Object getLocalValue(final String rowKey, final int col) {
303 return localValues.get(new SheetRowColIndex(rowKey, col));
304 }
305
306
307
308
309
310
311
312 public void setRowVar(final FacesContext context, final String rowKey) {
313
314 if (context == null) {
315 return;
316 }
317
318 if (rowKey == null) {
319 context.getExternalContext().getRequestMap().remove(getVar());
320 }
321 else {
322 final Object value = getRowMap().get(rowKey);
323 context.getExternalContext().getRequestMap().put(getVar(), value);
324 }
325 }
326
327 protected Map<String, Object> getRowMap() {
328 if (rowMap == null || rowMap.isEmpty()) {
329 remapRows();
330 }
331 return rowMap;
332 }
333
334
335
336
337
338
339
340
341
342 public Object getValueForCell(final FacesContext context, final String rowKey, final int col) {
343
344
345 final SheetRowColIndexeet/SheetRowColIndex.html#SheetRowColIndex">SheetRowColIndex index = new SheetRowColIndex(rowKey, col);
346 if (localValues.containsKey(index)) {
347 return localValues.get(index);
348 }
349
350 setRowVar(context, rowKey);
351 final SheetColumn column = getColumns().get(col);
352 return column.getValueExpression("value").getValue(context.getELContext());
353 }
354
355
356
357
358
359
360
361
362
363 public String getRenderValueForCell(final FacesContext context, final String rowKey, final int col) {
364
365
366
367 final SheetRowColIndexeet/SheetRowColIndex.html#SheetRowColIndex">SheetRowColIndex index = new SheetRowColIndex(rowKey, col);
368 if (submittedValues.containsKey(index)) {
369 return submittedValues.get(index);
370 }
371
372 final Object value = getValueForCell(context, rowKey, col);
373 if (value == null) {
374 return null;
375 }
376
377 final SheetColumn column = getColumns().get(col);
378 final Converter converter = ComponentUtils.getConverter(context, column);
379 if (converter == null) {
380 return value.toString();
381 }
382 else {
383 return converter.getAsString(context, this, value);
384 }
385 }
386
387
388
389
390
391
392
393 protected String getRowHeaderValueAsString(final FacesContext context) {
394 final ValueExpression veRowHeader = getRowHeaderValueExpression();
395 final Object value = veRowHeader.getValue(context.getELContext());
396 if (value == null) {
397 return Constants.EMPTY_STRING;
398 }
399 else {
400 return value.toString();
401 }
402 }
403
404
405
406
407
408
409 public List<Object> getSortedValues() {
410 List<Object> filtered = getFilteredValue();
411 if (filtered == null || filtered.isEmpty()) {
412 filtered = sortAndFilter();
413 }
414 return filtered;
415 }
416
417
418
419
420
421
422 public int getSortColRenderIndex() {
423
424 String currentSortById = (String) getStateHelper().get(PropertyKeys.currentSortBy.name());
425
426 if (StringUtils.isEmpty(currentSortById)) {
427 final Object sortBy = getStateHelper().eval(PropertyKeys.sortBy.name());
428 if (sortBy instanceof String) {
429 currentSortById = (String) sortBy;
430 }
431 }
432 if (StringUtils.isNotEmpty(currentSortById)) {
433 int colIdx = 0;
434 for (final SheetColumn column : getColumns()) {
435 if (!column.isRendered()) {
436 continue;
437 }
438
439 if (currentSortById.equals(column.getId())) {
440 return colIdx;
441 }
442 colIdx++;
443 }
444 }
445
446
447
448 final ValueExpression veSortBy = getValueExpression(PropertyKeys.sortBy.name());
449 if (veSortBy == null) {
450 return -1;
451 }
452
453 final String sortByExp = veSortBy.getExpressionString();
454 int colIdx = 0;
455 for (final SheetColumn column : getColumns()) {
456 if (!column.isRendered()) {
457 continue;
458 }
459
460 final ValueExpression veCol = column.getValueExpression(PropertyKeys.sortBy.name());
461 if (veCol != null) {
462 if (veCol.getExpressionString().equals(sortByExp)) {
463 return colIdx;
464 }
465 }
466 colIdx++;
467 }
468 return -1;
469 }
470
471
472
473
474
475
476
477
478
479
480 protected boolean matchesFilter(final Object obj) {
481 for (final SheetColumn col : getColumns()) {
482 final String filterValue = col.getFilterValue();
483 if (LangUtils.isValueBlank(filterValue)) {
484 continue;
485 }
486
487 final Object filterBy = col.getFilterBy();
488
489 if (filterBy == null) {
490 return false;
491 }
492
493 String filterMatchMode = col.getFilterMatchMode();
494 if (LangUtils.isValueBlank(filterMatchMode)) {
495 filterMatchMode = "contains";
496 }
497
498
499 final String value = filterBy.toString().toLowerCase();
500 final String filter = filterValue.toLowerCase();
501 switch (filterMatchMode) {
502 case "startsWith":
503 if (!value.startsWith(filter)) {
504 return false;
505 }
506 break;
507 case "endsWith":
508 if (!value.endsWith(filter)) {
509 return false;
510 }
511 break;
512 case "exact":
513 if (!value.equals(filter)) {
514 return false;
515 }
516 break;
517 default:
518
519 if (!value.contains(filter)) {
520 return false;
521 }
522 }
523 }
524 return true;
525 }
526
527
528
529
530 public List<Object> sortAndFilter() {
531 final List filteredList = getFilteredValue();
532 filteredList.clear();
533 rowMap = new HashMap<>();
534 rowNumbers = new HashMap<>();
535
536 final Collection<?> values = (Collection<?>) getValue();
537 if (values == null || values.isEmpty()) {
538 return filteredList;
539 }
540
541 remapRows();
542
543 boolean filters = false;
544 for (final SheetColumn col : getColumns()) {
545 if (!LangUtils.isValueBlank(col.getFilterValue())) {
546 filters = true;
547 break;
548 }
549 }
550
551 final FacesContext context = FacesContext.getCurrentInstance();
552 final Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
553 final String var = getVar();
554
555 if (filters) {
556
557 for (final Object obj : values) {
558 requestMap.put(var, obj);
559 if (matchesFilter(obj)) {
560 filteredList.add(obj);
561 }
562 }
563 }
564 else {
565 filteredList.addAll(values);
566 }
567
568
569 final int sortByIdx = getSortColRenderIndex();
570 final SheetColumn currentSortByColumn = sortByIdx >= 0 ? getColumns().get(sortByIdx) : null;
571 final ValueExpression currentSortByVe = currentSortByColumn != null ? currentSortByColumn.getValueExpression(
572 PropertyKeys.sortBy.name()) : null;
573 final ValueExpression veSortBy;
574 if (currentSortByVe != null) {
575 veSortBy = currentSortByVe;
576 }
577 else {
578 veSortBy = getValueExpression(PropertyKeys.sortBy.name());
579 }
580 if (veSortBy != null) {
581 Collections.sort(filteredList, new BeanPropertyComparator(veSortBy, var, convertSortOrder(), null,
582 isCaseSensitiveSort(), Locale.ENGLISH, getNullSortOrder()));
583 }
584
585
586 remapFilteredList(filteredList);
587 return filteredList;
588 }
589
590
591
592
593 protected void remapFilteredList(final List filteredList) {
594 rowNumbers = new HashMap<>(rowMap.size());
595 final FacesContext context = FacesContext.getCurrentInstance();
596 final Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
597 final String var = getVar();
598 int row = 0;
599 for (final Object value : filteredList) {
600 requestMap.put(var, value);
601 rowNumbers.put(getRowKeyValueAsString(context), Integer.valueOf(row));
602 row++;
603 }
604 requestMap.remove(var);
605 }
606
607
608
609
610 protected void remapRows() {
611 rowMap = new HashMap<>();
612 final FacesContext context = FacesContext.getCurrentInstance();
613 final Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
614 final Collection<?> values = (Collection<?>) getValue();
615 final String var = getVar();
616 for (final Object obj : values) {
617 requestMap.put(var, obj);
618 try {
619 final String key = getRowKeyValueAsString(context);
620 rowMap.put(key, obj);
621 }
622 finally {
623 requestMap.remove(var);
624 }
625 }
626 }
627
628
629
630
631
632
633
634 @Override
635 protected Object getRowKeyValue(final FacesContext context) {
636 final ValueExpression veRowKey = getValueExpression(PropertyKeys.rowKey.name());
637 if (veRowKey == null) {
638 throw new RuntimeException("RowKey required on sheet!");
639 }
640 final Object value = veRowKey.getValue(context.getELContext());
641 if (value == null) {
642 throw new RuntimeException("RowKey must resolve to non-null value for updates to work properly");
643 }
644 return value;
645 }
646
647
648
649
650
651
652
653 protected String getRowKeyValueAsString(final Object key) {
654 final String result = key.toString();
655 return "r_" + StringUtils.deleteWhitespace(result);
656 }
657
658
659
660
661
662
663
664 protected String getRowKeyValueAsString(final FacesContext context) {
665 return getRowKeyValueAsString(getRowKeyValue(context));
666 }
667
668
669
670
671
672
673 protected SortOrder convertSortOrder() {
674 final String sortOrder = getSortOrder();
675 if (sortOrder == null) {
676 return SortOrder.UNSORTED;
677 }
678 else {
679 final SortOrder result = SortOrder.valueOf(sortOrder.toUpperCase(Locale.ENGLISH));
680 return result;
681 }
682 }
683
684
685
686
687
688 @Override
689 public void validate(final FacesContext context) {
690
691
692
693
694 final Iterator<Entry<SheetRowColIndex, String>> entries = submittedValues.entrySet().iterator();
695 final boolean hadBadUpdates = !getInvalidUpdates().isEmpty();
696 getInvalidUpdates().clear();
697 while (entries.hasNext()) {
698 final Entry<SheetRowColIndex, String> entry = entries.next();
699 final SheetColumn column = getColumns().get(entry.getKey().getColIndex());
700 final String newValue = entry.getValue();
701 final String rowKey = entry.getKey().getRowKey();
702 final int col = entry.getKey().getColIndex();
703 setRowVar(context, rowKey);
704
705
706
707 final Converter converter = ComponentUtils.getConverter(context, column);
708
709
710 Object newValueObj = newValue;
711 if (converter != null) {
712 try {
713 newValueObj = converter.getAsObject(context, this, newValue);
714 }
715 catch (final ConverterException e) {
716
717
718
719 setValid(false);
720 FacesMessage message = e.getFacesMessage();
721 if (message == null) {
722 message = new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage());
723 }
724 context.addMessage(this.getClientId(context), message);
725
726 final String messageText = message.getDetail();
727 getInvalidUpdates()
728 .add(new SheetInvalidUpdate(getRowKeyValue(context), col, column, newValue, messageText));
729 continue;
730 }
731 }
732
733
734
735 setLocalValue(rowKey, col, newValueObj);
736
737
738 column.setValue(newValueObj);
739 try {
740 column.validate(context);
741 }
742 finally {
743 column.resetValue();
744 }
745
746 entries.remove();
747 }
748 setRowVar(context, null);
749
750 final boolean newBadUpdates = !getInvalidUpdates().isEmpty();
751 final String errorMessage = getErrorMessage();
752
753 if (hadBadUpdates || newBadUpdates) {
754
755 if (context.getPartialViewContext().isPartialRequest()) {
756 renderBadUpdateScript(context);
757 }
758 }
759
760 if (newBadUpdates && errorMessage != null) {
761 final FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, errorMessage);
762 context.addMessage(null, message);
763 }
764 }
765
766
767
768
769
770
771 @Override
772 public void updateModel(final FacesContext context) {
773 final Iterator<Entry<SheetRowColIndex, Object>> entries = localValues.entrySet().iterator();
774
775
776 final HashSet<String> dirtyRows = new HashSet<>();
777 while (entries.hasNext()) {
778 final Entry<SheetRowColIndex, Object> entry = entries.next();
779
780 final Object newValue = entry.getValue();
781 final String rowKey = entry.getKey().getRowKey();
782 final int col = entry.getKey().getColIndex();
783 final SheetColumn column = getColumns().get(col);
784 setRowVar(context, rowKey);
785 final Object rowVal = rowMap.get(rowKey);
786
787 final ValueExpression ve = column.getValueExpression(PropertyKeys.value.name());
788 final ELContext elContext = context.getELContext();
789 final Object oldValue = ve.getValue(elContext);
790 ve.setValue(elContext, newValue);
791 entries.remove();
792 appendUpdateEvent(getRowKeyValue(context), col, rowVal, oldValue, newValue);
793 dirtyRows.add(rowKey);
794 }
795 setLocalValueSet(false);
796 setRowVar(context, null);
797
798 if (context.getPartialViewContext().isPartialRequest()) {
799 renderRowUpdateScript(context, dirtyRows);
800 }
801 }
802
803
804
805
806 @Override
807 public Object saveState(final FacesContext context) {
808 final Object values[] = new Object[8];
809 values[0] = super.saveState(context);
810 values[1] = submittedValues;
811 values[2] = localValues;
812 values[3] = invalidUpdates;
813 values[4] = columnMapping;
814 values[5] = getFilteredValue();
815 values[6] = rowMap;
816 values[7] = rowNumbers;
817 return values;
818 }
819
820
821
822
823 @Override
824 public void restoreState(final FacesContext context, final Object state) {
825 if (state == null) {
826 return;
827 }
828
829 final Object values[] = (Object[]) state;
830 super.restoreState(context, values[0]);
831 final Object restoredSubmittedValues = values[1];
832 final Object restoredLocalValues = values[2];
833 final Object restoredInvalidUpdates = values[3];
834 final Object restoredColMappings = values[4];
835 final Object restoredSortedList = values[5];
836 final Object restoredRowMap = values[6];
837 final Object restoredRowNumbers = values[7];
838
839 if (restoredSubmittedValues == null) {
840 submittedValues.clear();
841 }
842 else {
843 submittedValues = (Map<SheetRowColIndex, String>) restoredSubmittedValues;
844 }
845
846 if (restoredLocalValues == null) {
847 localValues.clear();
848 }
849 else {
850 localValues = (Map<SheetRowColIndex, Object>) restoredLocalValues;
851 }
852
853 if (restoredInvalidUpdates == null) {
854 getInvalidUpdates().clear();
855 }
856 else {
857 invalidUpdates = (List<SheetInvalidUpdate>) restoredInvalidUpdates;
858 }
859
860 if (restoredColMappings == null) {
861 columnMapping = null;
862 }
863 else {
864 columnMapping = (Map<Integer, Integer>) restoredColMappings;
865 }
866
867 if (restoredSortedList == null) {
868 getFilteredValue().clear();
869 }
870 else {
871 setFilteredValue((List<Object>) restoredSortedList);
872 }
873
874 if (restoredRowMap == null) {
875 rowMap = null;
876 }
877 else {
878 rowMap = (Map<String, Object>) restoredRowMap;
879 }
880
881 if (restoredRowNumbers == null) {
882 rowNumbers = null;
883 }
884 else {
885 rowNumbers = (Map<String, Integer>) restoredRowNumbers;
886 }
887 }
888
889
890
891
892
893
894 public String getSelection() {
895 return selection;
896 }
897
898
899
900
901
902
903 public void setSelection(final String selection) {
904 this.selection = selection;
905 }
906
907
908
909
910
911 @Override
912 public Object getSubmittedValue() {
913 if (submittedValues.isEmpty()) {
914 return null;
915 }
916 else {
917 return submittedValues;
918 }
919 }
920
921
922
923
924
925 @Override
926 public void setSubmittedValue(final Object submittedValue) {
927 if (submittedValue == null) {
928 submittedValues.clear();
929 }
930 else {
931 submittedValues = (Map<SheetRowColIndex, String>) submittedValue;
932 }
933
934 }
935
936
937
938
939
940
941 public List<SheetUpdate> getUpdates() {
942 return updates;
943 }
944
945
946
947
948
949
950 public boolean isHasStyledCells() {
951 for (final SheetColumn column : getColumns()) {
952 if (column.getStyleClass() != null) {
953 return true;
954 }
955 }
956 return false;
957 }
958
959
960
961
962
963
964
965 public int getMappedColumn(final int renderCol) {
966 if (columnMapping == null || renderCol == -1) {
967 return renderCol;
968 }
969 else {
970 final Integer result = columnMapping.get(renderCol);
971 if (result == null) {
972 throw new IllegalArgumentException("Invalid index " + renderCol);
973 }
974 return result;
975 }
976 }
977
978
979
980
981
982
983
984 public int getRenderIndexFromRealIdx(final int realIdx) {
985 if (columnMapping == null || realIdx == -1) {
986 return realIdx;
987 }
988
989 for (final Entry<Integer, Integer> entry : columnMapping.entrySet()) {
990 if (entry.getValue().equals(realIdx)) {
991 return entry.getKey();
992 }
993 }
994
995 return realIdx;
996 }
997
998
999
1000
1001 public void updateColumnMappings() {
1002 columnMapping = new HashMap<>();
1003 int realIdx = 0;
1004 int renderCol = 0;
1005 for (final SheetColumn column : getColumns()) {
1006 if (column.isRendered()) {
1007 columnMapping.put(renderCol, realIdx);
1008 renderCol++;
1009 }
1010 realIdx++;
1011 }
1012 }
1013
1014
1015
1016
1017
1018
1019 public int getRowCount() {
1020 final List<Object> values = getSortedValues();
1021 if (values == null) {
1022 return 0;
1023 }
1024 return values.size();
1025 }
1026
1027
1028
1029
1030
1031
1032 public String getFocusId() {
1033 return focusId;
1034 }
1035
1036
1037
1038
1039
1040
1041 public void setFocusId(final String focusId) {
1042 this.focusId = focusId;
1043 }
1044
1045
1046
1047
1048
1049 public void commitUpdates() {
1050 resetSubmitted();
1051 final FacesContext context = FacesContext.getCurrentInstance();
1052 if (context.getPartialViewContext().isPartialRequest()) {
1053 final StringBuilder eval = new StringBuilder();
1054 final String jsVar = resolveWidgetVar();
1055 eval.append("PF('").append(jsVar).append("')").append(".clearDataInput();");
1056 PrimeFaces.current().executeScript(eval.toString());
1057 }
1058 }
1059
1060
1061
1062
1063
1064
1065 public String getInvalidDataValue() {
1066 final JavascriptVarBuilderscriptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vb = new JavascriptVarBuilder(null, true);
1067 for (final SheetInvalidUpdate sheetInvalidUpdate : getInvalidUpdates()) {
1068 final Object rowKey = sheetInvalidUpdate.getInvalidRowKey();
1069 final int col = getRenderIndexFromRealIdx(sheetInvalidUpdate.getInvalidColIndex());
1070 final String rowKeyProperty = this.getRowKeyValueAsString(rowKey);
1071 vb.appendProperty(rowKeyProperty + "_c" + col,
1072 sheetInvalidUpdate.getInvalidMessage().replace("'", "'"), true);
1073 }
1074 return vb.closeVar().toString();
1075 }
1076
1077
1078
1079
1080
1081
1082
1083 public void renderRowUpdateScript(final FacesContext context, final Set<String> dirtyRows) {
1084 final String jsVar = resolveWidgetVar();
1085 final StringBuilder eval = new StringBuilder();
1086
1087 for (final String rowKey : dirtyRows) {
1088 setRowVar(context, rowKey);
1089 final int rowIndex = rowNumbers.get(rowKey);
1090
1091 final JavascriptVarBuilderiptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsRow = new JavascriptVarBuilder(null, false);
1092 final JavascriptVarBuildertVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsStyle = new JavascriptVarBuilder(null, true);
1093 final JavascriptVarBuilderrBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsReadOnly = new JavascriptVarBuilder(null, true);
1094 int renderCol = 0;
1095 for (int col = 0; col < getColumns().size(); col++) {
1096 final SheetColumn column = getColumns().get(col);
1097 if (!column.isRendered()) {
1098 continue;
1099 }
1100
1101
1102 final String value = getRenderValueForCell(context, rowKey, col);
1103 jsRow.appendArrayValue(value, true);
1104
1105
1106 final String styleClass = column.getStyleClass();
1107 if (styleClass != null) {
1108 jsStyle.appendRowColProperty(rowIndex, renderCol, styleClass, true);
1109 }
1110
1111
1112 final boolean readOnly = column.isReadonlyCell();
1113 if (readOnly) {
1114 jsReadOnly.appendRowColProperty(rowIndex, renderCol, "true", true);
1115 }
1116 renderCol++;
1117 }
1118 eval.append("PF('").append(jsVar).append("')");
1119 eval.append(".updateData('");
1120 eval.append(rowIndex);
1121 eval.append("',");
1122 eval.append(jsRow.closeVar().toString());
1123 eval.append(",");
1124 eval.append(jsStyle.closeVar().toString());
1125 eval.append(",");
1126 eval.append(jsReadOnly.closeVar().toString());
1127 eval.append(");");
1128 }
1129 eval.append("PF('").append(jsVar).append("')").append(".redraw();");
1130 PrimeFaces.current().executeScript(eval.toString());
1131 }
1132
1133
1134
1135
1136
1137
1138 public void renderBadUpdateScript(final FacesContext context) {
1139 final String widgetVar = resolveWidgetVar();
1140 final String invalidValue = getInvalidDataValue();
1141 StringBuilder sb = new StringBuilder("PF('" + widgetVar + "')");
1142 sb.append(".cfg.errors=");
1143 sb.append(invalidValue);
1144 sb.append(";");
1145 sb.append("PF('" + widgetVar + "')");
1146 sb.append(".ht.render();");
1147 PrimeFaces.current().executeScript(sb.toString());
1148
1149 sb = new StringBuilder();
1150 sb.append("PF('").append(widgetVar).append("')");
1151 sb.append(".sheetDiv.removeClass('ui-state-error')");
1152 if (!getInvalidUpdates().isEmpty()) {
1153 sb.append(".addClass('ui-state-error')");
1154 }
1155 PrimeFaces.current().executeScript(sb.toString());
1156 }
1157
1158
1159
1160
1161 public void appendUpdateEvent(final Object rowKey, final int colIndex, final Object rowData, final Object oldValue,
1162 final Object newValue) {
1163 updates.add(new SheetUpdate(rowKey, colIndex, rowData, oldValue, newValue));
1164 }
1165 }