Java tutorial
/* * polymap.org Copyright 2013 Polymap GmbH. All rights reserved. * * This is free software; you can redistribute it and/or modify it under the terms of * the GNU Lesser General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ package org.polymap.kaps.ui.form; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.geotools.data.FeatureStore; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.Feature; import org.opengis.feature.type.PropertyDescriptor; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.qi4j.api.entity.association.Association; import org.qi4j.api.property.Property; import org.qi4j.api.query.QueryExpressions; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.polymap.core.data.PipelineFeatureSource; import org.polymap.core.data.operations.ModifyFeaturesOperation; import org.polymap.core.data.ui.featuretable.DefaultFeatureTableColumn; import org.polymap.core.data.ui.featuretable.FeatureTableViewer; import org.polymap.core.mapeditor.MapEditor; import org.polymap.core.model.EntityType; import org.polymap.core.operation.OperationSupport; import org.polymap.core.project.ILayer; import org.polymap.core.project.IMap; import org.polymap.core.qi4j.QiModule.EntityCreator; import org.polymap.core.runtime.Polymap; import org.polymap.core.workbench.PolymapWorkbench; import org.polymap.rhei.data.entityfeature.AssociationAdapter; import org.polymap.rhei.data.entityfeature.PropertyAdapter; import org.polymap.rhei.data.entityfeature.PropertyDescriptorAdapter; import org.polymap.rhei.data.entityfeature.ReloadablePropertyAdapter; import org.polymap.rhei.data.entityfeature.ReloadablePropertyAdapter.AssociationCallback; import org.polymap.rhei.data.entityfeature.ReloadablePropertyAdapter.PropertyCallback; import org.polymap.rhei.field.DateTimeFormField; import org.polymap.rhei.field.FormFieldEvent; import org.polymap.rhei.field.IFormFieldListener; import org.polymap.rhei.field.PicklistFormField; import org.polymap.rhei.field.StringFormField; import org.polymap.rhei.form.IFormEditorPage2; import org.polymap.rhei.form.IFormEditorPageSite; import org.polymap.kaps.KapsPlugin; import org.polymap.kaps.model.KapsRepository; import org.polymap.kaps.model.data.BodenRichtwertRichtlinieArtDerNutzungComposite; import org.polymap.kaps.model.data.BodenRichtwertRichtlinieErgaenzungComposite; import org.polymap.kaps.model.data.BodennutzungComposite; import org.polymap.kaps.model.data.EntwicklungsZustandComposite; import org.polymap.kaps.model.data.ErschliessungsBeitragComposite; import org.polymap.kaps.model.data.GemeindeComposite; import org.polymap.kaps.model.data.NutzungComposite; import org.polymap.kaps.model.data.RichtwertZoneLageComposite; import org.polymap.kaps.model.data.RichtwertzoneComposite; import org.polymap.kaps.model.data.RichtwertzoneZeitraumComposite; import org.polymap.kaps.model.data.VertragsdatenAgrarComposite; import org.polymap.kaps.model.data.VertragsdatenBaulandComposite; import org.polymap.kaps.ui.KapsDefaultFormEditorPageWithFeatureTable; import org.polymap.kaps.ui.MyNumberValidator; import org.polymap.kaps.ui.NotNullValidator; /** * @author <a href="http://www.polymap.de">Steffen Stundzig</a> */ public class RichtwertzoneGrunddatenFormEditorPage extends KapsDefaultFormEditorPageWithFeatureTable<RichtwertzoneZeitraumComposite> implements IFormEditorPage2 { private static Log log = LogFactory.getLog(RichtwertzoneGrunddatenFormEditorPage.class); private final static String prefix = RichtwertzoneGrunddatenFormEditorPage.class.getSimpleName(); protected RichtwertzoneComposite richtwertzone; private BodenRichtwertRichtlinieArtDerNutzungComposite selectedNutzung; private IFormFieldListener nutzungListener; private EntwicklungsZustandComposite selectedZustand; public RichtwertzoneGrunddatenFormEditorPage(Feature feature, FeatureStore featureStore) { super(RichtwertzoneZeitraumComposite.class, RichtwertzoneGrunddatenFormEditorPage.class.getName(), "Grunddaten", feature, featureStore); richtwertzone = lookupRichtwertzoneComposite(); } protected RichtwertzoneComposite lookupRichtwertzoneComposite() { return repository.findEntity(RichtwertzoneComposite.class, feature.getIdentifier().getID()); } @Override public Action[] getEditorActions() { if (richtwertzone.geom().get() == null) { Action action = new Action("Geometrie anlegen") { public void run() { try { ILayer layer = ((PipelineFeatureSource) fs).getLayer(); IMap map = layer.getMap(); MapEditor mapEditor = MapEditor.openMap(map, true); boolean yes = MessageDialog.openConfirm(PolymapWorkbench.getShellToParentOn(), "Geometrie anlegen", "Die Geometrie fr die Richtwertzone wird im aktuellen Kartenausschnitt angelegt. " + "Diese Standardgeometrie dient als Basis und muss nachbearbeitet werden.\n\n" + "Ist der aktuelle Kartenausschnitt (etwa) richtig fr die Richtwertzone?"); if (yes) { ReferencedEnvelope mapExtent = map.getExtent(); GeometryFactory gf = new GeometryFactory(); Polygon polygon = (Polygon) gf.toGeometry(mapExtent); polygon = (Polygon) polygon.buffer((mapExtent.getWidth() / 20) * -1); MultiPolygon geom = gf.createMultiPolygon(new Polygon[] { polygon }); ModifyFeaturesOperation op = new ModifyFeaturesOperation(layer, fs, feature.getIdentifier().getID(), "geom", geom); OperationSupport.instance().execute(op, true, false); // richtwertzone.geom().set( geom ); // WMSLayer ollayer = ((WMSLayer)mapEditor.findLayer( // layer )); // if (ollayer == null) { // layer.setVisible( true ); // } // else { // ollayer.redraw( true ); // } } } catch (Exception e) { PolymapWorkbench.handleError(KapsPlugin.PLUGIN_ID, RichtwertzoneGrunddatenFormEditorPage.this, "Die Geometrie konnte nicht angelegt werden.", e); } }; }; action.setImageDescriptor(ImageDescriptor .createFromURL(KapsPlugin.getDefault().getBundle().getResource("icons/add.gif"))); action.setToolTipText( "Fr importierte Richtwertzonen ohne Geometrie wird eine Geometrie im aktuellen Kartenausschnitt angelegt"); return new Action[] { action }; } return null; } @Override public void createFormContent(final IFormEditorPageSite site) { super.createFormContent(site); site.setEditorTitle(formattedTitle("Richtwertzone", richtwertzone.schl().get(), null)); site.setFormTitle(formattedTitle("Richtwertzone", richtwertzone.schl().get(), getTitle())); Composite parent = site.getPageBody(); Control top = createGrunddatenForm(parent); top = createZeitraumForm(parent, top); createTableForm(parent, top, true); } private Control createGrunddatenForm(Composite parent) { GemeindeComposite gemeinde = richtwertzone.gemeinde().get(); Composite newLine, lastLine = null; newLine = newFormField("Gemeinde").setEnabled(true)//richtwertzone.gemeinde().get() == null ) .setProperty(new AssociationAdapter<GemeindeComposite>(richtwertzone.gemeinde())) .setField(namedAssocationsPicklist(GemeindeComposite.class)).setValidator(new NotNullValidator()) .setLayoutData(left().top(lastLine).create()).create(); newFormField("Bezeichnung").setProperty(new PropertyAdapter(richtwertzone.name())) .setField(new StringFormField()).setLayoutData(right().top(lastLine).create()).create(); lastLine = newLine; newLine = newFormField("Zone").setEnabled(richtwertzone.schl().get() == null) .setProperty(new PropertyAdapter(richtwertzone.schl())).setValidator(new NotNullValidator()) .setField(new StringFormField()).setLayoutData(left().top(lastLine).create()).create(); // TODO einfach immer anlassen ist wohl am einfachsten oder? // boolean lageEnabled = (gemeinde != null && gemeinde.einwohner().get() > // 50000); final Composite lage = newFormField("Lage (STALA)") /* .setEnabled( lageEnabled ) */ .setProperty(new AssociationAdapter<RichtwertZoneLageComposite>(richtwertzone.lage())) .setField(namedAssocationsPicklist(RichtwertZoneLageComposite.class)) .setLayoutData(right().top(lastLine).create()).create(); lastLine = newLine; newLine = newFormField("GFZ-Bereich").setProperty(new PropertyAdapter(richtwertzone.gfzBereich())) .setField(new StringFormField()).setLayoutData(right().top(lastLine).create()).create(); lastLine = newLine; newLine = newFormField("Entwicklungszustand") .setProperty( new AssociationAdapter<EntwicklungsZustandComposite>(richtwertzone.entwicklungsZustand())) .setField(namedAssocationsPicklist(EntwicklungsZustandComposite.class)) .setLayoutData(left().top(lastLine).create()).create(); selectedZustand = richtwertzone.entwicklungsZustand().get(); lastLine = newLine; final PicklistFormField artList = new PicklistFormField(new PicklistFormField.ValueProvider() { @Override public SortedMap<String, Object> get() { SortedMap<String, Object> values = new TreeMap<String, Object>(); if (selectedZustand != null) { String zustand = selectedZustand.schl().get(); String art = null; BodenRichtwertRichtlinieArtDerNutzungComposite template = QueryExpressions .templateFor(BodenRichtwertRichtlinieArtDerNutzungComposite.class); if ("B".equals(zustand) || "R".equals(zustand) || "E".equals(zustand)) { art = "1"; } else if ("LF".equals(zustand)) { art = "2"; } else { art = "3"; } for (BodenRichtwertRichtlinieArtDerNutzungComposite be : repository.findEntities( BodenRichtwertRichtlinieArtDerNutzungComposite.class, QueryExpressions.eq(template.entwickungsZustand(), art), 0, 1000)) { values.put(be.schl().get() + " - " + be.name().get(), be); } } return values; } }); newLine = newFormField("Nutzung BRW-RL") .setToolTipText("Art der Nutzung entsprechend Bodenrichtwert-Richtlinie") .setProperty(new AssociationAdapter<BodenRichtwertRichtlinieArtDerNutzungComposite>( richtwertzone.brwrlArt())) .setField(artList).setLayoutData(left().top(lastLine).create()).create(); selectedNutzung = richtwertzone.brwrlArt().get(); final PicklistFormField ergaenzungList = new PicklistFormField(new PicklistFormField.ValueProvider() { @Override public SortedMap<String, Object> get() { SortedMap<String, Object> values = new TreeMap<String, Object>(); if (selectedNutzung != null) { String art = selectedNutzung.nummer().get(); for (BodenRichtwertRichtlinieErgaenzungComposite be : repository .findEntities(BodenRichtwertRichtlinieErgaenzungComposite.class, null, 0, 1000)) { String ergaenzung = be.nummer().get(); if (ergaenzung.startsWith(art) || (ergaenzung.equals("1-4.3") && (art.startsWith("1") || art.startsWith("2") || art.startsWith("3") || art.startsWith("4")))) { // values.put( be.nummer().get() + " " + be.name().get() // + "(" + be.schl().get() + ")", be ); values.put(be.schl().get() + " - " + be.name().get(), be); } } } return values; } }); newFormField("Ergnzung").setToolTipText("Ergnzung zur Nutzung entprechend Bodenrichtwert-Richtlinie") .setProperty(new AssociationAdapter<BodenRichtwertRichtlinieErgaenzungComposite>( richtwertzone.brwrlErgaenzung())) .setField(ergaenzungList).setLayoutData(right().top(lastLine).create()).create(); pageSite.addFieldListener(nutzungListener = new IFormFieldListener() { @Override public void fieldChange(FormFieldEvent ev) { if (ev.getEventCode() == VALUE_CHANGE) { if (ev.getFieldName() .equalsIgnoreCase(richtwertzone.entwicklungsZustand().qualifiedName().name())) { if ((ev.getNewValue() == null && selectedZustand != null) || !ev.getNewValue().equals(selectedZustand)) { selectedZustand = ev.getNewValue(); artList.reloadValues(); selectedNutzung = null; ergaenzungList.reloadValues(); } } else if (ev.getFieldName() .equalsIgnoreCase(richtwertzone.brwrlArt().qualifiedName().name())) { if (ev.getNewValue() != null && !ev.getNewValue().equals(selectedNutzung)) { selectedNutzung = ev.getNewValue(); ergaenzungList.reloadValues(); } } } } }); lastLine = newLine; newLine = newFormField("Nutzung").setToolTipText("Wird nicht mehr verwendet, da nicht BRW-RL konform.") .setEnabled(false).setProperty(new AssociationAdapter<NutzungComposite>(richtwertzone.nutzung())) .setField(namedAssocationsPicklist(NutzungComposite.class)) .setLayoutData(left().top(lastLine).create()).create(); newFormField("Bodennutzung").setToolTipText("Wird nicht mehr verwendet, da nicht BRW-RL konform.") .setEnabled(false) .setProperty(new AssociationAdapter<BodennutzungComposite>(richtwertzone.bodenNutzung())) .setField(namedAssocationsPicklist(BodennutzungComposite.class)) .setLayoutData(right().top(lastLine).create()).create(); // site.addFieldListener( gemeindeListener = new IFormFieldListener() { // // @Override // public void fieldChange( FormFieldEvent ev ) { // if (ev.getFieldName().equals( "gemeinde" )) { // GemeindeComposite gemeinde = (GemeindeComposite)ev.getNewValue(); // lage.setEnabled( gemeinde != null && gemeinde.einwohner().get() > 50000 ); // } // } // } ); lastLine = newLine; return newLine; } private Control createZeitraumForm(Composite parent, Control top) { Composite newLine, lastLine = null; newLine = newFormField("Bezeichnung").setParent(parent) .setProperty(new ReloadablePropertyAdapter<RichtwertzoneZeitraumComposite>(selectedComposite, prefix + "name", new PropertyCallback<RichtwertzoneZeitraumComposite>() { @Override public Property get(RichtwertzoneZeitraumComposite entity) { return entity.name(); } })) .setField(reloadable(new StringFormField())).setLayoutData(left().top(top).create()).create(); lastLine = newLine; newLine = newFormField("Gltig ab").setParent(parent) .setProperty(new ReloadablePropertyAdapter<RichtwertzoneZeitraumComposite>(selectedComposite, prefix + "gueltigAb", new PropertyCallback<RichtwertzoneZeitraumComposite>() { @Override public Property get(RichtwertzoneZeitraumComposite entity) { return entity.gueltigAb(); } })) .setField(reloadable(new DateTimeFormField()))// .setValidator( // new // NotNullValidator() // ) .setLayoutData(left().top(lastLine).create()).create(); newFormField("Stichtag").setParent(parent) .setProperty(new ReloadablePropertyAdapter<RichtwertzoneZeitraumComposite>(selectedComposite, prefix + "stichtag", new PropertyCallback<RichtwertzoneZeitraumComposite>() { @Override public Property get(RichtwertzoneZeitraumComposite entity) { return entity.stichtag(); } })) .setField(reloadable(new DateTimeFormField()))// .setValidator( // new // NotNullValidator() // ) .setLayoutData(right().top(lastLine).create()).create(); lastLine = newLine; newLine = newFormField(" pro m").setParent(parent) .setProperty(new ReloadablePropertyAdapter<RichtwertzoneZeitraumComposite>(selectedComposite, prefix + "euroQm", new PropertyCallback<RichtwertzoneZeitraumComposite>() { @Override public Property get(RichtwertzoneZeitraumComposite entity) { return entity.euroQm(); } })) .setField(reloadable(new StringFormField(StringFormField.Style.ALIGN_RIGHT))) .setValidator(new MyNumberValidator(Double.class, 2)).setLayoutData(left().top(lastLine).create()) .create(); lastLine = newLine; newLine = newFormField("EB").setParent(parent) .setProperty(new ReloadablePropertyAdapter<RichtwertzoneZeitraumComposite>(selectedComposite, prefix + "erschliessungsBeitrag", new AssociationCallback<RichtwertzoneZeitraumComposite>() { @Override public Association get(RichtwertzoneZeitraumComposite entity) { return entity.erschliessungsBeitrag(); } })) .setField(reloadable(namedAssocationsPicklist(ErschliessungsBeitragComposite.class))) .setLayoutData(left().top(lastLine).create()).create(); return newLine; } @Override protected EntityType addViewerColumns(FeatureTableViewer viewer) { final KapsRepository repo = KapsRepository.instance(); final EntityType<RichtwertzoneZeitraumComposite> type = repo .entityType(RichtwertzoneZeitraumComposite.class); PropertyDescriptor prop = null; prop = new PropertyDescriptorAdapter(type.getProperty("name")); viewer.addColumn(new DefaultFeatureTableColumn(prop).setHeader("Bezeichnung")); prop = new PropertyDescriptorAdapter(type.getProperty("gueltigAb")); viewer.addColumn(new DefaultFeatureTableColumn(prop).setHeader("Gltig ab")); prop = new PropertyDescriptorAdapter(type.getProperty("stichtag")); viewer.addColumn(new DefaultFeatureTableColumn(prop).setHeader("Stichtag")); prop = new PropertyDescriptorAdapter(type.getProperty("euroQm")); viewer.addColumn(new DefaultFeatureTableColumn(prop).setHeader(" pro m")); return type; } @Override protected Iterable<RichtwertzoneZeitraumComposite> getElements() { return RichtwertzoneZeitraumComposite.Mixin.forZone(richtwertzone); } @Override protected RichtwertzoneZeitraumComposite createNewComposite() throws Exception { return repository.newEntity(RichtwertzoneZeitraumComposite.class, null, new EntityCreator<RichtwertzoneZeitraumComposite>() { public void create(RichtwertzoneZeitraumComposite prototype) throws Exception { prototype.zone().set(richtwertzone); prototype.schl().set(richtwertzone.schl().get()); prototype.name().set(richtwertzone.name().get()); } }); } @Override public void updateElements(Collection<RichtwertzoneZeitraumComposite> coll) { super.updateElements(coll); RichtwertzoneZeitraumComposite latest = null; for (RichtwertzoneZeitraumComposite current : coll) { if (latest == null) { latest = current; } else if (latest.gueltigAb().get() == null && current.gueltigAb().get() == null) { // do nothing } else if ((latest.gueltigAb().get() == null && current.gueltigAb().get() != null) || (current.gueltigAb().get() != null && latest.gueltigAb().get().before(current.gueltigAb().get()))) { latest = current; } richtwertzone.latestZone().set(latest); } } @Override protected void queueDeleteComposite(RichtwertzoneZeitraumComposite entity) { final Set<String> vertrag = new HashSet<String>(); for (VertragsdatenBaulandComposite bauland : VertragsdatenBaulandComposite.Mixin.forRWZ(entity)) { vertrag.add(EingangsNummerFormatter.format(bauland.vertrag().get().eingangsNr().get())); } for (VertragsdatenAgrarComposite agrar : VertragsdatenAgrarComposite.Mixin.forRWZ(entity)) { vertrag.add(EingangsNummerFormatter.format(agrar.vertrag().get().eingangsNr().get())); } if (!vertrag.isEmpty()) { Polymap.getSessionDisplay().asyncExec(new Runnable() { public void run() { MessageDialog.openError(PolymapWorkbench.getShellToParentOn(), "Fehler beim Lschen", "Diese Richtwertzone wird noch benutzt in " + StringUtils.join(vertrag, ", ") + " !"); } }); } else { super.queueDeleteComposite(entity); } } }