package eu.kielczewski.akanke.common.service.document; import com.google.common.io.Files; import eu.kielczewski.akanke.common.dao.file.FileDao; import eu.kielczewski.akanke.common.domain.Document; import eu.kielczewski.akanke.common.service.facebook.FacebookStatsService; import org.pegdown.PegDownProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.inject.Inject; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; @Component class DocumentCreator { private static final Logger LOGGER = LoggerFactory.getLogger(DocumentCreator.class); private final FileDao fileDao; private final DocumentPropertyExtractor propertyExtractor; private final FacebookStatsService facebookStatsService; private final ObjectFactory<PegDownProcessor> pegDownProcessor; @Autowired public DocumentCreator(FileDao fileDao, DocumentPropertyExtractor propertyExtractor, FacebookStatsService facebookStatsService, ObjectFactory<PegDownProcessor> pegDownProcessor) { this.fileDao = fileDao; this.propertyExtractor = propertyExtractor; this.facebookStatsService = facebookStatsService; this.pegDownProcessor = pegDownProcessor; } public Document createDocument(String file) { LOGGER.debug("Creating document from file={}", file); checkArgument(file != null, "File cannot be null"); try { //noinspection ConstantConditions String contents = fileDao.getContents(file); Map<String, String> properties = propertyExtractor.fromContents(contents); Date datePublished = chooseDatePublished(properties.get("date"), file); String id = generateId(file, datePublished); Document document = new Document( id, file, properties.getOrDefault("title", generateTitle(id)), properties.getOrDefault("description", ""), pegDownProcessor.getObject().markdownToHtml(contents), generateTags(properties.get("tags")), datePublished, facebookStatsService.get(id)); LOGGER.trace("Returning {}", document); return document; } catch (Exception e) { throw new RuntimeException("Cannot create document from file=" + file, e); } } private String generateId(String file, Date datePublished) { Calendar cal = Calendar.getInstance(); cal.setTime(datePublished); return "/" + cal.get(Calendar.YEAR) + "/" + String.format("%02d", cal.get(Calendar.MONTH) + 1) + "/" + Files.getNameWithoutExtension(file) + "/"; } private String generateTitle(String id) { return StringUtils.capitalize(id .replaceFirst("/[0-9]+/[0-9]+/", "") .replace("-", " ") .replaceFirst("/$", "")); } private Collection<String> generateTags(String tagsString) { if (tagsString != null) { return Arrays.asList(tagsString.split(",")).stream() .map(String::trim) .collect(Collectors.toList()); } else { return Collections.emptyList(); } } private Date chooseDatePublished(String dateString, String file) throws IOException { Date fromFile = new Date(fileDao.getCreationTime(file)); if (dateString != null) { try { Calendar fromProperty = Calendar.getInstance(); fromProperty.setTime(new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH).parse(dateString)); Calendar date = Calendar.getInstance(); date.setTime(fromFile); date.set(Calendar.DAY_OF_MONTH, fromProperty.get(Calendar.DAY_OF_MONTH)); date.set(Calendar.MONTH, fromProperty.get(Calendar.MONTH)); date.set(Calendar.YEAR, fromProperty.get(Calendar.YEAR)); return date.getTime(); } catch (ParseException e) { LOGGER.warn("Date string={} is invalid", dateString, e); } } return fromFile; } }