comparison flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java @ 3818:dc18457b1cef

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

http://dive4elements.wald.intevation.org