comparison flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java @ 3806:881fcd01e056

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

http://dive4elements.wald.intevation.org