package de.cinovo.cloudconductor.server.util;
/*
* #%L cloudconductor-server %% Copyright (C) 2013 - 2014 Cinovo AG %% Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License. #L%
*/
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import de.cinovo.cloudconductor.api.model.Dependency;
import de.cinovo.cloudconductor.api.model.PackageVersion;
import de.cinovo.cloudconductor.server.comparators.PackageVersionComparator;
import de.cinovo.cloudconductor.server.dao.IDependencyDAO;
import de.cinovo.cloudconductor.server.dao.IFileDAO;
import de.cinovo.cloudconductor.server.dao.IPackageDAO;
import de.cinovo.cloudconductor.server.dao.IPackageVersionDAO;
import de.cinovo.cloudconductor.server.dao.ITemplateDAO;
import de.cinovo.cloudconductor.server.model.EDependency;
import de.cinovo.cloudconductor.server.model.EFile;
import de.cinovo.cloudconductor.server.model.EPackage;
import de.cinovo.cloudconductor.server.model.EPackageVersion;
import de.cinovo.cloudconductor.server.model.ETemplate;
import de.cinovo.cloudconductor.server.rest.helper.AMConverter;
import de.taimos.restutils.RESTAssert;
/**
* Copyright 2013 Cinovo AG<br>
* <br>
*
* @author psigloch
*
*/
@Service
public class PackageImport implements IPackageImport {
@Autowired
private IPackageDAO dpkg;
@Autowired
private IFileDAO dcfg;
@Autowired
private ITemplateDAO dtemplate;
@Autowired
private IPackageVersionDAO drpm;
@Autowired
private IDependencyDAO ddep;
@Autowired
private AMConverter amc;
@Override
@Transactional
public void importVersions(Set<PackageVersion> rpms) {
RESTAssert.assertNotEmpty(rpms);
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
HashMap<String, Set<String>> provided = new HashMap<>();
for (PackageVersion rpm : rpms) {
// Retrieve the package for the given RPM. Create it if it doesn't exist.
EPackage mpkg = this.dpkg.findByName(rpm.getName());
if (mpkg == null) { // there is no package for this RPM yet
mpkg = new EPackage();
mpkg.setName(rpm.getName());
mpkg.setDescription("Auto-generated from repository update on " + sdf.format(Calendar.getInstance().getTime()) + ".");
mpkg = this.dpkg.save(mpkg);
}
if (!provided.containsKey(mpkg.getName())) {
provided.put(mpkg.getName(), new HashSet<String>());
}
// Check if we have this particular RPM version on record.
EPackageVersion mrpm = this.drpm.find(rpm.getName(), rpm.getVersion());
provided.get(mpkg.getName()).add(rpm.getVersion());
// We already have this package version. Move on.
if (mrpm != null) {
mrpm.setDeprecated(false);
this.drpm.save(mrpm);
continue;
}
// Create a new version for the package.
mrpm = this.amc.toModel(rpm);
mrpm.setPkg(mpkg);
// Convert API dependency object to entities, add them to the package version, and save.
Set<EDependency> result = new HashSet<>();
if (rpm.getDependencies() != null) {
for (Dependency d : rpm.getDependencies()) {
EDependency md = this.ddep.save(this.amc.toModel(d));
result.add(md);
}
}
mrpm.setDependencies(result);
this.drpm.save(mrpm);
}
// perform db clean up
List<EPackage> inDB = this.dpkg.findList();
List<ETemplate> templates = this.dtemplate.findList();
List<EFile> cfgs = this.dcfg.findList();
for (EPackage pkg : inDB) {
if (provided.containsKey(pkg.getName())) {
// clean up rpm list
this.handleRPMUsage(provided.get(pkg.getName()), pkg.getRPMs(), templates);
continue;
}
// check if it's used somewhere within configfiles
for (EFile cfg : cfgs) {
if ((cfg.getPkg() != null) && cfg.getPkg().equals(pkg)) {
cfg.setPkg(null);
this.dcfg.save(cfg);
}
}
// clean up rpm list
boolean inUse = this.handleRPMUsage(null, pkg.getRPMs(), templates);
if (!inUse) {
this.dpkg.deleteById(pkg.getId());
}
}
this.autoUpdate(templates);
}
private boolean handleRPMUsage(Set<String> provided, Set<EPackageVersion> existing, List<ETemplate> templates) {
boolean deprecated = false;
if (existing == null) {
return deprecated;
}
for (EPackageVersion dbrpm : existing) {
if ((provided != null) && provided.contains(dbrpm.getName())) {
continue;
}
boolean found = false;
// check if it's used somewhere
for (ETemplate t : templates) {
if (t.getPackageVersions().contains(dbrpm)) {
// mark deprecated
dbrpm.setDeprecated(true);
found = true;
break;
}
}
if (found) {
this.drpm.save(dbrpm);
deprecated = true;
} else {
// delete it
this.drpm.deleteById(dbrpm.getId());
}
}
return deprecated;
}
private void autoUpdate(List<ETemplate> templates) {
PackageVersionComparator rpmComp = new PackageVersionComparator();
for (ETemplate t : templates) {
if ((t.getAutoUpdate() == null) || !t.getAutoUpdate()) {
continue;
}
List<EPackageVersion> list = new ArrayList<>(t.getPackageVersions());
for (EPackageVersion rpm : t.getPackageVersions()) {
List<EPackageVersion> eprpms = new ArrayList<>(rpm.getPkg().getRPMs());
Collections.sort(eprpms, rpmComp);
EPackageVersion newest = eprpms.get(eprpms.size() - 1);
if (!newest.equals(rpm)) {
list.remove(rpm);
list.add(newest);
}
}
t.setPackageVersions(list);
this.dtemplate.save(t);
}
}
}