Mercurial > dive4elements > river
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,313 @@ +package org.dive4elements.river.collections; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.ArtifactDatabase; +import org.dive4elements.artifacts.ArtifactDatabaseException; + +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifactdatabase.state.FacetActivity; +import org.dive4elements.artifactdatabase.state.Output; + +import org.dive4elements.river.artifacts.FLYSArtifact; +import org.dive4elements.river.artifacts.model.ManagedFacet; + +/** + * Create attribute- element of describe document of an ArtifactCollection. + * The attribute-element contains the merged output of all outputmodes and + * facets that are part of the collection. + */ +public class AttributeWriter { + + /** ArtifactDatabase used to fetch Artifacts. */ + protected ArtifactDatabase db = null; + + protected Map<String, Output> oldAttr; + + protected Map<String, Output> newAttr; + + /** List of already seen facets. */ + protected List<Facet> oldFacets; + + /** List of "new" facets. */ + protected List<Facet> newFacets; + + /** + * "Compatibility matrix", mapws list of facet names to output names. + * Any facet that is not found in the list for a specific output will + * not be added to the resulting document. + */ + protected Map<String, List<String>> compatibilities; + + + /** The result of the <i>write()</i> operation.*/ + protected CollectionAttribute attribute; + + + private static Logger logger = Logger.getLogger(AttributeWriter.class); + + + /** + * Create a AttributeWriter. + * Attributes not present in newAttr will not be included in the document. + * @param db Database to fetch artifacts. + * @param oldAttr "Old" (possibly user-changed) outputs. + * @param newAttr "New" (eventually re-read in its original, unchanged + * form) outputs. + * @param matrix Compatibility matrix, mapping output names to list of + * facet names that can be included in this out. + */ + public AttributeWriter( + ArtifactDatabase db, + CollectionAttribute attribute, + Map<String, Output> oldAttr, + List<Facet> oldFacets, + Map<String, Output> newAttr, + List<Facet> newFacets, + Map<String, List<String>> matrix) + { + this.db = db; + this.attribute = attribute; + this.oldAttr = oldAttr; + this.newAttr = newAttr; + this.oldFacets = oldFacets; + this.newFacets = newFacets; + this.compatibilities = matrix; + } + + + /** + * Create document by merging outputs given in + * constructor. + * + * The "new" set rules about existance of attributes, so anything not + * present in it will not be included in the resulting document. + * The "old" set rules about the content of attributes (as user changes + * are recorded here and not in the new set). + * + * @return document with merged outputs as described. + */ + protected CollectionAttribute write() { + + boolean debug = logger.isDebugEnabled(); + + for (Map.Entry<String, Output> entry: newAttr.entrySet()) { + String outName = entry.getKey(); + Output a = entry.getValue(); + + if (!attribute.hasOutput(outName)) { + attribute.addOutput(outName, a); + } + + attribute.clearFacets(outName); + + if (debug) { + logger.debug("Merge Output: " + outName); + logger.debug(" old Facets: " + oldFacets.size()); + logger.debug(" new Facets: " + newFacets.size()); + } + + writeOutput(a.getName(), newFacets, oldFacets); + } + + // THIS CALL IS ABSOLUTELY NECESSARY! + attribute.cleanEmptyOutputs(); + + return attribute; + } + + + /** + * @param outputName the "new" outputs name + * @param newOutFacets Facets of the new outputs + * @param oldOutFacets Facets of the old outputs (can be null) + */ + protected void writeOutput( + String outputName, + List<Facet> newOutFacets, + List<Facet> oldOutFacets + ) { + List<String> compatFacets = this.compatibilities.get(outputName); + + if (logger.isDebugEnabled() && compatFacets != null) { + logger.debug("Compabitle Facets:"); + for (String compatible: compatFacets) { + logger.debug( "- " + compatible); + } + } + + try { + writeFacets(outputName, newOutFacets, oldOutFacets, compatFacets); + } + catch (ArtifactDatabaseException ade) { + logger.error(ade, ade); + } + } + + + /** + * @param newFacets the new facets + * @param oldFacets the old facets + * @param compatibleFacets List of facets to accept + * @return true if any facets are written to the out. + */ + protected boolean writeFacets( + String outputName, + List<Facet> newFacets, + List<Facet> oldFacets, + List<String> compatibleFacets) + throws ArtifactDatabaseException + { + if (compatibleFacets == null) { + logger.warn("No compatible facets, not generating out " + outputName + "."); + return false; + } + + int num = newFacets.size(); + + // Add all new Facets either in their old state or (if really + // new) as they are. + List<ManagedFacet> currentFacets = new ArrayList<ManagedFacet>(); + List<ManagedFacet> genuinelyNewFacets = new ArrayList<ManagedFacet>(); + + boolean debug = logger.isDebugEnabled(); + if (debug) { + logger.debug("Compatible facets are " + compatibleFacets); + } + + for (int i = 0; i < num; i++) { + ManagedFacet facet = (ManagedFacet) newFacets.get(i); + + if (debug) { + logger.debug("Try to add Facet: " + facet.getName()); + } + + if (!compatibleFacets.contains(facet.getName())) { + logger.warn("Have incompatible facet, skip: " + facet.getName()); + continue; + } + else { + logger.debug("Have compatible facet: " + facet.getName()); + } + + ManagedFacet picked = pickFacet(facet, oldFacets); + + if (facet.equals(picked)) { + genuinelyNewFacets.add(picked); + } + else { + currentFacets.add(picked); + } + } + + FacetActivity.Registry registry = FacetActivity.Registry.getInstance(); + + // With each genuinely new Facet, figure out whether it comes to live + // in/activate. + for (ManagedFacet newMF: genuinelyNewFacets) { + FLYSArtifact flys = + (FLYSArtifact)db.getRawArtifact(newMF.getArtifact()); + + boolean isActive = registry.isInitialActive( + flys.getName(), flys, newMF, outputName); + + newMF.setActive(isActive ? 1 : 0); + } + + // For each genuinely new Facet check positional conflicts. + for (ManagedFacet newMF: genuinelyNewFacets) { + boolean conflicts = true; + // Loop until all conflicts resolved. + while (conflicts) { + conflicts = false; + for (ManagedFacet oldMF: currentFacets) { + if (newMF.getPosition() == oldMF.getPosition()) { + conflicts = true; + if (debug) { + logger.debug( + "Positional conflict while merging " + + "facets, pushing newest facet 1 up (" + + newMF.getPosition() + ")"); + } + newMF.setPosition(newMF.getPosition() + 1); + break; + } + } + } + currentFacets.add(newMF); + } + + // Fill/correct "gaps" (e.g. position 1,2,5 are taken, after gap filling + // expect positions 1,2,3 [5->3]) + // Preparations to be able to detect gaps. + Map<Integer, ManagedFacet> mfmap = + new HashMap<Integer, ManagedFacet>(); + int max = 0; + for (ManagedFacet mf: currentFacets) { + int pos = mf.getPosition(); + mfmap.put(Integer.valueOf(pos), mf); + if (pos > max) max = pos; + } + + // Finally do gap correction. + if (max != currentFacets.size()) { + int gap = 0; + for (int i = 1; i <= max; i++) { + ManagedFacet mf = mfmap.get(Integer.valueOf(i)); + if (mf == null) { + gap++; + continue; + } + mf.setPosition(mf.getPosition() - gap); + } + } + + // Now add all facets. + for (ManagedFacet oldMF: currentFacets) { + attribute.addFacet(outputName, oldMF); + } + + return !currentFacets.isEmpty(); + } + + + /** + * Returns the facet to be added to Document. + * Return the new facet only if the "same" facet was not present before. + * Return the "old" facet otherwise (user-defined information sticks + * to it). + * @param facet the new facet. + * @param oldFacets the old facets, new facet is compared against each of + * these. + * @return facet if genuinely new, matching old facet otherwise. + */ + protected ManagedFacet pickFacet(ManagedFacet facet, List<Facet> oldFacets) + { + if (oldFacets == null) { + logger.debug("No old facets to compare a new to found."); + return facet; + } + + String hash = facet.getName() + facet.getIndex() + facet.getArtifact(); + + // Compare "new" facet with all old facets. + // Take oldFacet if that facet was already present (otherwise + // information is lost, the new one otherwise. + for (Facet oFacet: oldFacets) { + ManagedFacet oldFacet = (ManagedFacet) oFacet; + String oldHash = oldFacet.getName() + + oldFacet.getIndex() + + oldFacet.getArtifact(); + if (hash.equals(oldHash)) { + return oldFacet; + } + } + return facet; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :