4 changed files with 159 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,63 @@ |
|||
package com.crawler; |
|||
|
|||
import com.crawler.command.*; |
|||
import com.crawler.controller.CrawlerController; |
|||
import com.crawler.repository.ArticleRepository; |
|||
import com.crawler.repository.InMemoryArticleRepository; |
|||
import com.crawler.view.ConsoleView; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class App { |
|||
private final Map<String, Command> commands = new HashMap<>(); |
|||
private final ConsoleView view; |
|||
private final AtomicBoolean running = new AtomicBoolean(true); |
|||
|
|||
public App() { |
|||
view = new ConsoleView(); |
|||
ArticleRepository repository = new InMemoryArticleRepository(); |
|||
CrawlerController controller = new CrawlerController(repository, view); |
|||
|
|||
commands.put("crawl", new CrawlCommand(controller, view)); |
|||
commands.put("list", new ListCommand(controller)); |
|||
commands.put("save", new SaveCommand(controller)); |
|||
commands.put("load", new LoadCommand(controller)); |
|||
commands.put("help", new HelpCommand(view)); |
|||
commands.put("exit", new ExitCommand(view, () -> running.set(false))); |
|||
} |
|||
|
|||
public void run() { |
|||
view.displayWelcome(); |
|||
view.displayHelp(); |
|||
|
|||
while (running.get()) { |
|||
try { |
|||
String input = view.readInput(); |
|||
if (input.isEmpty()) { |
|||
continue; |
|||
} |
|||
|
|||
String[] parts = input.split("\\s+", 3); |
|||
String commandName = parts[0].toLowerCase(); |
|||
String[] args = parts.length > 1 ? java.util.Arrays.copyOfRange(parts, 1, parts.length) : new String[0]; |
|||
|
|||
Command command = commands.get(commandName); |
|||
if (command != null) { |
|||
command.execute(args); |
|||
} else { |
|||
view.displayError("Unknown command: " + commandName); |
|||
view.displayInfo("Type 'help' for available commands"); |
|||
} |
|||
} catch (Exception e) { |
|||
view.displayError("Error: " + e.getMessage()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
App app = new App(); |
|||
app.run(); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.crawler.repository; |
|||
|
|||
import com.crawler.model.Article; |
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
|
|||
public interface ArticleRepository { |
|||
void save(Article article); |
|||
void saveAll(List<Article> articles); |
|||
Optional<Article> findById(String id); |
|||
Optional<Article> findByUrl(String url); |
|||
List<Article> findAll(); |
|||
List<Article> findBySource(String source); |
|||
void deleteById(String id); |
|||
void deleteAll(); |
|||
int count(); |
|||
boolean existsByUrl(String url); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
package com.crawler.repository; |
|||
|
|||
import com.crawler.model.Article; |
|||
import java.util.*; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class InMemoryArticleRepository implements ArticleRepository { |
|||
private final Map<String, Article> articles = new ConcurrentHashMap<>(); |
|||
private final Map<String, String> urlToIdMap = new ConcurrentHashMap<>(); |
|||
private final AtomicInteger idGenerator = new AtomicInteger(1); |
|||
|
|||
@Override |
|||
public void save(Article article) { |
|||
if (article.getId() == null) { |
|||
article.setId(String.valueOf(idGenerator.getAndIncrement())); |
|||
} |
|||
articles.put(article.getId(), article); |
|||
if (article.getUrl() != null) { |
|||
urlToIdMap.put(article.getUrl(), article.getId()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void saveAll(List<Article> articleList) { |
|||
for (Article article : articleList) { |
|||
save(article); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Optional<Article> findById(String id) { |
|||
return Optional.ofNullable(articles.get(id)); |
|||
} |
|||
|
|||
@Override |
|||
public Optional<Article> findByUrl(String url) { |
|||
String id = urlToIdMap.get(url); |
|||
return id != null ? Optional.ofNullable(articles.get(id)) : Optional.empty(); |
|||
} |
|||
|
|||
@Override |
|||
public List<Article> findAll() { |
|||
return new ArrayList<>(articles.values()); |
|||
} |
|||
|
|||
@Override |
|||
public List<Article> findBySource(String source) { |
|||
return articles.values().stream() |
|||
.filter(a -> source.equals(a.getSource())) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
@Override |
|||
public void deleteById(String id) { |
|||
Article article = articles.remove(id); |
|||
if (article != null && article.getUrl() != null) { |
|||
urlToIdMap.remove(article.getUrl()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteAll() { |
|||
articles.clear(); |
|||
urlToIdMap.clear(); |
|||
} |
|||
|
|||
@Override |
|||
public int count() { |
|||
return articles.size(); |
|||
} |
|||
|
|||
@Override |
|||
public boolean existsByUrl(String url) { |
|||
return urlToIdMap.containsKey(url); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue