diff --git a/README.md b/README.md
index 55a4b69..e648bbb 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,157 @@
-Example Script Plugin for Fess [](https://travis-ci.org/codelibs/fess-script-example)
-==========================
+# Fess Script Example Plugin
+
+[](https://maven-badges.herokuapp.com/maven-central/org.codelibs.fess/fess-script-example)
+[](https://opensource.org/licenses/Apache-2.0)
+
+A simple example plugin demonstrating how to create custom script engines for [Fess](https://fess.codelibs.org/), the open-source enterprise search server.
## Overview
-This is a example plugin for Fess Script.
+This plugin provides a minimal implementation of a custom script engine for Fess. The `ExampleEngine` serves as a template and starting point for developers who want to create their own script engines with custom template processing logic.
+
+### Key Features
-## Download
+- **Simple Implementation**: Demonstrates the basic structure of a Fess script engine
+- **Template Pass-through**: Returns template strings unchanged (useful for testing and learning)
+- **Full Integration**: Properly integrated with Fess's dependency injection container
+- **Comprehensive Tests**: Includes extensive test cases covering edge cases and various scenarios
-See [Maven Repository](https://repo1.maven.org/maven2/org/codelibs/fess/fess-script-example/).
+## Architecture
+
+The plugin extends Fess's `AbstractScriptEngine` class and implements:
+
+- **Template Evaluation**: Process template strings with parameter maps
+- **Engine Identification**: Provides a unique name ("example") for the script engine
+- **DI Integration**: Configured via LastaDi container for seamless Fess integration
## Installation
-See [Plugin](https://fess.codelibs.org/13.12/admin/plugin-guide.html) of Administration guide.
+### Prerequisites
+
+- Fess 15.0.0 or later
+- Java 21 or later
+
+### Download
+
+You can download the plugin JAR from [Maven Central](https://repo1.maven.org/maven2/org/codelibs/fess/fess-script-example/).
+
+### Plugin Installation
+
+1. Download the latest `fess-script-example-{version}.jar` from the releases
+2. Copy the JAR file to your Fess plugin directory (`$FESS_HOME/app/WEB-INF/plugin/`)
+3. Restart Fess server
+4. The "example" script engine will be available for use
+
+For detailed installation instructions, see the [Fess Plugin Guide](https://fess.codelibs.org/15.0/admin/plugin-guide.html).
+
+## Usage
+
+Once installed, you can use the "example" script engine in your Fess configuration:
+
+```xml
+
+```
+
+The engine will process templates by returning them unchanged, making it useful for:
+- Testing script engine integration
+- Learning how to implement custom script engines
+- As a starting point for more complex implementations
+
+## Development
+
+### Building from Source
+
+```bash
+git clone https://github.com/codelibs/fess-script-example.git
+cd fess-script-example
+mvn clean package
+```
+
+### Running Tests
+
+```bash
+mvn test
+```
+
+The test suite includes 19 comprehensive test cases covering:
+- Basic functionality
+- Edge cases (null/empty inputs)
+- Various data types and special characters
+- Multi-line templates and large content
+- Instance independence and data integrity
+
+### Code Quality
+
+```bash
+# Format code
+mvn formatter:format
+
+# Check license headers
+mvn license:check
+
+# Generate Javadoc
+mvn javadoc:javadoc
+```
+
+## Project Structure
+
+```
+src/
+├── main/java/
+│ └── org/codelibs/fess/script/example/
+│ └── ExampleEngine.java # Main script engine implementation
+├── main/resources/
+│ └── fess_se++.xml # DI container configuration
+└── test/java/
+ └── org/codelibs/fess/script/example/
+ └── ExampleEngineTest.java # Comprehensive test suite
+```
+
+## Creating Your Own Script Engine
+
+This project serves as a template for creating custom script engines. To create your own:
+
+1. Fork this repository
+2. Rename the `ExampleEngine` class
+3. Implement your custom template processing logic in the `evaluate` method
+4. Update the `getName` method to return your engine's unique identifier
+5. Update the DI configuration in `fess_se++.xml`
+6. Add appropriate tests
+
+## Dependencies
+
+- **Fess Framework**: Core search server functionality (provided scope)
+- **LastaFlute**: Web application framework with DI container
+- **DBFlute**: Database access framework
+- **OpenSearch**: Search engine integration (provided scope)
+- **UTFlute**: Testing framework for LastaFlute applications
+
+## Contributing
+
+We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.
+
+### Development Guidelines
+
+- Follow the existing code style and formatting
+- Add comprehensive tests for new functionality
+- Update documentation as needed
+- Ensure all tests pass before submitting PRs
+
+## License
+
+This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
+
+## Support
+
+- **Documentation**: [Fess Official Documentation](https://fess.codelibs.org/)
+- **Issues**: [GitHub Issues](https://github.com/codelibs/fess-script-example/issues)
+- **Community**: [Fess Community Forum](https://discuss.codelibs.org/)
+
+## Related Projects
+
+- [Fess](https://github.com/codelibs/fess) - The main Fess search server
+- [Fess Plugins](https://github.com/codelibs?q=fess-) - Other Fess plugins
+
+---
+Developed by [CodeLibs Project](https://github.com/codelibs)
diff --git a/src/main/java/org/codelibs/fess/script/example/ExampleEngine.java b/src/main/java/org/codelibs/fess/script/example/ExampleEngine.java
index b5e7652..0efa39e 100644
--- a/src/main/java/org/codelibs/fess/script/example/ExampleEngine.java
+++ b/src/main/java/org/codelibs/fess/script/example/ExampleEngine.java
@@ -19,13 +19,37 @@
import org.codelibs.fess.script.AbstractScriptEngine;
+/**
+ * Example script engine implementation that demonstrates how to create custom script engines for Fess.
+ * This implementation simply returns the template string unchanged without any processing.
+ */
public class ExampleEngine extends AbstractScriptEngine {
+ /**
+ * Creates a new instance of ExampleEngine.
+ */
+ public ExampleEngine() {
+ super();
+ }
+
+ /**
+ * Evaluates the given template with the provided parameter map.
+ * In this example implementation, the template is returned unchanged without any processing.
+ *
+ * @param template the template string to evaluate
+ * @param paramMap the parameter map containing variables for template evaluation
+ * @return the template string unchanged
+ */
@Override
public Object evaluate(final String template, final Map paramMap) {
return template;
}
+ /**
+ * Returns the name of this script engine.
+ *
+ * @return the name "example" that identifies this script engine
+ */
@Override
protected String getName() {
return "example";
diff --git a/src/test/java/org/codelibs/fess/script/example/ExampleEngineTest.java b/src/test/java/org/codelibs/fess/script/example/ExampleEngineTest.java
index b0c90bb..a68801c 100644
--- a/src/test/java/org/codelibs/fess/script/example/ExampleEngineTest.java
+++ b/src/test/java/org/codelibs/fess/script/example/ExampleEngineTest.java
@@ -54,4 +54,128 @@ public void test_evaluate() {
public void test_getName() {
assertEquals("example", exampleEngine.getName());
}
+
+ // Comprehensive test cases for evaluating various input scenarios
+
+ public void test_evaluate_withNullTemplate() {
+ final Map params = new HashMap<>();
+ assertNull(exampleEngine.evaluate(null, params));
+ }
+
+ public void test_evaluate_withEmptyTemplate() {
+ final Map params = new HashMap<>();
+ assertEquals("", exampleEngine.evaluate("", params));
+ }
+
+ public void test_evaluate_withNullParameterMap() {
+ assertEquals("test", exampleEngine.evaluate("test", null));
+ }
+
+ public void test_evaluate_withEmptyParameterMap() {
+ final Map params = new HashMap<>();
+ assertEquals("test", exampleEngine.evaluate("test", params));
+ }
+
+ public void test_evaluate_withPopulatedParameterMap() {
+ final Map params = new HashMap<>();
+ params.put("key1", "value1");
+ params.put("key2", 123);
+ params.put("key3", true);
+ assertEquals("template content", exampleEngine.evaluate("template content", params));
+ }
+
+ public void test_evaluate_withSpecialCharacters() {
+ final Map params = new HashMap<>();
+ final String template = "Special chars: !@#$%^&*(){}[]|\\:;\"'<>,.?/~`";
+ assertEquals(template, exampleEngine.evaluate(template, params));
+ }
+
+ public void test_evaluate_withMultilineTemplate() {
+ final Map params = new HashMap<>();
+ final String template = "Line 1\nLine 2\nLine 3";
+ assertEquals(template, exampleEngine.evaluate(template, params));
+ }
+
+ public void test_evaluate_withJapaneseCharacters() {
+ final Map params = new HashMap<>();
+ final String template = "こんにちは世界";
+ assertEquals(template, exampleEngine.evaluate(template, params));
+ }
+
+ public void test_evaluate_withLongTemplate() {
+ final Map params = new HashMap<>();
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 1000; i++) {
+ sb.append("This is a long template content. ");
+ }
+ final String template = sb.toString();
+ assertEquals(template, exampleEngine.evaluate(template, params));
+ }
+
+ public void test_evaluate_withComplexParameterMap() {
+ final Map params = new HashMap<>();
+ params.put("string", "value");
+ params.put("number", 42);
+ params.put("boolean", true);
+ params.put("null", null);
+ params.put("map", new HashMap());
+ assertEquals("complex template", exampleEngine.evaluate("complex template", params));
+ }
+
+ public void test_getName_consistency() {
+ assertEquals("example", exampleEngine.getName());
+ assertEquals("example", exampleEngine.getName());
+ assertEquals("example", exampleEngine.getName());
+ }
+
+ public void test_getName_returnsConstant() {
+ final String name1 = exampleEngine.getName();
+ final String name2 = exampleEngine.getName();
+ assertSame(name1, name2);
+ }
+
+ public void test_constructor_initialization() {
+ final ExampleEngine engine = new ExampleEngine();
+ assertNotNull(engine);
+ assertEquals("example", engine.getName());
+ }
+
+ public void test_multipleInstances_independence() {
+ final ExampleEngine engine1 = new ExampleEngine();
+ final ExampleEngine engine2 = new ExampleEngine();
+
+ assertNotSame(engine1, engine2);
+ assertEquals(engine1.getName(), engine2.getName());
+
+ final Map params = new HashMap<>();
+ assertEquals("test", engine1.evaluate("test", params));
+ assertEquals("test", engine2.evaluate("test", params));
+ }
+
+ public void test_evaluate_preservesTemplateIntegrity() {
+ final Map params = new HashMap<>();
+ params.put("modify", "attempt");
+
+ final String originalTemplate = "original template";
+ final Object result = exampleEngine.evaluate(originalTemplate, params);
+
+ assertEquals(originalTemplate, result);
+ assertTrue(result instanceof String);
+ assertEquals(String.class, result.getClass());
+ }
+
+ public void test_evaluate_withWhitespaceOnly() {
+ final Map params = new HashMap<>();
+ assertEquals(" ", exampleEngine.evaluate(" ", params));
+ assertEquals(" ", exampleEngine.evaluate(" ", params));
+ assertEquals("\t", exampleEngine.evaluate("\t", params));
+ assertEquals("\n", exampleEngine.evaluate("\n", params));
+ }
+
+ public void test_evaluate_returnTypeConsistency() {
+ final Map params = new HashMap<>();
+ final Object result = exampleEngine.evaluate("test", params);
+ assertTrue(result instanceof String);
+ assertEquals("test", result);
+ }
}