class ImportEndpoint {

	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	@Transactional
	public ImportResult importERD(final EntityRelationDiagram erd) {
		ImportResult result = new ImportResult();
		if (erd == null) {
			throw new InvalidRestParam();
		}
		List<String> warnings = new ArrayList<>();
		result.setWarnings(warnings);

		UserSystem system = new UserSystem();
		userSystemRepository.save(system);
		String name = erd.getName();
		if (!StringUtils.hasLength(name)) {
			name = "imported " + new Date().toString();
		}
		system.setName(name);

		List<TemporaryNanoentity> nanoentities = erd.getEntities().stream().flatMap(e -> e.getNanoentities().stream().map(n -> new TemporaryNanoentity(e.getName(), n))).collect(toList());

		// entities
		CouplingCriterion criterion = couplingCriterionRepository.readByName(CouplingCriterion.IDENTITY_LIFECYCLE);
		Map<String, List<TemporaryNanoentity>> nanoentitiesByEntity = expandEntitiesByCompositionAndInheritance(erd, nanoentities).stream()
				.collect(Collectors.groupingBy(TemporaryNanoentity::getNewEntity));
		for (Entry<String, List<TemporaryNanoentity>> entityAndNanoentities : nanoentitiesByEntity.entrySet()) {
			CouplingInstance entityCoupling = new CouplingInstance(criterion, InstanceType.SAME_ENTITY);
			system.addCouplingInstance(entityCoupling);
			couplingInstanceRepository.save(entityCoupling);
			entityCoupling.setName(entityAndNanoentities.getKey());
			entityCoupling.setSystem(system);
			log.info("Store entity {} with attributes {}", entityAndNanoentities.getKey(), entityAndNanoentities.getValue());
			for (TemporaryNanoentity newNanoentity : entityAndNanoentities.getValue()) {
				entityCoupling.addNanoentity(createNanoentity(system, newNanoentity.getOriginalEntity(), newNanoentity.getOriginalName()));
			}
		}

		// Aggregations
		CouplingCriterion semanticProximity = couplingCriterionRepository.readByName(CouplingCriterion.SEMANTIC_PROXIMITY);
		for (EntityRelation relation : erd.getRelations()) {
			if (RelationType.AGGREGATION.equals(relation.getType())) {
				CouplingInstance instance = new CouplingInstance(semanticProximity, InstanceType.AGGREGATION);
				couplingInstanceRepository.save(instance);
				List<Nanoentity> originNanoentities = relation.getOrigin().getNanoentities().stream()
						.map(attr -> nanoentityRepository.findByContextAndNameAndUserSystem(relation.getOrigin().getName(), attr, system)).collect(Collectors.toList());
				List<Nanoentity> destinationNanoentities = relation.getDestination().getNanoentities().stream()
						.map(attr -> nanoentityRepository.findByContextAndNameAndUserSystem(relation.getDestination().getName(), attr, system)).collect(Collectors.toList());
				instance.setNanoentities(originNanoentities);
				instance.setSecondNanoentities(destinationNanoentities);
				instance.setSystem(system);
				instance.setName(relation.getOrigin().getName() + "." + relation.getDestination().getName());

				log.info("Import aggregation on {} and {}", instance.getNanoentities(), instance.getSecondNanoentities());
			}
		}
		result.setMessage("userSystem " + system.getId() + " has been created");
		result.setId(system.getId());
		return result;
	}

	@Autowired public  ImportEndpoint(final UserSystemRepository userSystemRepository, final NanoentityRepository nanoentityRepository, final CouplingInstanceRepository couplingInstanceRepository,
			final UserSystemCompleter systemCompleter, final CouplingCriterionRepository couplingCriterionRepository,
			final CouplingCriterionCharacteristicRepository couplingCriteriaCharacteristicRepository);

}