comparison flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java@345f3bba6f15
children
comparison
equal deleted inserted replaced
5830:160f53ee0870 5831:bd047b71ab37
1 package org.dive4elements.river.collections;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import org.apache.log4j.Logger;
9
10 import org.dive4elements.artifacts.ArtifactDatabase;
11 import org.dive4elements.artifacts.ArtifactDatabaseException;
12
13 import org.dive4elements.artifactdatabase.state.Facet;
14 import org.dive4elements.artifactdatabase.state.FacetActivity;
15 import org.dive4elements.artifactdatabase.state.Output;
16
17 import org.dive4elements.river.artifacts.FLYSArtifact;
18 import org.dive4elements.river.artifacts.model.ManagedFacet;
19
20 /**
21 * Create attribute- element of describe document of an ArtifactCollection.
22 * The attribute-element contains the merged output of all outputmodes and
23 * facets that are part of the collection.
24 */
25 public class AttributeWriter {
26
27 /** ArtifactDatabase used to fetch Artifacts. */
28 protected ArtifactDatabase db = null;
29
30 protected Map<String, Output> oldAttr;
31
32 protected Map<String, Output> newAttr;
33
34 /** List of already seen facets. */
35 protected List<Facet> oldFacets;
36
37 /** List of "new" facets. */
38 protected List<Facet> newFacets;
39
40 /**
41 * "Compatibility matrix", mapws list of facet names to output names.
42 * Any facet that is not found in the list for a specific output will
43 * not be added to the resulting document.
44 */
45 protected Map<String, List<String>> compatibilities;
46
47
48 /** The result of the <i>write()</i> operation.*/
49 protected CollectionAttribute attribute;
50
51
52 private static Logger logger = Logger.getLogger(AttributeWriter.class);
53
54
55 /**
56 * Create a AttributeWriter.
57 * Attributes not present in newAttr will not be included in the document.
58 * @param db Database to fetch artifacts.
59 * @param oldAttr "Old" (possibly user-changed) outputs.
60 * @param newAttr "New" (eventually re-read in its original, unchanged
61 * form) outputs.
62 * @param matrix Compatibility matrix, mapping output names to list of
63 * facet names that can be included in this out.
64 */
65 public AttributeWriter(
66 ArtifactDatabase db,
67 CollectionAttribute attribute,
68 Map<String, Output> oldAttr,
69 List<Facet> oldFacets,
70 Map<String, Output> newAttr,
71 List<Facet> newFacets,
72 Map<String, List<String>> matrix)
73 {
74 this.db = db;
75 this.attribute = attribute;
76 this.oldAttr = oldAttr;
77 this.newAttr = newAttr;
78 this.oldFacets = oldFacets;
79 this.newFacets = newFacets;
80 this.compatibilities = matrix;
81 }
82
83
84 /**
85 * Create document by merging outputs given in
86 * constructor.
87 *
88 * The "new" set rules about existance of attributes, so anything not
89 * present in it will not be included in the resulting document.
90 * The "old" set rules about the content of attributes (as user changes
91 * are recorded here and not in the new set).
92 *
93 * @return document with merged outputs as described.
94 */
95 protected CollectionAttribute write() {
96
97 boolean debug = logger.isDebugEnabled();
98
99 for (Map.Entry<String, Output> entry: newAttr.entrySet()) {
100 String outName = entry.getKey();
101 Output a = entry.getValue();
102
103 if (!attribute.hasOutput(outName)) {
104 attribute.addOutput(outName, a);
105 }
106
107 attribute.clearFacets(outName);
108
109 if (debug) {
110 logger.debug("Merge Output: " + outName);
111 logger.debug(" old Facets: " + oldFacets.size());
112 logger.debug(" new Facets: " + newFacets.size());
113 }
114
115 writeOutput(a.getName(), newFacets, oldFacets);
116 }
117
118 // THIS CALL IS ABSOLUTELY NECESSARY!
119 attribute.cleanEmptyOutputs();
120
121 return attribute;
122 }
123
124
125 /**
126 * @param outputName the "new" outputs name
127 * @param newOutFacets Facets of the new outputs
128 * @param oldOutFacets Facets of the old outputs (can be null)
129 */
130 protected void writeOutput(
131 String outputName,
132 List<Facet> newOutFacets,
133 List<Facet> oldOutFacets
134 ) {
135 List<String> compatFacets = this.compatibilities.get(outputName);
136
137 if (logger.isDebugEnabled() && compatFacets != null) {
138 logger.debug("Compabitle Facets:");
139 for (String compatible: compatFacets) {
140 logger.debug( "- " + compatible);
141 }
142 }
143
144 try {
145 writeFacets(outputName, newOutFacets, oldOutFacets, compatFacets);
146 }
147 catch (ArtifactDatabaseException ade) {
148 logger.error(ade, ade);
149 }
150 }
151
152
153 /**
154 * @param newFacets the new facets
155 * @param oldFacets the old facets
156 * @param compatibleFacets List of facets to accept
157 * @return true if any facets are written to the out.
158 */
159 protected boolean writeFacets(
160 String outputName,
161 List<Facet> newFacets,
162 List<Facet> oldFacets,
163 List<String> compatibleFacets)
164 throws ArtifactDatabaseException
165 {
166 if (compatibleFacets == null) {
167 logger.warn("No compatible facets, not generating out " + outputName + ".");
168 return false;
169 }
170
171 int num = newFacets.size();
172
173 // Add all new Facets either in their old state or (if really
174 // new) as they are.
175 List<ManagedFacet> currentFacets = new ArrayList<ManagedFacet>();
176 List<ManagedFacet> genuinelyNewFacets = new ArrayList<ManagedFacet>();
177
178 boolean debug = logger.isDebugEnabled();
179 if (debug) {
180 logger.debug("Compatible facets are " + compatibleFacets);
181 }
182
183 for (int i = 0; i < num; i++) {
184 ManagedFacet facet = (ManagedFacet) newFacets.get(i);
185
186 if (debug) {
187 logger.debug("Try to add Facet: " + facet.getName());
188 }
189
190 if (!compatibleFacets.contains(facet.getName())) {
191 logger.warn("Have incompatible facet, skip: " + facet.getName());
192 continue;
193 }
194 else {
195 logger.debug("Have compatible facet: " + facet.getName());
196 }
197
198 ManagedFacet picked = pickFacet(facet, oldFacets);
199
200 if (facet.equals(picked)) {
201 genuinelyNewFacets.add(picked);
202 }
203 else {
204 currentFacets.add(picked);
205 }
206 }
207
208 FacetActivity.Registry registry = FacetActivity.Registry.getInstance();
209
210 // With each genuinely new Facet, figure out whether it comes to live
211 // in/activate.
212 for (ManagedFacet newMF: genuinelyNewFacets) {
213 FLYSArtifact flys =
214 (FLYSArtifact)db.getRawArtifact(newMF.getArtifact());
215
216 boolean isActive = registry.isInitialActive(
217 flys.getName(), flys, newMF, outputName);
218
219 newMF.setActive(isActive ? 1 : 0);
220 }
221
222 // For each genuinely new Facet check positional conflicts.
223 for (ManagedFacet newMF: genuinelyNewFacets) {
224 boolean conflicts = true;
225 // Loop until all conflicts resolved.
226 while (conflicts) {
227 conflicts = false;
228 for (ManagedFacet oldMF: currentFacets) {
229 if (newMF.getPosition() == oldMF.getPosition()) {
230 conflicts = true;
231 if (debug) {
232 logger.debug(
233 "Positional conflict while merging " +
234 "facets, pushing newest facet 1 up (" +
235 newMF.getPosition() + ")");
236 }
237 newMF.setPosition(newMF.getPosition() + 1);
238 break;
239 }
240 }
241 }
242 currentFacets.add(newMF);
243 }
244
245 // Fill/correct "gaps" (e.g. position 1,2,5 are taken, after gap filling
246 // expect positions 1,2,3 [5->3])
247 // Preparations to be able to detect gaps.
248 Map<Integer, ManagedFacet> mfmap =
249 new HashMap<Integer, ManagedFacet>();
250 int max = 0;
251 for (ManagedFacet mf: currentFacets) {
252 int pos = mf.getPosition();
253 mfmap.put(Integer.valueOf(pos), mf);
254 if (pos > max) max = pos;
255 }
256
257 // Finally do gap correction.
258 if (max != currentFacets.size()) {
259 int gap = 0;
260 for (int i = 1; i <= max; i++) {
261 ManagedFacet mf = mfmap.get(Integer.valueOf(i));
262 if (mf == null) {
263 gap++;
264 continue;
265 }
266 mf.setPosition(mf.getPosition() - gap);
267 }
268 }
269
270 // Now add all facets.
271 for (ManagedFacet oldMF: currentFacets) {
272 attribute.addFacet(outputName, oldMF);
273 }
274
275 return !currentFacets.isEmpty();
276 }
277
278
279 /**
280 * Returns the facet to be added to Document.
281 * Return the new facet only if the "same" facet was not present before.
282 * Return the "old" facet otherwise (user-defined information sticks
283 * to it).
284 * @param facet the new facet.
285 * @param oldFacets the old facets, new facet is compared against each of
286 * these.
287 * @return facet if genuinely new, matching old facet otherwise.
288 */
289 protected ManagedFacet pickFacet(ManagedFacet facet, List<Facet> oldFacets)
290 {
291 if (oldFacets == null) {
292 logger.debug("No old facets to compare a new to found.");
293 return facet;
294 }
295
296 String hash = facet.getName() + facet.getIndex() + facet.getArtifact();
297
298 // Compare "new" facet with all old facets.
299 // Take oldFacet if that facet was already present (otherwise
300 // information is lost, the new one otherwise.
301 for (Facet oFacet: oldFacets) {
302 ManagedFacet oldFacet = (ManagedFacet) oFacet;
303 String oldHash = oldFacet.getName()
304 + oldFacet.getIndex()
305 + oldFacet.getArtifact();
306 if (hash.equals(oldHash)) {
307 return oldFacet;
308 }
309 }
310 return facet;
311 }
312 }
313 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org