/** * */ package nl.ipo.cds.admin.ba.controller; import static nl.ipo.cds.admin.ba.attributemapping.AttributeMappingUtils.getAttributeDescriptors; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javax.inject.Inject; import javax.validation.Valid; import nl.idgis.commons.jobexecutor.Job; import nl.idgis.commons.jobexecutor.JobCreator; import nl.ipo.cds.admin.ba.attributemapping.AttributeMappingUtils; import nl.ipo.cds.admin.ba.attributemapping.FeatureTypeCache; import nl.ipo.cds.admin.ba.attributemapping.OperationFactory; import nl.ipo.cds.admin.ba.controller.beans.mapping.Mapping; import nl.ipo.cds.admin.ba.util.GebruikerAuthorization; import nl.ipo.cds.admin.reporting.ReportConfiguration; import nl.ipo.cds.attributemapping.operations.discover.OperationDiscoverer; import nl.ipo.cds.dao.ManagerDao; import nl.ipo.cds.dao.attributemapping.AttributeMappingDao; import nl.ipo.cds.dao.attributemapping.OperationDTO; import nl.ipo.cds.domain.Bronhouder; import nl.ipo.cds.domain.BronhouderThema; import nl.ipo.cds.domain.Dataset; import nl.ipo.cds.domain.DatasetType; import nl.ipo.cds.domain.FeatureType; import nl.ipo.cds.domain.ImportJob; import nl.ipo.cds.domain.RefreshPolicy; import nl.ipo.cds.domain.RemoveJob; import nl.ipo.cds.domain.Thema; import nl.ipo.cds.domain.TransformJob; import nl.ipo.cds.domain.TypeGebruik; import nl.ipo.cds.etl.process.HarvesterException; import nl.ipo.cds.etl.theme.AttributeDescriptor; import nl.ipo.cds.etl.theme.ThemeConfig; import nl.ipo.cds.etl.theme.ThemeDiscoverer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; /** * Controller voor de dataset configuratie pagina.<br/> * @author Rob * */ @Controller public class DatasetController{ @Autowired private ManagerDao managerDao; @Autowired private JobCreator jobCreator; @Autowired private ReportConfiguration reportConfiguration; @Inject private ThemeDiscoverer themeDiscoverer; @Inject private FeatureTypeCache featureTypeCache; @Inject private OperationDiscoverer operationDiscoverer; @Inject private ConversionService conversionService; @ModelAttribute("roleFunction") String getRoleFunction(){ return "bronhouder"; } /** * Returns all datasets for the given bronhouder and theme. * * @param bronhouder The bronhouder to use as a filter. * @param thema The theme to use as a filter. * @return All datasets for the given bronhouder and theme. */ private List<Dataset> getDatasetsByBronhouderAndThema (final Bronhouder bronhouder, final Thema thema) { final List<Dataset> result = new ArrayList<Dataset> (); for (final Dataset dataset: managerDao.getDatasetsByBronhouder (bronhouder)) { if (dataset.getDatasetType ().getThema ().equals (thema)) { result.add (dataset); } } return Collections.unmodifiableList (result); } /** * Returns a list of bronhouders that are authorized to use themes, or that have * existing datasets. * * @return */ private Collection<Bronhouder> getBronhoudersWithThemesOrDatasets () { final SortedSet<Bronhouder> bronhouders = new TreeSet<Bronhouder> (new Comparator<Bronhouder> () { @Override public int compare (final Bronhouder o1, final Bronhouder o2) { return o1.getNaam ().compareTo (o2.getNaam ()); } }); // Add bronhouders that are associated with a theme: for (final BronhouderThema bronhouderThema: managerDao.getBronhouderThemas ()) { bronhouders.add (bronhouderThema.getBronhouder ()); } // Add bronhouders that are associated with a dataset: for (final Dataset dataset: managerDao.getAllDatasets ()) { bronhouders.add (dataset.getBronhouder ()); } return Collections.unmodifiableCollection (bronhouders); } /** * Returns a list of themes for which the given bronhouder either has permissions to use * it or existing datasets for that bronhouder exist which are related to the theme. * * @param bronhouder The bronhouder to use as a filter. * @return A collection of themes. */ private Collection<Thema> getThemesWithBronhouderOrDatasets (final Bronhouder bronhouder, final Collection<Thema> unauthorizedThemes) { final SortedSet<Thema> themas = new TreeSet<Thema> (new Comparator<Thema> () { @Override public int compare (final Thema o1, final Thema o2) { return o1.getNaam ().compareTo (o2.getNaam ()); } }); // Add themes that are directly associated with the given bronhouder: themas.addAll (managerDao.getAllThemas (bronhouder)); // Add themes that are associated with a dataset for this bronhouder: for (final Dataset dataset: managerDao.getDatasetsByBronhouder (bronhouder)) { final Thema thema = dataset.getDatasetType ().getThema (); if (!themas.contains (thema)) { unauthorizedThemes.add (dataset.getDatasetType ().getThema ()); themas.add (dataset.getDatasetType ().getThema ()); } } return Collections.unmodifiableCollection (themas); } @RequestMapping(value ="/ba/datasetconfig/{bronhouderId}", method = RequestMethod.GET) public String updateDatasetForm(final @PathVariable("bronhouderId") long bronhouderId, @RequestParam(value="thema", required=false) String themaName, Model model, final Principal principal) throws ThemeNotFoundException { final GebruikerAuthorization gebruikerAuthorization = new GebruikerAuthorization (managerDao.getGebruiker (principal.getName ()), TypeGebruik.DATABEHEERDER, managerDao); // Get bronhouder: final Bronhouder bronhouder = gebruikerAuthorization.getAuthorizedBronhouder (bronhouderId); if (bronhouder == null) { return "redirect:/ba"; } // Get the current thema: final Thema thema = gebruikerAuthorization.getAuthorizedThemaByName (themaName, bronhouder); // get all datasets from a bronhouder and put them in a map final List<Dataset> datasetList = getDatasetsByBronhouderAndThema (bronhouder, thema); // List themes: final Collection<Thema> themaList; final Collection<String> notAuthorizedThemaList = new ArrayList<String> (); if (gebruikerAuthorization.getGebruiker ().isSuperuser ()) { final List<Thema> unauthorizedThemas = new ArrayList<Thema> (); themaList = getThemesWithBronhouderOrDatasets (bronhouder, unauthorizedThemas); // add themas that are implicit in the datasetlist to the themalist // this happens when the datasetlist contains more datasets than the themaAuthorization allows for (final Thema t: unauthorizedThemas) { notAuthorizedThemaList.add (t.getNaam ()); } } else { themaList = gebruikerAuthorization.getAuthorizedThemas (bronhouder); } // List the attributes that are available in the theme: final ThemeConfig<?> themeConfig = themeDiscoverer.getThemeConfiguration (thema.getNaam ()); if (themeConfig == null) { throw new ThemeNotFoundException (thema.getNaam ()); } final int totalAttributeCount = themeConfig.getAttributeDescriptors ().size (); // a list of datasets for the current bronhouder and the current thema List<BronhouderDataset> bronhouderDatasetList = new ArrayList<BronhouderDataset>(); for (Dataset dataset : datasetList) { bronhouderDatasetList.add(new BronhouderDataset( dataset, managerDao.getValidAttributeMappings (dataset).size (), totalAttributeCount )); } /** check the authorization of the current user * fill the bronhouders list depending on the role * i.e. only the current bronhouder for role bronhouder * or all bronhouders for role beheerder */ // Use BronhouderNAW instead of Bronhouder because of the need to flag when a bronhouder has more datasets than it is authorized for final List<BronhouderNAW> bronhouderNAWList = new ArrayList<BronhouderNAW>(); if (gebruikerAuthorization.getGebruiker ().isSuperuser ()) { for (Bronhouder bronhouder2 : getBronhoudersWithThemesOrDatasets ()) { List<Thema> themaList1 = this.managerDao.getAllThemas(bronhouder2); List<Thema> themaList2 = new ArrayList<Thema>(); List <Dataset> datasetList2 = this.managerDao.getDatasetsByBronhouder(bronhouder2); for (Dataset dataset2 : datasetList2) { Thema datasetThema = dataset2.getDatasetType().getThema(); if (!themaList1.contains(datasetThema)){ themaList2.add(datasetThema); } } if (themaList2.isEmpty()){ bronhouderNAWList.add(new BronhouderNAW (bronhouder2, false)); }else{ //flag this bronhouder as having datasets it is not authorized to have bronhouderNAWList.add(new BronhouderNAW (bronhouder2, true)); } } } else { for (final Bronhouder b: gebruikerAuthorization.getAuthorizedBronhouders ()) { bronhouderNAWList.add (new BronhouderNAW (b, false)); } } model.addAttribute("bronhouders", bronhouderNAWList); model.addAttribute("bronhouder", bronhouder); model.addAttribute("themaList", themaList); model.addAttribute("notAuthorizedThemaList", notAuthorizedThemaList); model.addAttribute("currentThema", thema); model.addAttribute("bronhouderDatasetList", bronhouderDatasetList); model.addAttribute("pgrBaseUrl", reportConfiguration.getPgrBaseUrl ()); return "/ba/datasetconfig"; } /** * Performs actions of the Dataset configuration view.<br/> * A dataset can be removed, added, updated (uuid) and made (in)active.<br/> * The proper working depends on the lists having the order in which items appear on the html form. * @return view url */ @Transactional @RequestMapping(value ="/ba/datasetconfig/{bronhouderId}", method = RequestMethod.POST) public String updateDataset(@PathVariable Long bronhouderId, @RequestParam(value="thema", required=true) String themaName, @ModelAttribute BronhouderDatasetForm bronhouderDatasetForm, Model model, RedirectAttributes redirectAttributes, RefreshPolicy refreshPolicy) { //w1502 019 for (BronhouderDataset bronhouderDataset : bronhouderDatasetForm.getBronhouderDatasets()) { Dataset dataset = this.managerDao.getDataSet(bronhouderDataset.getId()); if (dataset.getBronhouder().getId().equals(bronhouderId)) { if (dataset.getDatasetType().getNaam().equals(bronhouderDataset.getType())) { dataset.setNaam(bronhouderDataset.getNaam()); dataset.setActief(bronhouderDataset.isActief()); // W1502 019 dataset.setRefreshPolicy(bronhouderDataset.getRefreshPolicy()); final String oldUuid = dataset.getUuid(); final String newUuid = bronhouderDataset.getUuid(); if (!oldUuid.equals(newUuid)) { dataset.setUuid(newUuid); removeAndReimportDataAfterUuidChange(dataset, oldUuid, newUuid); } this.managerDao.update(dataset); } } } // Redirect after POST pattern redirectAttributes.addAttribute ("thema", themaName); return "redirect:/ba/datasetconfig/" + bronhouderId; } private void removeAndReimportDataAfterUuidChange(final Dataset dataset, final String oldUuid, final String newUuid ) { final RemoveJob deleteJob = new RemoveJob (); deleteJob.setBronhouder(dataset.getBronhouder()); deleteJob.setDatasetType(dataset.getDatasetType()); deleteJob.setUuid(oldUuid); jobCreator.putJob (deleteJob); final ImportJob job = new ImportJob (); job.setBronhouder(dataset.getBronhouder()); job.setDatasetType(dataset.getDatasetType()); job.setUuid(newUuid); job.setForceExecution(true); jobCreator.putJob (job); if(this.managerDao.getLastTransformJob(Job.Status.CREATED) == null){ final TransformJob transformJob = new TransformJob (); managerDao.create (transformJob); } } @Transactional @RequestMapping(value ="/ba/remove_datasetconfig/{bronhouderId}", method = RequestMethod.GET) public String removeDataset(final @PathVariable("bronhouderId") long bronhouderId, @RequestParam(value="datasetId", required=false)Long datasetId, Model model, final RedirectAttributes redirectAttributes, final Principal principal) { final GebruikerAuthorization gebruikerAuthorization = new GebruikerAuthorization (managerDao.getGebruiker (principal.getName ()), TypeGebruik.DATABEHEERDER, managerDao); // Get bronhouder: final Bronhouder bronhouder = gebruikerAuthorization.getAuthorizedBronhouder (bronhouderId); if (bronhouder == null) { return "redirect:/ba"; } Dataset dataset = this.managerDao.getDataSet(datasetId); final String themaNaam = dataset.getDatasetType ().getThema ().getNaam (); // NB deleten van dataset gebeurt in ETL-proces dmv een delete job final RemoveJob deleteJob = new RemoveJob (); deleteJob.setBronhouder(bronhouder); deleteJob.setDatasetType(dataset.getDatasetType()); deleteJob.setUuid(dataset.getUuid()); jobCreator.putJob (deleteJob); managerDao.delete (dataset); /* Check whether to create a transform Job, by checking if there is already a TRANSFORM job that * hasn't started yet */ if(this.managerDao.getLastTransformJob(Job.Status.CREATED) == null){ final TransformJob transformJob = new TransformJob (); managerDao.create (transformJob); } redirectAttributes.addAttribute ("thema", themaNaam); return "redirect:/ba/datasetconfig/" + bronhouder.getId(); } @RequestMapping(value ="/ba/add_datasetconfig/{bronhouderId}", method = RequestMethod.GET) public String addDatasetForm(final @PathVariable("bronhouderId") long bronhouderId, @RequestParam(value="thema", required=true) String themaName, Model model, final Principal principal) { final GebruikerAuthorization gebruikerAuthorization = new GebruikerAuthorization (managerDao.getGebruiker (principal.getName ()), TypeGebruik.DATABEHEERDER, managerDao); // Get bronhouder: final Bronhouder bronhouder = gebruikerAuthorization.getAuthorizedBronhouder (bronhouderId); if (bronhouder == null) { return "redirect:/ba"; } Thema thema = managerDao.getThemaByName(themaName); // check thema List<Thema> themaList = this.managerDao.getAllThemas(bronhouder); if (!themaList.contains(thema)){ // if the bronhouder does not have the current thema then get the first thema from bronhouder thema = themaList.get(0); } List<DatasetType> datasetTypes = this.managerDao.getDatasetTypesByThema(thema); model.addAttribute("bronhouder", bronhouder); model.addAttribute("thema", thema); model.addAttribute("datasetTypes", datasetTypes); model.addAttribute("viewName", "/ba/datasetconfig"); if(!model.containsAttribute("datasetForm")) { model.addAttribute("datasetForm", new DatasetForm()); } return "ba/add_datasetconfig"; } @RequestMapping(value ="/ba/add_datasetconfig/{bronhouderId}", method = RequestMethod.POST) @Transactional public String addDataset(final @PathVariable("bronhouderId") long bronhouderId, @ModelAttribute("datasetForm") @Valid DatasetForm datasetForm, BindingResult bindingResult, Model model, final RedirectAttributes redirectAttributes, final Principal principal) throws ThemeNotFoundException, HarvesterException, MappingParserException { final GebruikerAuthorization gebruikerAuthorization = new GebruikerAuthorization (managerDao.getGebruiker (principal.getName ()), TypeGebruik.DATABEHEERDER, managerDao); // Get bronhouder: final Bronhouder bronhouder = gebruikerAuthorization.getAuthorizedBronhouder (bronhouderId); if (bronhouder == null) { return "redirect:/ba"; } if(bindingResult.hasErrors()) { return addDatasetForm(bronhouderId, datasetForm.getThema(), model, principal); } // default refresh policy value mast be "MANUAL" W1502 019 Dataset dataset = new Dataset(); dataset.setActief(true); dataset.setBronhouder(bronhouder); dataset.setUuid(datasetForm.getUuid()); dataset.setNaam(datasetForm.getNaam()); //W1502 019 dataset.setRefreshPolicy(RefreshPolicy.MANUAL); dataset.setDatasetType(this.managerDao.getDatasetType(datasetForm.getDatasettypeId())); this.managerDao.create(dataset); // configure any dataset mapping templates configureMappings(dataset); redirectAttributes.addAttribute ("thema", datasetForm.getThema ()); return "redirect:/ba/datasetconfig/" + bronhouder.getId(); } /** * Configure and persist any template mappings associated with the dataset. * * @param dataset * @throws ThemeNotFoundException * @throws HarvesterException * @throws MappingParserException */ private void configureMappings(Dataset dataset) throws ThemeNotFoundException, HarvesterException, MappingParserException { final Set<AttributeDescriptor<?>> attributeDescriptors = getAttributeDescriptors(themeDiscoverer, dataset); final FeatureType featureType = featureTypeCache.getFeatureType(dataset); final AttributeMappingDao dao = new AttributeMappingDao(managerDao); final ThemeConfig<?> themeConfig = themeDiscoverer.getThemeConfiguration(dataset.getDatasetType().getThema() .getNaam()); for (AttributeDescriptor<?> attributeDescriptor : attributeDescriptors) { final Mapping mapping = themeConfig.getDefaultMappingForAttributeType(attributeDescriptor); if (mapping==null) { // skip mapping if no template is available continue; } // Convert mapping to an operation tree used in the dao: final OperationFactory factory = new OperationFactory (attributeDescriptor, operationDiscoverer.getOperationTypes(), featureType, conversionService); final OperationDTO operationTree = factory.buildOperationCommand (mapping); // Determine whether the mapping is valid: final OperationDTO rootOperation = (OperationDTO) operationTree.getInputs().get(0).getOperation(); final boolean isValid = AttributeMappingUtils.isMappingValid(rootOperation, attributeDescriptor, featureType); // Save the mapping: dao.putAttributeMapping(dataset, attributeDescriptor, rootOperation, isValid); } } }