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