teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.states.minfo; raimund@3629: ingo@3749: import java.util.ArrayList; ingo@3767: import java.util.Date; ingo@3749: import java.util.List; ingo@3749: ingo@3749: import org.apache.log4j.Logger; ingo@3749: teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; rrenkert@6262: import org.dive4elements.artifactdatabase.state.FacetActivity; rrenkert@6262: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.CallMeta; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.access.BedQualityAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.CalculationResult; teichmann@5831: import org.dive4elements.river.artifacts.model.DataFacet; teichmann@5831: import org.dive4elements.river.artifacts.model.DateRange; teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; andre@8587: import org.dive4elements.river.artifacts.model.minfo.BedQualityDataFacet; andre@8592: import org.dive4elements.river.artifacts.model.minfo.BedQualityInterpolFacet; rrenkert@6252: import org.dive4elements.river.artifacts.model.minfo.BedDiameterDataFacet; andre@8587: import org.dive4elements.river.artifacts.model.minfo.BedloadDiameterDataFacet; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation; teichmann@5831: import org.dive4elements.river.artifacts.model.minfo.BedQualityResult; andre@8587: import org.dive4elements.river.artifacts.model.minfo.BedQualityResultValue; teichmann@5831: import org.dive4elements.river.artifacts.resources.Resources; teichmann@5831: import org.dive4elements.river.artifacts.states.DefaultState; raimund@3629: andre@8587: /* TODO: Change data facets to live in the generalized data scheme and andre@8587: * obsolute the obfuscated index magic. */ sascha@3750: ingo@3757: public class BedQualityState extends DefaultState implements FacetTypes { ingo@3757: ingo@3757: private static final long serialVersionUID = 1L; ingo@3757: teichmann@8202: private static final Logger log = Logger ingo@3757: .getLogger(BedQualityState.class); sascha@3750: andre@8587: /* The suffix to append to interpol facets. */ andre@8587: public static final String I18N_INTERPOL_SUFFIX = "facet.bedquality.interpol.suffix"; andre@8587: andre@8587: /* I18n is in the pattern base.. with the optional suffix .data */ andre@8587: public static final String I18N_FACET_BED_BASE = "facet.bedquality.bed"; andre@8587: andre@8587: /* Data Layers */ andre@8587: public static final String I18N_FACET_BEDLOAD_DIAMETER_DATA = "facet.bedquality.bed.diameter.bedload.data"; andre@8587: public static final String I18N_FACET_BED_DIAMETER_DATA_TOPLAYER = "facet.bedquality.bed.diameter.toplayer.data"; andre@8587: public static final String I18N_FACET_BED_DIAMETER_DATA_SUBLAYER = "facet.bedquality.bed.diameter.sublayer.data"; ingo@3767: public static final String I18N_TOPLAYER = "bedquality.toplayer"; ingo@3767: public static final String I18N_SUBLAYER = "bedquality.sublayer"; ingo@3767: rrenkert@6262: static { rrenkert@6262: // Active/deactivate facets. rrenkert@6262: FacetActivity.Registry.getInstance().register( rrenkert@6262: "minfo", rrenkert@6262: new FacetActivity() { rrenkert@6262: @Override rrenkert@6262: public Boolean isInitialActive( rrenkert@6262: Artifact artifact, rrenkert@6262: Facet facet, rrenkert@6262: String output rrenkert@6262: ) { andre@8592: String name = facet.getName().replace(".interpol",""); rrenkert@6262: if (name.equals(BED_QUALITY_SEDIMENT_DENSITY_TOPLAYER) || rrenkert@6262: name.equals(BED_QUALITY_SEDIMENT_DENSITY_SUBLAYER) || rrenkert@6262: name.equals(BED_DIAMETER_DATA_TOP) || rrenkert@6262: name.equals(BED_DIAMETER_DATA_SUB) || rrenkert@6262: name.equals(BEDLOAD_DIAMETER_DATA)){ rrenkert@6262: return Boolean.FALSE; rrenkert@6262: } tom@8274: if (name.equals(BED_QUALITY_POROSITY_TOPLAYER) || tom@8274: name.equals(BED_QUALITY_POROSITY_SUBLAYER) || tom@8274: name.equals(BED_QUALITY_BED_DIAMETER_TOPLAYER) || tom@8274: name.equals(BED_QUALITY_BED_DIAMETER_SUBLAYER) || tom@8274: name.equals(BED_QUALITY_BEDLOAD_DIAMETER)) { tom@8274: return Boolean.TRUE; rrenkert@6262: } tom@8274: return null; rrenkert@6262: } rrenkert@6262: }); rrenkert@6262: } rrenkert@6262: ingo@3749: @Override teichmann@5867: public Object computeAdvance(D4EArtifact artifact, String hash, ingo@3757: CallContext context, List facets, Object old) { teichmann@8202: log.debug("BedQualityState.computeAdvance"); raimund@3629: ingo@3749: List newFacets = new ArrayList(); ingo@3749: felix@4825: BedQualityAccess access = new BedQualityAccess(artifact, context); ingo@3749: ingo@3757: CalculationResult res = old instanceof CalculationResult ? (CalculationResult) old ingo@3749: : new BedQualityCalculation().calculate(access); ingo@3749: ingo@3749: if (facets == null || res == null) { ingo@3749: return res; ingo@3749: } ingo@3749: ingo@3762: BedQualityResult[] results = (BedQualityResult[]) res.getData(); ingo@3757: ingo@3762: if (results == null || results.length == 0) { teichmann@8202: log.warn("Calculation computed no results!"); ingo@3762: return res; ingo@3762: } ingo@3757: ingo@3767: generateFacets(context, newFacets, results, getID(), hash); andre@8587: generateDataFacets(context, newFacets, access, getID(), hash); teichmann@8202: log.debug("Created " + newFacets.size() + " new Facets."); ingo@3749: facets.addAll(newFacets); ingo@3749: ingo@3749: return res; ingo@3749: } ingo@3762: andre@8587: private int generateIndex(String diameter) { andre@8587: int d = 0; andre@8587: if(diameter.equals("d10")) { andre@8587: d = 1; andre@8587: } andre@8587: else if (diameter.equals("d16")) { andre@8587: d = 2; andre@8587: } andre@8587: else if (diameter.equals("d20")) { andre@8587: d = 3; andre@8587: } andre@8587: else if (diameter.equals("d25")) { andre@8587: d = 4; andre@8587: } andre@8587: else if (diameter.equals("d30")) { andre@8587: d = 5; andre@8587: } andre@8587: else if (diameter.equals("d40")) { andre@8587: d = 6; andre@8587: } andre@8587: else if (diameter.equals("d50")) { andre@8587: d = 7; andre@8587: } andre@8587: else if (diameter.equals("d60")) { andre@8587: d = 8; andre@8587: } andre@8587: else if (diameter.equals("d70")) { andre@8587: d = 9; andre@8587: } andre@8587: else if (diameter.equals("d75")) { andre@8587: d = 10; andre@8587: } andre@8587: else if (diameter.equals("d80")) { andre@8587: d = 11; andre@8587: } andre@8587: else if (diameter.equals("d84")) { andre@8587: d = 12; andre@8587: } andre@8587: else if (diameter.equals("d90")) { andre@8587: d = 13; andre@8587: } andre@8587: else if (diameter.equals("dmin")) { andre@8587: d = 14; andre@8587: } andre@8587: else if (diameter.equals("dmax")) { andre@8587: d = 15; andre@8587: } andre@8587: else if (diameter.equals("dm")) { andre@8587: d = 16; andre@8587: } andre@8587: int ndx = d << 1; andre@8587: return ndx; andre@8587: } andre@8587: rrenkert@6252: private void generateDataFacets( rrenkert@6252: CallContext context, rrenkert@6252: List newFacets, rrenkert@6252: BedQualityAccess access, rrenkert@6252: String stateId, rrenkert@6252: String hash) { rrenkert@6252: List diameters = access.getBedDiameter(); rrenkert@6262: List loadDiameters = access.getBedloadDiameter(); rrenkert@6252: List ranges = access.getDateRanges(); teichmann@7254: for (int i = 0, R = ranges.size(); i < R; i++) { rrenkert@6252: DateRange range = ranges.get(i); rrenkert@6252: for (String diameter: diameters) { rrenkert@6262: int ndxTop = generateIndex(diameter); andre@8587: int ndxSub = ndxTop; rrenkert@6262: ndxTop += 1; rrenkert@6262: ndxTop = ndxTop << 3; rrenkert@6262: ndxSub = ndxSub << 3; rrenkert@6262: ndxTop += i; rrenkert@6262: ndxSub += i; rrenkert@6252: String toplayer = rrenkert@6252: Resources.getMsg( rrenkert@6252: context.getMeta(), I18N_TOPLAYER, I18N_TOPLAYER); rrenkert@6252: String sublayer = rrenkert@6252: Resources.getMsg( rrenkert@6252: context.getMeta(), I18N_SUBLAYER, I18N_SUBLAYER); rrenkert@6252: //toplayer rrenkert@6252: newFacets.add(new BedDiameterDataFacet( rrenkert@6252: ndxTop, rrenkert@6252: BED_DIAMETER_DATA_TOP, rrenkert@6252: Resources.getMsg( rrenkert@6252: context.getMeta(), rrenkert@6252: I18N_FACET_BED_DIAMETER_DATA_TOPLAYER, rrenkert@6252: I18N_FACET_BED_DIAMETER_DATA_TOPLAYER, rrenkert@6252: new Object[] { diameter.toUpperCase(), rrenkert@6252: range.getFrom(), range.getTo(), toplayer}), rrenkert@6252: ComputeType.ADVANCE, rrenkert@6252: stateId, rrenkert@6252: hash)); rrenkert@6252: //sublayer rrenkert@6252: newFacets.add(new BedDiameterDataFacet( rrenkert@6252: ndxSub, rrenkert@6252: BED_DIAMETER_DATA_SUB, rrenkert@6252: Resources.getMsg( rrenkert@6252: context.getMeta(), rrenkert@6252: I18N_FACET_BED_DIAMETER_DATA_TOPLAYER, rrenkert@6252: I18N_FACET_BED_DIAMETER_DATA_TOPLAYER, rrenkert@6252: new Object[] { diameter.toUpperCase(), rrenkert@6252: range.getFrom(), range.getTo(), sublayer}), rrenkert@6252: ComputeType.ADVANCE, rrenkert@6252: stateId, rrenkert@6252: hash)); rrenkert@6252: } rrenkert@6262: for (String loadDiameter: loadDiameters) { rrenkert@6262: int ndx = generateIndex(loadDiameter); rrenkert@6262: ndx = ndx << 3; rrenkert@6262: ndx += i; rrenkert@6262: newFacets.add(new BedloadDiameterDataFacet( rrenkert@6262: ndx, rrenkert@6262: BEDLOAD_DIAMETER_DATA, rrenkert@6262: Resources.getMsg( rrenkert@6262: context.getMeta(), rrenkert@6262: I18N_FACET_BEDLOAD_DIAMETER_DATA, rrenkert@6262: I18N_FACET_BEDLOAD_DIAMETER_DATA, rrenkert@6262: new Object[] { loadDiameter.toUpperCase(), rrenkert@6262: range.getFrom(), range.getTo()}), rrenkert@6262: ComputeType.ADVANCE, rrenkert@6262: stateId, rrenkert@6262: hash)); rrenkert@6262: } rrenkert@6252: } rrenkert@6252: } rrenkert@6252: andre@8587: andre@8587: protected String getFacetName(BedQualityResultValue value) { andre@8587: /* basename + name or "diameter" + .type */ andre@8587: return BED_QUALITY_DATA_FACET + "." + andre@8587: (value.isDiameterResult() ? "diameter" : value.getName()) + "." + andre@8587: value.getType(); rrenkert@6252: } rrenkert@6252: ingo@3767: protected void generateFacets(CallContext context, List newFacets, ingo@3762: BedQualityResult[] results, String stateId, String hash) { teichmann@8202: log.debug("BedQualityState.generateFacets"); ingo@3762: ingo@3767: CallMeta meta = context.getMeta(); ingo@3767: ingo@3785: newFacets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); ingo@3762: for (int idx = 0; idx < results.length; idx++) { ingo@3762: BedQualityResult result = results[idx]; ingo@3784: DateRange range = result.getDateRange(); andre@8587: int i = 0; andre@8587: for (BedQualityResultValue value: result.getValues()) { andre@8587: newFacets.add(new BedQualityDataFacet((idx << 8) + i++, andre@8587: getFacetName(value), andre@8587: getFacetDescription(meta, range, value), ingo@3784: ComputeType.ADVANCE, andre@8587: stateId, hash, value.getName(), value.getType())); andre@8592: newFacets.add(new BedQualityInterpolFacet((idx << 8) + i++, andre@8592: getFacetName(value) + ".interpol", andre@8592: getFacetInterpolDescription(meta, range, value), andre@8592: ComputeType.ADVANCE, andre@8592: stateId, hash, value.getName(), value.getType())); ingo@3762: } ingo@3762: } ingo@3762: } ingo@3767: andre@8592: protected String getFacetInterpolDescription(CallMeta meta, andre@8592: DateRange range, andre@8592: BedQualityResultValue value) { andre@8592: String part1 = getFacetDescription(meta, range, value); andre@8592: /* We could add a step description here */ andre@8592: return part1 + " " + Resources.getMsg(meta, andre@8592: I18N_INTERPOL_SUFFIX, andre@8592: I18N_INTERPOL_SUFFIX, andre@8592: new Object[] {}); andre@8592: } andre@8592: andre@8592: andre@8587: protected String getFacetDescription(CallMeta meta, andre@8587: DateRange range, andre@8587: BedQualityResultValue value) { ingo@3767: Date from = range != null ? range.getFrom() : new Date(); ingo@3767: Date to = range != null ? range.getTo() : new Date(); sascha@3772: andre@8587: final String layerSuffix = andre@8587: Resources.getMsg(meta, "bedquality." + value.getType(), ""); andre@8587: andre@8587: /* This could probably be unified with the facet name */ andre@8587: final String i18n = I18N_FACET_BED_BASE + "." + andre@8587: (value.isDiameterResult() ? "diameter" : value.getName()) + "." + andre@8587: value.getType(); andre@8587: andre@8587: if (value.isDiameterResult()) { andre@8587: /* Include the diameter in the description */ andre@8587: return Resources.getMsg(meta, i18n, i18n, new Object[] { andre@8587: value.getName().toUpperCase(), from, to, layerSuffix }); andre@8585: } else { andre@8587: return Resources.getMsg(meta, i18n, i18n, new Object[] { from, to, layerSuffix }); andre@8585: } ingo@3767: } raimund@3629: }