Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java @ 4031:e4e345d81a65
issue889/2
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Thu, 04 Oct 2012 14:54:44 +0200 |
parents | 721d55bdab9e |
children | e8a4d2fd25cc |
line wrap: on
line source
package de.intevation.flys.collections; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import de.intevation.artifacts.ArtifactDatabase; import de.intevation.artifacts.ArtifactDatabaseException; import de.intevation.artifactdatabase.state.Facet; import de.intevation.artifactdatabase.state.FacetActivity; import de.intevation.artifactdatabase.state.Output; import de.intevation.flys.artifacts.FLYSArtifact; import de.intevation.flys.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. */ 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(); Output exists = attribute.getOutput(outName); if (exists == null) { 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."); 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(); 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 :