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;
22  
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  
27  import org.openflexo.foundation.technologyadapter.TechnologyAdapter;
28  import org.openflexo.pamela.annotations.Adder;
29  import org.openflexo.pamela.annotations.CloningStrategy;
30  import org.openflexo.pamela.annotations.Embedded;
31  import org.openflexo.pamela.annotations.Getter;
32  import org.openflexo.pamela.annotations.ModelEntity;
33  import org.openflexo.pamela.annotations.PastingPoint;
34  import org.openflexo.pamela.annotations.PropertyIdentifier;
35  import org.openflexo.pamela.annotations.Remover;
36  import org.openflexo.pamela.annotations.Setter;
37  import org.openflexo.pamela.annotations.XMLElement;
38  import org.openflexo.pamela.annotations.CloningStrategy.StrategyType;
39  import org.openflexo.pamela.annotations.Getter.Cardinality;
40  import org.openflexo.toolbox.StringUtils;
41  
42  /**
43   * Generic abstract concept representing a paragraph of a text-based document (eg .docx, .odt, etc...)
44   * 
45   * @author sylvain
46   *
47   * @param <D>
48   *            type of {@link FlexoDocument} involving this concept
49   * @param <TA>
50   *            {@link TechnologyAdapter} of current implementation
51   */
52  @ModelEntity(isAbstract = true)
53  public interface FlexoDocParagraph<D extends FlexoDocument<D, TA>, TA extends TechnologyAdapter<TA>> extends FlexoDocElement<D, TA> {
54  
55  	@PropertyIdentifier(type = FlexoDocRun.class, cardinality = Cardinality.LIST)
56  	public static final String RUNS_KEY = "runs";
57  
58  	/**
59  	 * Return the list of runs of this paragraph
60  	 * 
61  	 * @return
62  	 */
63  	@Getter(value = RUNS_KEY, cardinality = Cardinality.LIST, inverse = FlexoDocRun.PARAGRAPH_KEY)
64  	@XMLElement(primary = true)
65  	@CloningStrategy(StrategyType.CLONE)
66  	@Embedded
67  	public List<FlexoDocRun<D, TA>> getRuns();
68  
69  	@Setter(RUNS_KEY)
70  	public void setRuns(List<FlexoDocRun<D, TA>> someRuns);
71  
72  	/**
73  	 * Add run to this {@link FlexoDocParagraph} (public API).<br>
74  	 * Element will be added to underlying technology-specific model and {@link FlexoDocParagraph} will be updated accordingly
75  	 */
76  	@Adder(RUNS_KEY)
77  	@PastingPoint
78  	public void addToRuns(FlexoDocRun<D, TA> aRun);
79  
80  	/**
81  	 * Remove run from this {@link FlexoDocParagraph} (public API).<br>
82  	 * Element will be removed from underlying technology-specific model and {@link FlexoDocParagraph} will be updated accordingly
83  	 */
84  	@Remover(RUNS_KEY)
85  	public void removeFromRuns(FlexoDocRun<D, TA> aRun);
86  
87  	/**
88  	 * Insert run to this {@link FlexoDocParagraph} at supplied index (public API).<br>
89  	 * Element will be inserted to underlying technology-specific model and {@link FlexoDocParagraph} will be updated accordingly
90  	 */
91  	public void insertRunAtIndex(FlexoDocRun<D, TA> anElement, int index);
92  
93  	/**
94  	 * Move run in this {@link FlexoDocParagraph} at supplied index (public API).<br>
95  	 * Element will be moved inside underlying technology-specific model and {@link FlexoDocParagraph} will be updated accordingly
96  	 */
97  	public void moveRunToIndex(FlexoDocRun<D, TA> anElement, int index);
98  
99  	/**
100 	 * Return a string representation (plain text) of contents of the paragraph (styles associated to runs are not reflected)
101 	 * 
102 	 * @return
103 	 */
104 	public String getRawText();
105 
106 	/**
107 	 * Sets contents of the paragraph by erasing actual structure, and replacing it by a unique run reflecting supplied text
108 	 * 
109 	 * @return
110 	 */
111 	public void setRawText(String someText);
112 
113 	public String getRawTextPreview();
114 
115 	public void fireTextChanged();
116 
117 	/**
118 	 * Return a new list containing {@link FlexoDrawingRun} for this paragraph
119 	 * 
120 	 * @return
121 	 */
122 	public List<FlexoDrawingRun<D, TA>> getDrawingRuns();
123 
124 	public static abstract class FlexoDocParagraphImpl<D extends FlexoDocument<D, TA>, TA extends TechnologyAdapter<TA>>
125 			extends FlexoDocumentElementImpl<D, TA> implements FlexoDocParagraph<D, TA> {
126 
127 		@Override
128 		public String toString() {
129 			return "Paragraph(" + getIdentifier() + ") " /* + getRawText() + " "*/
130 					+ (getNamedStyle() != null ? "[" + getNamedStyle().getName() + "]" : "")
131 					+ (getParagraphStyle() != null ? "[" + getParagraphStyle().getStringRepresentation() + "]" : "");
132 		}
133 
134 		@Override
135 		protected List<FlexoDocElement<D, TA>> computeChildrenElements() {
136 			if (getFlexoDocument() == null) {
137 				return null;
138 			}
139 			if (getNamedStyle() == null || !getNamedStyle().isLevelled()) {
140 				return Collections.emptyList();
141 			}
142 
143 			Integer parentLevel = getNamedStyle().getLevel();
144 			Integer childLevel = null;
145 			int start = getFlexoDocument().getElements().indexOf(this) + 1;
146 
147 			int i = start;
148 
149 			List<FlexoDocElement<D, TA>> returned = new ArrayList<>();
150 
151 			while (i < getFlexoDocument().getElements().size()) {
152 				FlexoDocElement<D, TA> e = getFlexoDocument().getElements().get(i);
153 
154 				if (e instanceof FlexoDocParagraph) {
155 					if (((FlexoDocParagraph<D, TA>) e).getNamedStyle() != null
156 							&& ((FlexoDocParagraph<D, TA>) e).getNamedStyle().isLevelled()) {
157 						if (((FlexoDocParagraph<D, TA>) e).getNamedStyle().getLevel() <= parentLevel) {
158 							return returned;
159 						}
160 					}
161 				}
162 
163 				if (childLevel == null) {
164 					returned.add(e);
165 					if (e instanceof FlexoDocParagraph) {
166 						if (((FlexoDocParagraph<D, TA>) e).getNamedStyle() != null
167 								&& ((FlexoDocParagraph<D, TA>) e).getNamedStyle().isLevelled()) {
168 							childLevel = ((FlexoDocParagraph<D, TA>) e).getNamedStyle().getLevel();
169 						}
170 					}
171 				}
172 				else {
173 					if (e instanceof FlexoDocParagraph) {
174 						if (((FlexoDocParagraph<D, TA>) e).getNamedStyle() != null) {
175 							if (((FlexoDocParagraph<D, TA>) e).getNamedStyle().getLevel().equals(childLevel)) {
176 								returned.add(e);
177 							}
178 						}
179 					}
180 				}
181 
182 				/*if (childLevel == null) 
183 				if (e instanceof FlexoDocParagraph) {
184 					if (((FlexoDocParagraph<D, TA>) e).getStyle() != null && ((FlexoDocParagraph<D, TA>) e).getStyle().isLevelled()) {
185 						if (((FlexoDocParagraph<D, TA>) e).getStyle().getLevel() <= l) {
186 							return returned;
187 						}
188 					}
189 				}
190 				returned.add(e);*/
191 				i++;
192 			}
193 
194 			return returned;
195 
196 		}
197 
198 		@Override
199 		public String getRawTextPreview() {
200 			// TODO: perf issue
201 			String rawText = getRawText();
202 			if (rawText.length() > 35) {
203 				return rawText.substring(0, 35) + "...";
204 			}
205 			else if (StringUtils.isNotEmpty(rawText)) {
206 				return rawText;
207 			}
208 			else {
209 				return "<newline>";
210 			}
211 		}
212 
213 		@Override
214 		public void fireTextChanged() {
215 			getPropertyChangeSupport().firePropertyChange("rawText", null, getRawText());
216 			getPropertyChangeSupport().firePropertyChange("rawTextPreview", null, getRawTextPreview());
217 		}
218 
219 		@Override
220 		public List<FlexoDrawingRun<D, TA>> getDrawingRuns() {
221 			List<FlexoDrawingRun<D, TA>> returned = new ArrayList<>();
222 			for (FlexoDocRun<?, ?> run : getRuns()) {
223 				if (run instanceof FlexoDrawingRun) {
224 					returned.add((FlexoDrawingRun) run);
225 				}
226 			}
227 			return returned;
228 		}
229 	}
230 
231 }