**برای این سوال، نسخهی جاوای شما باید ۱۷ باشد.**
----------
![اندیس](https://quera.org/qbox/view/7PlWCxxoTi/D.png)
شما به قبل سال `2000` برگشتهاید، زمانی که فناوری دیتابیسها به تازگی در حال ظهور است و مهندسان در تلاشند تا راهحلهای نوآورانهای برای جستجوی اطلاعات پیدا کنند. بسیاری از آنها از ایدههای جدید شگفتزده شده و دنیای فناوری اطلاعات در آستانهی تغییرات شگرفی است.
شما که از آینده خبر دارید، تصمیم گرفتهاید سیستم ابتدایی `Full-Text Search` را پیادهسازی کنید. با این اختراع، شما نه تنها دنیای جستجو را متحول میکنید بلکه تاریخ را نیز تحت تأثیر قرار خواهید داد و این اختراع را به نام خود ثبت خواهید کرد.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/253389/) دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
```java
index
├── Document.java
├── Index.java
└── Query.java
```
شما باید سه کلاس `Document`، `Index` و `Query` را مطابق با مواردی که در ادامه مطرح میشود، کامل کنید.
## کلاس `Document`
اولین کلاسی که باید تکمیل کنید کلاس `Document` است. این کلاس بدنه اصلی داکیومنتهای شما را برای اندیس مشخص میکند و باید شامل ویژگیهای(property) زیر باشد:
| نام | نوع |
|:----------:|:------------------:|
| id | `long` |
| text | `String` |
| date | `LocalDate` |
## کلاس `Query`
این کلاس شامل ویژگیهای کوئری است که قصد دارید طبق این ویژگیها داکیومنتهایی را از درون اندیس بازیابی کنید. این کلاس شامل ویژگیهای زیر میشود:
| نام | نوع |
|:----------:|:------------------:|
| text | `String` |
| date | `LocalDate` |
| endDate | `LocalDate` |
## کلاس `Index`
این کلاس اصلیترین کلاسی است که باید پیادهسازی کنید. این کلاس شامل داکیومنتها و اندیسها(Index) میشود. اندیسهای این کلاس در واقع [اندیسهای معکوس](https://en.wikipedia.org/wiki/Inverted_index) (Inverted index) به هر داکیومنت هستند.
```java Index.java java
public class Index {
private List<Document> documents = new ArrayList<>();
private Map<String, Set<Long>> textIndex = new HashMap<>();
private Map<LocalDate, Set<Long>> dateIndex = new TreeMap<>();
public Index(String filePath) throws Exception {
}
public void indexDocument(Document document) {
}
public void saveIndexToFile(String filePath) throws IOException {
}
public List<Document> search(Query query) {
}
}
```
همانطور که میبینید، دو اندیس `textIndex` و `dateIndex` وجود دارند که نحوه ساخت این اندیسها در ادامه آورده شده است. مطابق این فایل، شما در این کلاس باید یک کانستراکتور و سه متد که در ادامه جزئیات آنها ذکر میشود را پیادهسازی نمایید:
کانستراکتور `Index`: این کانستراکتور فایلی که در مسیر ورودی دریافت کرده را به صورت `ObjectInputStream` خوانده و اندیسهای گفته شده را باید به درستی مقداردهی کند.
متد `saveIndexToFile`: این متد یه مسیر را دریافت و کل کلاس `Index` را با تمام مقادیرش به صورت `ObjectOutputStream` در این مسیر قرار میدهد.
متد `indexDocument`: این متد یک داکیومنت را دریافت میکند و اندیسهای گفته شده را به صورت زیر ایجاد میکند:
+ برای ساخت `textIndex` باید ویژگی `text` هر داکیومنت براساس کاراکترهای غیر کلمهای (حرف، رقم یا `_`) شکسته شود و داکیومنتها اندیس شوند.
+ برای ساخت `dateIndex` هر داکیومنت براساس ویژگی `date` خودش اندیس میشود.
متد `search`: این متد وظیفه دارد تا داکیومنتهایی را براساس کوئری ورودی برگرداند. هر کدام از ویژگیهای کلاس `Query` میتواند نال باشند ولی در صورتی که هر کدام از مقادیر نال نبود باید داکیومنتهایی براساس اولویت زیر برگردانده شوند:
1. متن
2. بازه زمانی (این به این معنی است که اگر در کوئری بازه زمانی وارد شده بود، این بازه اولویت بیشتری دارد)
3. زمان دقیق
# مثال
مثالهایی به صورت تست نمونه در اختیار شما قرار داده شده است که میتوانید از آنها کمک بگیرید. به عنوان مثال به مورد زیر دقت کنید:
```java
Index index = new Index();
index.indexDocument(new Document(1, "Quera online coding contests", LocalDate.now()));
index.indexDocument(new Document(2, "Quera for programmers", LocalDate.now().minusDays(4)));
index.indexDocument(new Document(3, "Practice coding skills", LocalDate.now().minusMonths(11)));
Query query = new Query("Quera", null, null);
List<Document> result = index.search(query);
```
خروجی مثال بالا باید داکیومنتها با آیدی `1`و `2` را برگرداند.
# نکات
+ دو کلاس `Document` و `Query` باید شامل کانستراکتوری با همه ویژگیها باشند.
+ همه ویژگیهای دو کلاس `Document` و `Query` باید دارای `getter` متد با نام پیشفرض در جاوا باشند.
+ **تضمین میشود** داکیومنت با آیدی تکراری وارد نخواهد شد.
+ **دقت کنید** که ساختار ابتدایی کلاسها را تغییر ندهید.
+ **دقت کنید** که کلاسهای شما در صورت لزوم باید قابلیت سریالایز و دسریالایز شدن داشته باشند.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، فقط این سه کلاس را زیپ کرده و آپلود کنید.
```java
[your-solution-file].zip
├── Document.java
├── Index.java
└── Query.java
```