View Javadoc
1   /*
2    * (c) Copyright 2013- Openflexo
3    *
4    * This file is part of OpenFlexo.
5    *
6    * OpenFlexo is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * OpenFlexo is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
18   *
19   */
20  
21  package org.openflexo.foundation.doc.fml;
22  
23  import java.lang.reflect.ParameterizedType;
24  import java.lang.reflect.Type;
25  import java.util.List;
26  
27  import org.openflexo.connie.BindingModel;
28  import org.openflexo.connie.BindingVariable;
29  import org.openflexo.connie.DataBinding;
30  import org.openflexo.connie.DataBinding.BindingDefinitionType;
31  import org.openflexo.foundation.doc.FlexoDocFragment;
32  import org.openflexo.foundation.doc.FlexoDocTable;
33  import org.openflexo.foundation.doc.FlexoDocument;
34  import org.openflexo.foundation.fml.FlexoRole;
35  import org.openflexo.foundation.fml.rt.AbstractVirtualModelInstanceModelFactory;
36  import org.openflexo.foundation.fml.rt.FlexoConceptInstance;
37  import org.openflexo.foundation.technologyadapter.TechnologyAdapter;
38  import org.openflexo.pamela.annotations.Adder;
39  import org.openflexo.pamela.annotations.Getter;
40  import org.openflexo.pamela.annotations.ImplementationClass;
41  import org.openflexo.pamela.annotations.ModelEntity;
42  import org.openflexo.pamela.annotations.PropertyIdentifier;
43  import org.openflexo.pamela.annotations.Remover;
44  import org.openflexo.pamela.annotations.Setter;
45  import org.openflexo.pamela.annotations.XMLAttribute;
46  import org.openflexo.pamela.annotations.XMLElement;
47  import org.openflexo.pamela.annotations.Getter.Cardinality;
48  import org.openflexo.toolbox.StringUtils;
49  
50  @ModelEntity(isAbstract = true)
51  @ImplementationClass(FlexoTableRole.FlexoTableRoleImpl.class)
52  public interface FlexoTableRole<T extends FlexoDocTable<D, TA>, D extends FlexoDocument<D, TA>, TA extends TechnologyAdapter<TA>>
53  		extends FlexoRole<T> {
54  
55  	@PropertyIdentifier(type = FlexoDocFragment.class)
56  	public static final String TABLE_KEY = "table";
57  	@PropertyIdentifier(type = String.class)
58  	public static final String TABLE_ID_KEY = "tableId";
59  	@PropertyIdentifier(type = DataBinding.class)
60  	public static final String ITERATION_KEY = "iteration";
61  	@PropertyIdentifier(type = Integer.class)
62  	public static final String START_ITERATION_INDEX_KEY = "startIterationIndex";
63  	@PropertyIdentifier(type = Integer.class)
64  	public static final String END_ITERATION_INDEX_KEY = "endIterationIndex";
65  	@PropertyIdentifier(type = DataOrientation.class)
66  	public static final String DATA_ORIENTATION_KEY = "dataOrientation";
67  	@PropertyIdentifier(type = ColumnTableBinding.class, cardinality = Cardinality.LIST)
68  	public static final String COLUMN_BINDINGS_KEY = "columnBindings";
69  
70  	public static enum DataOrientation {
71  		Vertical, Horizontal
72  	}
73  
74  	/**
75  	 * Return the template document
76  	 * 
77  	 * @return
78  	 */
79  	public FlexoDocument<D, TA> getDocument();
80  
81  	/**
82  	 * Return the represented table in the template document resource<br>
83  	 * Note that is not the table that is to be managed at run-time
84  	 * 
85  	 * @return
86  	 */
87  	@Getter(value = TABLE_KEY, isStringConvertable = true)
88  	public T getTable();
89  
90  	/**
91  	 * Sets the represented table in the template resource<br>
92  	 * 
93  	 * @param fragment
94  	 */
95  	@Setter(TABLE_KEY)
96  	public void setTable(T table);
97  
98  	/**
99  	 * Return the represented table id in the template document resource<br>
100 	 */
101 	@Getter(TABLE_ID_KEY)
102 	@XMLAttribute
103 	public String getTableId();
104 
105 	@Setter(TABLE_ID_KEY)
106 	public void setTableId(String tableId);
107 
108 	/**
109 	 * Return a {@link DataBinding} representing access to the list of objects on which to iterate
110 	 * 
111 	 * @return
112 	 */
113 	@Getter(ITERATION_KEY)
114 	@XMLAttribute
115 	public DataBinding<List> getIteration();
116 
117 	/**
118 	 * Sets {@link DataBinding} representing access to the list of objects on which to iterate
119 	 * 
120 	 * @param value
121 	 */
122 	@Setter(ITERATION_KEY)
123 	public void setIteration(DataBinding<List> value);
124 
125 	@Getter(value = START_ITERATION_INDEX_KEY, defaultValue = "-1")
126 	@XMLAttribute
127 	public int getStartIterationIndex();
128 
129 	@Setter(START_ITERATION_INDEX_KEY)
130 	public void setStartIterationIndex(int startIterationIndex);
131 
132 	@Getter(value = END_ITERATION_INDEX_KEY, defaultValue = "-1")
133 	@XMLAttribute
134 	public int getEndIterationIndex();
135 
136 	@Setter(END_ITERATION_INDEX_KEY)
137 	public void setEndIterationIndex(int endIterationIndex);
138 
139 	@Getter(value = DATA_ORIENTATION_KEY)
140 	@XMLAttribute
141 	public DataOrientation getDataOrientation();
142 
143 	@Setter(DATA_ORIENTATION_KEY)
144 	public void setDataOrientation(DataOrientation dataOrientation);
145 
146 	@Getter(value = COLUMN_BINDINGS_KEY, cardinality = Cardinality.LIST, inverse = ColumnTableBinding.TABLE_ROLE_KEY)
147 	@XMLElement
148 	public List<ColumnTableBinding<D, TA>> getColumnBindings();
149 
150 	@Setter(COLUMN_BINDINGS_KEY)
151 	public void setColumnBindings(List<ColumnTableBinding<D, TA>> someColumnBindings);
152 
153 	@Adder(COLUMN_BINDINGS_KEY)
154 	public void addToColumnBindings(ColumnTableBinding<D, TA> aColumnBinding);
155 
156 	@Remover(COLUMN_BINDINGS_KEY)
157 	public void removeFromColumnBindings(ColumnTableBinding<D, TA> aColumnBinding);
158 
159 	public BindingModel getTableBindingModel();
160 
161 	public static abstract class FlexoTableRoleImpl<T extends FlexoDocTable<D, TA>, D extends FlexoDocument<D, TA>, TA extends TechnologyAdapter<TA>>
162 			extends FlexoRoleImpl<T> implements FlexoTableRole<T, D, TA> {
163 
164 		private BindingModel tableBindingModel;
165 		public static final String ITERATOR_NAME = "iterator";
166 
167 		private T table;
168 		private String tableId;
169 
170 		@Override
171 		public String getTableId() {
172 			if (getTable() != null) {
173 				return getTable().getIdentifier();
174 			}
175 			return tableId;
176 		}
177 
178 		@Override
179 		public void setTableId(String tableId) {
180 			if ((tableId == null && this.tableId != null) || (tableId != null && !tableId.equals(this.tableId))) {
181 				String oldValue = getTableId();
182 				this.tableId = tableId;
183 				this.table = null;
184 				getPropertyChangeSupport().firePropertyChange(TABLE_ID_KEY, oldValue, tableId);
185 				getPropertyChangeSupport().firePropertyChange(TABLE_KEY, null, table);
186 			}
187 		}
188 
189 		@Override
190 		public T getTable() {
191 			if (table == null && StringUtils.isNotEmpty(tableId) && getDocument() != null) {
192 				table = (T) getDocument().getElementWithIdentifier(tableId);
193 			}
194 			return table;
195 		}
196 
197 		@Override
198 		public void setTable(T table) {
199 			T oldValue = this.table;
200 			if (table != oldValue) {
201 				this.table = table;
202 				getPropertyChangeSupport().firePropertyChange(TABLE_KEY, oldValue, table);
203 				getPropertyChangeSupport().firePropertyChange(TABLE_ID_KEY, null, getTableId());
204 			}
205 		}
206 
207 		@Override
208 		public DataOrientation getDataOrientation() {
209 			DataOrientation returned = (DataOrientation) performSuperGetter(DATA_ORIENTATION_KEY);
210 			if (returned == null) {
211 				return DataOrientation.Vertical;
212 			}
213 			return returned;
214 		}
215 
216 		@Override
217 		public FlexoDocument<D, TA> getDocument() {
218 			if (getModelSlot() instanceof FlexoDocumentModelSlot) {
219 				if (((FlexoDocumentModelSlot<D>) getModelSlot()).getTemplateResource() != null) {
220 					return ((FlexoDocumentModelSlot<D>) getModelSlot()).getTemplateResource().getDocument();
221 				}
222 			}
223 			return null;
224 		}
225 
226 		private DataBinding<List> iteration;
227 
228 		@Override
229 		public DataBinding<List> getIteration() {
230 			if (iteration == null) {
231 				iteration = new DataBinding<>(this, List.class, DataBinding.BindingDefinitionType.GET);
232 				iteration.setBindingName("Iteration");
233 				iteration.setMandatory(false);
234 			}
235 			return iteration;
236 		}
237 
238 		@Override
239 		public void setIteration(DataBinding<List> iteration) {
240 			if (iteration != null) {
241 				iteration.setOwner(this);
242 				iteration.setDeclaredType(List.class);
243 				iteration.setBindingName("Iteration");
244 				iteration.setMandatory(true);
245 				iteration.setBindingDefinitionType(BindingDefinitionType.GET);
246 			}
247 			this.iteration = iteration;
248 			notifiedBindingChanged(getIteration());
249 			if (tableBindingModel != null) {
250 				BindingVariable iteratorVariable = tableBindingModel.bindingVariableNamed(ITERATOR_NAME);
251 				iteratorVariable.setType(getIteratorType());
252 			}
253 		}
254 
255 		public Type getIteratorType() {
256 			if (getIteration() != null && getIteration().isSet() && getIteration().isValid()) {
257 				Type iterationType = getIteration().getAnalyzedType();
258 				if (iterationType instanceof ParameterizedType) {
259 					return ((ParameterizedType) iterationType).getActualTypeArguments()[0];
260 				}
261 			}
262 			return Object.class;
263 		}
264 
265 		@Override
266 		public BindingModel getTableBindingModel() {
267 			if (tableBindingModel == null) {
268 				createTableBindingModel();
269 			}
270 			return tableBindingModel;
271 		}
272 
273 		private void createTableBindingModel() {
274 			tableBindingModel = new BindingModel(getBindingModel());
275 
276 			BindingVariable iteratorVariable = new BindingVariable(ITERATOR_NAME, getIteratorType()) {
277 				@Override
278 				public Type getType() {
279 					return getIteratorType();
280 				}
281 			};
282 			iteratorVariable.setCacheable(false);
283 
284 			tableBindingModel.addToBindingVariables(iteratorVariable);
285 			// System.out.println("dataClass="+getDataClass()+" dataClassName="+dataClassName);
286 
287 			// logger.info("******** Table: "+getName()+" Add BindingVariable: iterator type="+getIteratorClass());
288 		}
289 
290 		@Override
291 		public TableActorReference<T> makeActorReference(T table, FlexoConceptInstance fci) {
292 
293 			AbstractVirtualModelInstanceModelFactory<?> factory = fci.getFactory();
294 			TableActorReference<T> returned = factory.newInstance(TableActorReference.class);
295 			returned.setFlexoRole(this);
296 			returned.setFlexoConceptInstance(fci);
297 			returned.setModellingElement(table);
298 			return returned;
299 
300 		}
301 
302 	}
303 }