DefaultFXTableFormat.java
001 /*
002  * Copyright 2014-2016 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *     http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 package griffon.plugins.glazedlists.javafx.gui;
017 
018 import griffon.plugins.glazedlists.ColumnReader;
019 import javafx.beans.value.ObservableValue;
020 
021 import javax.annotation.Nonnull;
022 import java.util.List;
023 import java.util.Map;
024 
025 import static griffon.util.GriffonClassUtils.requireState;
026 import static griffon.util.GriffonNameUtils.getNaturalName;
027 import static griffon.util.GriffonNameUtils.isBlank;
028 import static java.util.Objects.requireNonNull;
029 
030 /**
031  * Defines a read-only {@code FXTableFormat}.
032  *
033  @author Andres Almiray
034  */
035 public class DefaultFXTableFormat<E> implements FXTableFormat<E> {
036     private static final String ERROR_COLUMN_NAMES_NULL = "Argument 'columnNames' must not be null.";
037 
038     protected final String[] columnNames;
039     protected final String[] columnTitles;
040     protected final ColumnReader[] columnReaders;
041     protected final TableCellFactory[] tableCellFactories;
042 
043     private static final String NAME = "name";
044     private static final String TITLE = "title";
045     private static final String READER = "reader";
046     private static final String TABLE_CELL_FACTORY = "tableCellFactory";
047 
048     public DefaultFXTableFormat(@Nonnull String[] columnNames) {
049         this.columnNames = requireNonNull(columnNames, ERROR_COLUMN_NAMES_NULL);
050         this.columnTitles = new String[columnNames.length];
051         this.columnReaders = new ColumnReader[columnNames.length];
052         this.tableCellFactories = new TableCellFactory[columnNames.length];
053 
054         for (int i = 0; i < columnNames.length; i++) {
055             columnTitles[i= getNaturalName(columnNames[i]);
056             columnReaders[i= DefaultJavaFXColumnReader.INSTANCE;
057             tableCellFactories[i= TableCellFactory.DEFAULT_NON_EDITABLE;
058         }
059     }
060 
061     public DefaultFXTableFormat(@Nonnull String[] columnNames, @Nonnull String[] columnTitles, @Nonnull ColumnReader[] columnReaders) {
062         this.columnNames = requireNonNull(columnNames, ERROR_COLUMN_NAMES_NULL);
063         this.columnTitles = requireNonNull(columnTitles, "Argument 'columnTitles' must not be null");
064         this.columnReaders = requireNonNull(columnReaders, "Argument 'columnReaders' must not be nul");
065         this.tableCellFactories = new TableCellFactory[columnNames.length];
066 
067         requireState(columnNames.length == columnTitles.length,
068             "Arguments 'columNames' and 'columnTitles' have different cardinality. " + columnNames.length + " != " + columnTitles.length);
069         requireState(columnNames.length == columnReaders.length,
070             "Arguments 'columNames' and 'columnReaders' have different cardinality. " + columnNames.length + " != " + columnReaders.length);
071 
072         for (int i = 0; i < columnNames.length; i++) {
073             tableCellFactories[i= TableCellFactory.DEFAULT_NON_EDITABLE;
074         }
075     }
076 
077     /**
078      * Creates a {@code FXTableFormat} based on the supplied options.
079      <p>
080      * Valid option keys are <tt>name</tt><tt>title</tt> and <tt>reader</tt>.
081      </p>
082      *
083      @param options the options that configure this format
084      */
085     public DefaultFXTableFormat(@Nonnull FXTableFormat.Options... options) {
086         requireNonNull(options, "Argument 'options' must not be null");
087         requireState(options.length > 0"Argument 'options' must have at least one entry");
088 
089         this.columnNames = new String[options.length];
090         this.columnTitles = new String[options.length];
091         this.columnReaders = new ColumnReader[options.length];
092         this.tableCellFactories = new TableCellFactory[options.length];
093 
094         int i = 0;
095         for (Options opts : options) {
096             for (Option opt : opts.options) {
097                 if (NAME.equalsIgnoreCase(opt.name)) {
098                     columnNames[i= String.valueOf(opt.value);
099                 else if (TITLE.equalsIgnoreCase(opt.name)) {
100                     columnTitles[i= String.valueOf(opt.value);
101                 else if (READER.equalsIgnoreCase(opt.name)) {
102                     columnReaders[i(ColumnReaderopt.value;
103                 else if (TABLE_CELL_FACTORY.equalsIgnoreCase(opt.name)) {
104                     tableCellFactories[i(TableCellFactoryopt.value;
105                 }
106             }
107 
108             if (isBlank(columnNames[i])) {
109                 throw new IllegalArgumentException("Column " + i + " must have a value for name:");
110             }
111             if (isBlank(columnTitles[i])) {
112                 columnTitles[i= getNaturalName(columnNames[i]);
113             }
114             if (columnReaders[i== null) {
115                 columnReaders[i= DefaultJavaFXColumnReader.INSTANCE;
116             }
117 
118             i++;
119         }
120     }
121 
122     /**
123      * Creates a {@code FXTableFormat} based on the supplied options.
124      <p>
125      * Valid option keys are <tt>name</tt><tt>title</tt> and <tt>reader</tt>.
126      </p>
127      *
128      @param options the options that configure this format
129      */
130     public DefaultFXTableFormat(@Nonnull List<Map<String, Object>> options) {
131         requireNonNull(options, "Argument 'options' must not be null");
132         requireState(options.size() 0"Argument 'options' must have at least one entry");
133 
134         this.columnNames = new String[options.size()];
135         this.columnTitles = new String[options.size()];
136         this.columnReaders = new ColumnReader[options.size()];
137         this.tableCellFactories = new TableCellFactory[options.size()];
138 
139         int i = 0;
140         for (Map<String, Object> op : options) {
141             if (op.containsKey(NAME)) {
142                 columnNames[i= String.valueOf(op.get(NAME));
143             }
144             if (isBlank(columnNames[i])) {
145                 throw new IllegalArgumentException("Column " + i + " must have a value for name:");
146             }
147 
148             if (op.containsKey(TITLE)) {
149                 columnTitles[i= String.valueOf(op.get(TITLE));
150             else {
151                 columnTitles[i= getNaturalName(columnNames[i]);
152             }
153 
154             if (op.containsKey(READER&& op.get(READERinstanceof ColumnReader) {
155                 columnReaders[i(ColumnReaderop.get(READER);
156             else {
157                 columnReaders[i= DefaultJavaFXColumnReader.INSTANCE;
158             }
159 
160             if (op.containsKey(TABLE_CELL_FACTORY&& op.get(TABLE_CELL_FACTORYinstanceof TableCellFactory) {
161                 tableCellFactories[i(TableCellFactoryop.get(TABLE_CELL_FACTORY);
162             else {
163                 tableCellFactories[i= TableCellFactory.DEFAULT_EDITABLE;
164             }
165 
166             i++;
167         }
168     }
169 
170     @Override
171     public int getColumnCount() {
172         return columnNames.length;
173     }
174 
175     @Override
176     public String getColumnName(int column) {
177         return columnTitles[column];
178     }
179 
180     @Override
181     @SuppressWarnings("unchecked")
182     public Object getColumnValue(E baseObject, int column) {
183         return columnReaders[column].getValue(baseObject, columnNames[column], column);
184     }
185 
186     @Override
187     @SuppressWarnings("unchecked")
188     public ObservableValue<?> getColumnObservableValue(E baseObject, int column) {
189         return (ObservableValue<?>columnReaders[column].getValue(baseObject, columnNames[column], column);
190     }
191 
192     @Nonnull
193     @Override
194     public TableCellFactory getTableCellFactory(int column) {
195         return tableCellFactories[column];
196     }
197 }