add new site for documentation

pull/3/head
Mahmoud Ben Hassine 11 years ago
parent 9fa82c6ea2
commit 5cb26cb163

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Diagram>
<ID>JAVA</ID>
<OriginalElement>net.benas.easyrules.core.BasicRule</OriginalElement>
<nodes>
<node x="655.0" y="279.0">net.benas.easyrules.core.CompositeRule</node>
<node x="347.5" y="463.0">java.lang.Comparable</node>
<node x="249.0" y="238.5">net.benas.easyrules.core.BasicRule</node>
<node x="26.5" y="126.0">net.benas.easyrules.api.JmxManagedRule</node>
<node x="277.0" y="74.5">net.benas.easyrules.api.Rule</node>
<node x="13.0" y="320.0">net.benas.easyrules.core.BasicJmxManagedRule</node>
</nodes>
<notes />
<edges>
<edge source="net.benas.easyrules.core.BasicRule" target="java.lang.Comparable">
<point x="0.0" y="-94.5" />
<point x="0.0" y="24.0" />
</edge>
<edge source="net.benas.easyrules.core.BasicJmxManagedRule" target="net.benas.easyrules.core.BasicRule">
<point x="82.0" y="-0.0" />
<point x="-168.0" y="-0.0" />
</edge>
<edge source="net.benas.easyrules.core.BasicJmxManagedRule" target="net.benas.easyrules.api.JmxManagedRule">
<point x="0.0" y="14.0" />
<point x="0.0" y="-14.0" />
</edge>
<edge source="net.benas.easyrules.core.CompositeRule" target="net.benas.easyrules.api.Rule">
<point x="0.0" y="0.0" />
<point x="0.0" y="0.0" />
</edge>
<edge source="net.benas.easyrules.api.JmxManagedRule" target="net.benas.easyrules.api.Rule">
<point x="67.5" y="-0.0" />
<point x="-138.0" y="-0.0" />
</edge>
<edge source="net.benas.easyrules.core.BasicRule" target="net.benas.easyrules.api.Rule">
<point x="0.0" y="94.5" />
<point x="0.0" y="-64.5" />
</edge>
<edge source="net.benas.easyrules.core.CompositeRule" target="net.benas.easyrules.core.BasicRule">
<point x="-128.0" y="-0.0" />
<point x="168.0" y="-0.0" />
</edge>
</edges>
<settings layout="Hierarchic Group" zoom="1.0" x="474.0" y="293.0" />
<SelectedNodes />
<Categories>
<Category>Methods</Category>
<Category>Inner Classes</Category>
<Category>Properties</Category>
</Categories>
<SCOPE>All</SCOPE>
<VISIBILITY>private</VISIBILITY>
</Diagram>

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Diagram>
<ID>JAVA</ID>
<OriginalElement>net.benas.easyrules.core.DefaultRulesEngine</OriginalElement>
<nodes>
<node x="0.0" y="0.0">net.benas.easyrules.api.RulesEngine</node>
<node x="145.25" y="239.0">net.benas.easyrules.core.DefaultRulesEngine</node>
<node x="325.0" y="30.0">net.benas.easyrules.api.Rule</node>
</nodes>
<notes />
<edges>
<edge source="net.benas.easyrules.core.DefaultRulesEngine" target="net.benas.easyrules.api.Rule">
<point x="0.0" y="0.0" />
<point x="0.0" y="0.0" />
</edge>
<edge source="net.benas.easyrules.core.DefaultRulesEngine" target="net.benas.easyrules.api.RulesEngine">
<point x="-81.25" y="-104.5" />
<point x="226.5" y="214.0" />
<point x="152.5" y="214.0" />
<point x="0.0" y="94.5" />
</edge>
</edges>
<settings layout="Hierarchic Group" zoom="1.0" x="301.0" y="224.0" />
<SelectedNodes>
<node>net.benas.easyrules.core.DefaultRulesEngine</node>
</SelectedNodes>
<Categories>
<Category>Methods</Category>
<Category>Properties</Category>
</Categories>
<SCOPE>All</SCOPE>
<VISIBILITY>private</VISIBILITY>
</Diagram>

@ -0,0 +1 @@
www.easyrules.org

@ -0,0 +1 @@
Easy Rules website.

@ -0,0 +1,20 @@
version: 1.1.0
highlighter: pygments
url: http://www.easyrules.org
google_analytics_id: UA-46301888-1
exclude: ["CNAME", "README"]
author :
name : Mahmoud Ben Hassine
email : md.benhassine@gmail.com
github : benas
twitter : md_benhassine
web : http://www.mahmoudbenhassine.com
project:
name: Easy Rules
github: easy-rules
markdown: redcarpet
redcarpet:
extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "strikethrough", "superscript", "with_toc_data"]

@ -0,0 +1,10 @@
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{{ site.google_analytics_id }}']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

@ -0,0 +1,53 @@
<div class="unit one-fifth">
<aside>
<h4>About Easy Rules</h4>
<ul>
<li class="{% if page.title == "Overview" %}current{% endif %}">
<a href="{{ site.url }}/about/overview.html">Overview</a>
</li>
<li class="{% if page.title == "Getting started" %}current{% endif %}">
<a href="{{ site.url }}/about/getting-started.html">Getting started</a>
</li>
</ul>
<h4>User guide</h4>
<ul>
<li class="{% if page.title == "Introduction" %}current{% endif %}">
<a href="{{ site.url }}/user-guide/introduction.html">Introduction</a>
</li>
<li class="{% if page.title == "Defining rules" %}current{% endif %}">
<a href="{{ site.url }}/user-guide/defining-rules.html">Defining rules</a>
</li>
<li class="{% if page.title == "Rules engine" %}current{% endif %}">
<a href="{{ site.url }}/user-guide/rules-engine.html">Rules engine</a>
</li>
<li class="{% if page.title == "Managing rules" %}current{% endif %}">
<a href="{{ site.url }}/user-guide/managing-rules.html">Managing rules</a>
</li>
</ul>
<h4>Tutorials</h4>
<ul>
<li class="{% if page.title == "Hello World" %}current{% endif %}">
<a href="{{ site.url }}/tutorials/hello-world.html">Hello World</a>
</li>
<li class="{% if page.title == "Dynamic configuration" %}current{% endif %}">
<a href="{{ site.url }}/tutorials/dynamic-configuration.html">Dynamic configuration</a>
</li>
</ul>
<h4>Get involved</h4>
<ul>
<li>
<a target="_blank" href="https://github.com/benas/easy-rules">Source repository</a>
</li>
<li>
<a target="_blank" href="https://github.com/benas/easy-rules/issues">Issue tracker</a>
</li>
</ul>
</aside>
</div>

@ -0,0 +1,13 @@
<footer>
<div class="grid">
<div class="unit one-third center-on-mobiles">
<p>Project created and maintained by <a target="_blank" href="{{ site.author.web }}">{{ site.author.name}}</a>.</p>
</div>
<div class="unit two-thirds align-right center-on-mobiles">
<p>
Inspired by and built with <a target="_blank" href="http://jekyllrb.com">Jekyll</a>. Hosted on <a target="_blank" href="https://github.com">Github</a>.
</p>
</div>
</div>
</footer>

@ -0,0 +1,14 @@
<header>
<div class="grid">
<div class="unit one-third">
<a href="{{ site.url }}/index.html">
<h1>
<span class="shadow">{{ site.project.name }}</span>
</h1>
</a>
</div>
<nav class="main-nav unit two-thirds">
{% include primary-nav-items.html %}
</nav>
</div>
</header>

@ -0,0 +1,12 @@
<ul>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li class="{% if page.overview %}current{% endif %}">
<a href="{{ site.url }}/index.html">Home</a>
</li>
<li class="{% if page.doc %}current{% endif %}">
<a href="{{ site.url }}/about/overview.html">Documentation</a>
</li>
<li>
<a target="_blank" href="https://github.com/{{ site.author.github }}/{{ site.project.github }}">View on GitHub</a>
</li>
</ul>

@ -0,0 +1,22 @@
<div class="section-nav">
<div class="left align-right">
{% if page.prev_section != null %}
<a href="{{ site.url }}/{{ page.prev_section }}.html" class="prev">
Back
</a>
{% else %}
<span class="prev disabled">Back</span>
{% endif %}
</div>
<div class="right align-left">
{% if page.next_section != null %}
<a href="{{ site.url }}/{{ page.next_section }}.html" class="next">
Next
</a>
{% else %}
<span class="next disabled">Next</span>
{% endif %}
</div>
<div class="clear"></div>
</div>

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>{{ page.title }}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Arizonia' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="{{ site.url }}/css/normalize.css" />
<link rel="stylesheet" href="{{ site.url }}/css/gridism.css" />
<link rel="stylesheet" href="{{ site.url }}/css/style.css" />
<link rel="stylesheet" href="{{ site.url }}/css/pygments.css" />
<link rel="icon" type="image/x-icon" href="{{ site.url }}/favicon.ico" />
<script src="{{ site.url }}/js/modernizr-2.5.3.min.js"></script>
</head>

@ -0,0 +1,16 @@
{% include top.html %}
<body class="wrap">
{% include header.html %}
{{ content }}
{% include footer.html %}
{% include analytics.html %}
</body>
{% include bottom.html %}

@ -0,0 +1,21 @@
---
layout: default
---
<section class="docs">
<div class="grid">
<div class="unit four-fifths">
<article>
<h1>{{ page.header }}</h1>
{{ content }}
{% include section_nav.html %}
</article>
</div>
{% include docs_contents.html %}
<div class="clear"></div>
</div>
</section>

@ -0,0 +1,41 @@
---
layout: docs
title: Getting started
header: Getting started
prev_section: about/overview
next_section: user-guide/introduction
doc: true
---
Easy Rules is a Java library. It requires a Java 1.5+ runtime.
## Building form source
To build Easy Rules from sources, you need to have [git](http://www.git-scm.com) and [maven](http://maven.apache.org/) installed and set up.
Please follow these instructions :
{% highlight bash %}
$ git clone https://github.com/benas/easy-rules.git
$ mvn package
{% endhighlight %}
Easy Rules core jar **_easyrules-core-${version}.jar_** will be generated in the target folder.
## Use with maven
Easy Rules is a single jar file with no dependencies. You have to simply add the jar **_easyrules-core-{{site.version}}.jar_** to your application's classpath.
Using maven, you should add the following dependency to your pom.xml :
```xml
<dependencies>
<dependency>
<groupId>org.easyrules</groupId>
<artifactId>easyrules-core</artifactId>
<version>{{site.version}}</version>
</dependency>
</dependencies>
```

@ -0,0 +1,21 @@
---
layout: docs
title: Overview
header: What is Easy rules?
next_section: about/getting-started
doc: true
---
Easy Rules is a simple yet powerful Java rules engine providing the following features:
* Lightweight framework and easy to learn API
* POJO based development
* Useful abstractions to define business rules and apply them easily
* The ability to create composite rules from primitive ones
* Dynamic rule configuration at runtime using JMX
In a very interesting [article](http://martinfowler.com/bliki/RulesEngine.html) about rules engines, [Martin Fowler](http://martinfowler.com/) says the following :
>You can build a simple rules engine yourself. All you need is to create a bunch of objects with conditions and actions, store them in a collection, and run through them to evaluate the conditions and execute the actions.
This is exactly what Easy Rules does, with more features like rule composition and dynamic configuration.

@ -0,0 +1,110 @@
/*
* Gridism
* A simple, responsive, and handy CSS grid by @cobyism
* https://github.com/cobyism/gridism
*/
/* Preserve some sanity */
.grid,
.unit {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* Set up some rules to govern the grid */
.grid {
display: block;
clear: both;
}
.grid .unit {
float: left;
width: 100%;
padding: 10px;
}
/* This ensures the outer gutters are equal to the (doubled) inner gutters. */
.grid .unit:first-child { padding-left: 10px; }
.grid .unit:last-child { padding-right: 10px; }
/* Nested grids already have padding though, so lets nuke it */
.unit .unit:first-child { padding-left: 0; }
.unit .unit:last-child { padding-right: 0; }
.unit .grid:first-child > .unit { padding-top: 0; }
.unit .grid:last-child > .unit { padding-bottom: 0; }
/* Let people nuke the gutters/padding completely in a couple of ways */
.no-gutters .unit,
.unit.no-gutters {
padding: 0 !important;
}
/* Wrapping at a maximum width is optional */
.wrap .grid,
.grid.wrap {
max-width: 978px;
margin: 0 auto;
}
/* Width classes also have shorthand versions numbered as fractions
* For example: for a grid unit 1/3 (one third) of the parent width,
* simply apply class="w-1-3" to the element. */
.grid .whole, .grid .w-1-1 { width: 100%; }
.grid .half, .grid .w-1-2 { width: 50%; }
.grid .one-third, .grid .w-1-3 { width: 33.3332%; }
.grid .two-thirds, .grid .w-2-3 { width: 66.6665%; }
.grid .one-quarter, .grid .w-1-4 { width: 25%; }
.grid .three-quarters, .grid .w-3-4 { width: 75%; }
.grid .one-fifth, .grid .w-1-5 { width: 20%; }
.grid .two-fifths, .grid .w-2-5 { width: 40%; }
.grid .three-fifths, .grid .w-3-5 { width: 60%; }
.grid .four-fifths, .grid .w-4-5 { width: 80%; }
.grid .golden-small, .grid .w-g-s { width: 38.2716%; } /* Golden section: smaller piece */
.grid .golden-large, .grid .w-g-l { width: 61.7283%; } /* Golden section: larger piece */
/* Utility classes */
.align-center { text-align: center; }
.align-left { text-align: left; }
.align-right { text-align: right; }
.pull-left { float: left; }
.pull-right { float: right; }
.show-on-mobiles {
display: none;
}
/* Responsive Stuff */
@media screen and (max-width: 568px) {
/* Stack anything that isnt full-width on smaller screens */
.grid .unit {
width: 100% !important;
padding-left: 20px;
padding-right: 20px;
}
.unit .grid .unit {
padding-left: 0px;
padding-right: 0px;
}
/* Sometimes, you just want to be different on small screens */
.center-on-mobiles {
text-align: center !important;
}
.hide-on-mobiles {
display: none !important;
}
.show-on-mobiles {
display: block !important;
}
a .show-on-mobiles {
display: inline !important;
}
}
/* Expand the wrap a bit further on larger screens */
/*@media screen and (min-width: 1180px) {
.wrap .grid {
max-width: 1180px;
margin: 0 auto;
}
}*/

@ -0,0 +1,504 @@
/*! normalize.css 2012-03-11T12:53 UTC - http://github.com/necolas/normalize.css */
/* =============================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects block display not defined in IE6/7/8/9 & FF3
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects inline-block display not defined in IE6/7/8/9 & FF3
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/*
* Prevents modern browsers from displaying 'audio' without controls
* Remove excess height in iOS5 devices
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
* Known issue: no IE6 support
*/
[hidden] {
display: none;
}
/* =============================================================================
Base
========================================================================== */
/*
* 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
* http://clagnut.com/blog/348/#c790
* 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
* www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/*
* Addresses font-family inconsistency between 'textarea' and other form elements.
*/
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
/*
* Addresses margins handled incorrectly in IE6/7
*/
body {
margin: 0;
}
/* =============================================================================
Links
========================================================================== */
/*
* Addresses outline displayed oddly in Chrome
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers
* people.opera.com/patrickl/experiments/keyboard/test
*/
a:hover,
a:active {
outline: 0;
}
/* =============================================================================
Typography
========================================================================== */
/*
* Addresses font sizes and margins set differently in IE6/7
* Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.75em;
margin: 2.33em 0;
}
/*
* Addresses styling not present in IE7/8/9, S5, Chrome
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to 'bolder' in FF3+, S4/5, Chrome
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/*
* Addresses styling not present in S5, Chrome
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE6/7/8/9
*/
mark {
background: #ff0;
color: #000;
}
/*
* Addresses margins set differently in IE6/7
*/
p,
pre {
margin: 1em 0;
}
/*
* Corrects font family set oddly in IE6, S4/5, Chrome
* en.wikipedia.org/wiki/User:Davidgothberg/Test59
*/
pre,
code,
kbd,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* 1. Addresses CSS quotes not supported in IE6/7
* 2. Addresses quote property not supported in S4
*/
/* 1 */
q {
quotes: none;
}
/* 2 */
q:before,
q:after {
content: '';
content: none;
}
small {
font-size: 75%;
}
/*
* Prevents sub and sup affecting line-height in all browsers
* gist.github.com/413930
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* =============================================================================
Lists
========================================================================== */
/*
* Addresses margins set differently in IE6/7
*/
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
/*
* Addresses paddings set differently in IE6/7
*/
menu,
ol,
ul {
padding: 0 0 0 40px;
}
/*
* Corrects list images handled incorrectly in IE7
*/
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* =============================================================================
Embedded content
========================================================================== */
/*
* 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
* 2. Improves image quality when scaled in IE7
* code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/*
* Corrects overflow displayed oddly in IE9
*/
svg:not(:root) {
overflow: hidden;
}
/* =============================================================================
Figures
========================================================================== */
/*
* Addresses margin not present in IE6/7/8/9, S5, O11
*/
figure {
margin: 0;
}
/* =============================================================================
Forms
========================================================================== */
/*
* Corrects margin displayed oddly in IE6/7
*/
form {
margin: 0;
}
/*
* Define consistent border, margin, and padding
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/*
* 1. Corrects color not being inherited in IE6/7/8/9
* 2. Corrects text not wrapping in FF3
* 3. Corrects alignment displayed oddly in IE6/7
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/*
* 1. Corrects font size not being inherited in all browsers
* 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
* 3. Improves appearance and consistency in all browsers
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/*
* Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
*/
button,
input {
line-height: normal; /* 1 */
}
/*
* 1. Improves usability and consistency of cursor style between image-type 'input' and others
* 2. Corrects inability to style clickable 'input' types in iOS
* 3. Removes inner spacing in IE7 without affecting normal text inputs
* Known issue: inner spacing remains in IE6
*/
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
cursor: pointer; /* 1 */
-webkit-appearance: button; /* 2 */
*overflow: visible; /* 3 */
}
/*
* Re-set default cursor for disabled elements
*/
button[disabled],
input[disabled] {
cursor: default;
}
/*
* 1. Addresses box sizing set to content-box in IE8/9
* 2. Removes excess padding in IE8/9
* 3. Removes excess padding in IE7
Known issue: excess padding remains in IE6
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/*
* 1. Addresses appearance set to searchfield in S5, Chrome
* 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/*
* Removes inner padding and search cancel button in S5, Chrome on OS X
*/
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
}
/*
* Removes inner padding and border in FF3+
* www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/*
* 1. Removes default vertical scrollbar in IE6/7/8/9
* 2. Improves readability and alignment in all browsers
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* =============================================================================
Tables
========================================================================== */
/*
* Remove most spacing between table cells
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

@ -0,0 +1,70 @@
.highlight .hll { background-color: #222222 }
/* .highlight { background: #000000; color: #cccccc } */
.highlight .c { color: #777777; font-style: italic } /* Comment */
.highlight .err { color: #cccccc; border: 1px solid #FF0000 } /* Error */
.highlight .g { color: #cccccc } /* Generic */
.highlight .k { color: #cdcd00 } /* Keyword */
.highlight .l { color: #cccccc } /* Literal */
.highlight .n { color: #cccccc } /* Name */
.highlight .o { color: #3399cc } /* Operator */
.highlight .x { color: #cccccc } /* Other */
.highlight .p { color: #cccccc } /* Punctuation */
.highlight .cm { color: #777777; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #777777; font-style: italic } /* Comment.Preproc */
.highlight .c1 { color: #777777; font-style: italic } /* Comment.Single */
.highlight .cs { color: #cd5c5c; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #cd5c5c } /* Generic.Deleted */
.highlight .ge { color: #cccccc; font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00cd00 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { color: #cccccc; font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #cdcd00 } /* Keyword.Constant */
.highlight .kd { color: #00cd00 } /* Keyword.Declaration */
.highlight .kn { color: #cd00cd } /* Keyword.Namespace */
.highlight .kp { color: #cdcd00 } /* Keyword.Pseudo */
.highlight .kr { color: #cdcd00 } /* Keyword.Reserved */
.highlight .kt { color: #00cd00 } /* Keyword.Type */
.highlight .ld { color: #cccccc } /* Literal.Date */
.highlight .m { color: #cd00cd } /* Literal.Number */
.highlight .s { color: #cd5c5c } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #cd00cd } /* Name.Builtin */
.highlight .nc { color: #00cdcd } /* Name.Class */
.highlight .no { color: #cccccc } /* Name.Constant */
.highlight .nd { color: #cccc00 } /* Name.Decorator */
.highlight .ni { color: #cccccc } /* Name.Entity */
.highlight .ne { color: #666699; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #f0e68c } /* Name.Function */
.highlight .nl { color: #cccccc } /* Name.Label */
.highlight .nn { color: #cccccc } /* Name.Namespace */
.highlight .nx { color: #cccccc } /* Name.Other */
.highlight .py { color: #cccccc } /* Name.Property */
.highlight .nt { color: #00cccc } /* Name.Tag */
.highlight .nv { color: #00cdcd } /* Name.Variable */
.highlight .ow { color: #cdcd00 } /* Operator.Word */
.highlight .w { color: #cccccc } /* Text.Whitespace */
.highlight .mf { color: #cd00cd } /* Literal.Number.Float */
.highlight .mh { color: #cd00cd } /* Literal.Number.Hex */
.highlight .mi { color: #cd00cd } /* Literal.Number.Integer */
.highlight .mo { color: #cd00cd } /* Literal.Number.Oct */
.highlight .sb { color: #cd5c5c } /* Literal.String.Backtick */
.highlight .sc { color: #cd5c5c } /* Literal.String.Char */
.highlight .sd { color: #cd5c5c } /* Literal.String.Doc */
.highlight .s2 { color: #cd5c5c } /* Literal.String.Double */
.highlight .se { color: #cd5c5c } /* Literal.String.Escape */
.highlight .sh { color: #cd5c5c } /* Literal.String.Heredoc */
.highlight .si { color: #cd5c5c } /* Literal.String.Interpol */
.highlight .sx { color: #cd5c5c } /* Literal.String.Other */
.highlight .sr { color: #cd5c5c } /* Literal.String.Regex */
.highlight .s1 { color: #cd5c5c } /* Literal.String.Single */
.highlight .ss { color: #cd5c5c } /* Literal.String.Symbol */
.highlight .bp { color: #cd00cd } /* Name.Builtin.Pseudo */
.highlight .vc { color: #00cdcd } /* Name.Variable.Class */
.highlight .vg { color: #00cdcd } /* Name.Variable.Global */
.highlight .vi { color: #00cdcd } /* Name.Variable.Instance */
.highlight .il { color: #cd00cd } /* Literal.Number.Integer.Long */

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@ -0,0 +1,95 @@
---
layout: default
title: Easy rules &bull; Xml-free open source Java&trade; rules engine.
overview: true
---
<section class="intro">
<div class="grid">
<div class="unit whole">
<p class="first">Xml-free open source Java™ rules engine.</p>
</div>
</div>
</section>
<section class="features">
<div class="grid">
<div class="unit one-third">
<h2>Lightweight</h2>
<p>
A tiny jar with no dependencies and a lot of features!
</p>
<a href="{{ site.url }}/about/getting-started.html" class="">Get started &rarr;</a>
</div>
<div class="unit one-third">
<h2>POJO based</h2>
<p>
Turn your POJOs into business rules with a couple of annotations.
</p>
<a href="{{ site.url }}/about/overview.html" class="">Read documentation &rarr;</a>
</div>
<div class="unit one-third">
<h2>Simple yet powerful</h2>
<p>
Easy rules provides a simple API to get you up and running quickly.
</p>
<a href="{{ site.url }}/tutorials/hello-world.html" class="">2 minutes tutorial &rarr;</a>
</div>
<div class="clear"></div>
</div>
</section>
<section class="quickstart">
<div class="grid">
<div class="unit code" style="width: 50%">
<p class="title">Then, fire it!</p>
<div class="shell">
<div class="highlight"><pre><code class="language-java" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size: 16px"><span class="kd">public class</span> <span class="nc">Test</span> <span class="o">{</span>
<span class="kd">public static void</span> <span class="nf">main</span><span class="o">(</span>String<span class="o">[]</span> args<span class="o">)</span> <span class="o">{</span>
<span class="c1">// create a rules engine</span>
AnnotatedRulesEngine rulesEngine <span class="o">=</span>
<span class="k">new</span> AnnotatedRulesEngine<span class="o">();</span>
<span class="c1">//register the rule</span>
rulesEngine<span class="o">.</span><span class="na">registerRule</span><span class="o">(</span><span class="k">new</span> MyRule<span class="o">());</span>
<span class="c1">//fire rules!</span>
rulesEngine<span class="o">.</span><span class="na">fireRules</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></div>
</div>
</div>
<div class="unit code" style="width: 50%">
<p class="title">First, define your rule..</p>
<div class="shell">
<div class="highlight"><pre><code class="language-java" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size: 16px"><span class="nd">@Rule</span> <span class="o">(</span>name <span class="o">=</span> <span class="s">"my awesome rule"</span> <span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyRule</span> <span class="o">{</span>
<span class="nd">@Condition</span>
<span class="kd">public boolean</span> <span class="nf">when</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> true<span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Action</span>
<span class="kd">public void</span> <span class="nf">then</span><span class="o">()</span> <span class="o">{</span>
System<span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Easy Rules rocks!"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></div>
</div>
</div>
<div class="clear"></div>
</div>
</section>
<section class="free-hosting">
<div class="grid">
<div class="unit whole">
<div class="grid pane">
<div class="unit whole center-on-mobiles">
<div class="pane-content">
<h2>License</h2>
<p>Easy Rules is open source, hosted on <a target="_blank" href="https://github.com/benas/easy-rules">GitHub</a> and is released under the <a target="_blank" href="http://opensource.org/licenses/mit-license.php/">MIT License</a>.</p>
</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</section>

File diff suppressed because one or more lines are too long

@ -0,0 +1,206 @@
---
layout: docs
title: Dynamic configuration
header: Online shop tutorial
prev_section: tutorials/hello-world
doc: true
---
In this tutorial, we have an online shop application and we would like to implement the following requirements:
1. Whenever a new customer places an order with an amount greater than a defined threshold, send an alert about this suspect order to the monitoring team.
2. Moreover, the order amount threshold should be reconfigurable via JMX so we can change it at runtime.
In the first part of this tutorial, we will see how to use Easy Rules to implement the business rule described in requirement #1.
In the second part, we will add JMX capability to the business rule developed in part 1 to be able to change the order amount threshold at runtime (requirement #2).
## Part 1 : Implementing the business rule
In this application, orders and customers are represented by the _Order_ and _Customer_ classes.
First, let's implement the rule's logic by extending the `BasicRule` class:
```java
public class SuspectOrderRule extends BasicRule {
private float suspectOrderAmountThreshold = 1000;
private Order order;
private Customer customer;
SuspectOrderRule(String name, String description) {
super(name, description);
}
@Override
public boolean evaluateConditions() {
return order.getAmount() > suspectOrderAmountThreshold
&& customer.isNew();
}
@Override
public void performActions() throws Exception {
System.out.printf("Alert : A new customer [id=%s] has placed an order [id=%s] with amount %f > %f\n",
customer.getCustomerId(), order.getOrderId(), order.getAmount(), suspectOrderAmountThreshold);
}
// getters and setters for customer and order fields omitted
}
```
This rule operates on an order and a customer instances which represent the business data to operate on.
The `evaluateConditions` method evaluates to true when the customer is new and the order amount is greater than the defined threshold.
The `performActions` method simply writes to the console the specified alert (this could be sending an email or another action in a real use case).
Then, let's create an Easy Rules engine and register the `SuspectOrderRule` rule:
```java
public class OrderSampleLauncher {
public static void main(String[] args) {
Order order = new Order(6654, 1200);
Customer customer = new Customer(2356, true);
/**
* Create a business rule instance
*/
SuspectOrderRule suspectOrderRule = new SuspectOrderRule(
"Suspect Order",
"Send alert if a new customer places an order with amount greater than a threshold");
/**
* Set data to operate on
*/
suspectOrderRule.setOrder(order);
suspectOrderRule.setCustomer(customer);
/**
* Create a default rules engine and register the business rule
*/
DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.registerRule(suspectOrderRule);
/**
* Fire rules
*/
rulesEngine.fireRules();
}
}
```
To run this tutorial, you can follow these instructions from the root directory of Easy Rules :
{% highlight bash %}
$ mvn install
$ cd easyrules-samples
$ mvn exec:java -P runOnlineShopTutorial
{% endhighlight %}
When you run this tutorial, the rule named _Suspect Order_ that we registered will be applied since the order amount (1200) is greater than the threshold (1000) and the customer 2356 is a new customer.
## Part 2 : Changing the order amount threshold at runtime
In this tutorial, we need to expose the order amount threshold as a JMX attribute. So first, let's define an interface that allows us to change order amount threshold via JMX:
```java
@javax.management.MXBean
public interface SuspectOrderJmxRule extends Rule {
/**
* Get the current suspect order amount threshold
* @return current suspect order amount threshold
*/
float getSuspectOrderAmountThreshold();
/**
* Set the suspect order amount threshold
* @param suspectOrderAmountThreshold the new suspect order amount threshold
*/
void setSuspectOrderAmountThreshold(float suspectOrderAmountThreshold);
}
```
Then, we should make our `SuspectOrderRule` implement the `SuspectOrderJmxRule` interface to expose the order amount threshold as a JMX attribute.
So here is the new `SuspectOrderRule` class:
```java
public class SuspectOrderRule extends BasicRule implements SuspectOrderJmxRule {
// same implementation of the rule
public float getSuspectOrderAmountThreshold() {
return suspectOrderAmountThreshold;
}
public void setSuspectOrderAmountThreshold(float suspectOrderAmountThreshold) {
this.suspectOrderAmountThreshold = suspectOrderAmountThreshold;
}
}
```
Finally, let's suspend the program to change the order amount threshold value at runtime via any compliant JMX client and see the engine behavior after this change:
```java
public class OrderSampleLauncher {
public static void main(String[] args) throws InterruptedException {
Order order = new Order(6654, 1200);
Customer customer = new Customer(2356, true);
/**
* Create a business rule instance
*/
SuspectOrderRule suspectOrderRule = new SuspectOrderRule(
"Suspect Order",
"Send alert if a new customer places an order with amount greater than a threshold");
/**
* Set data to operate on
*/
suspectOrderRule.setOrder(order);
suspectOrderRule.setCustomer(customer);
/**
* Create a default rules engine and register the business rule
*/
DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.registerJmxRule(suspectOrderRule);
/**
* Fire rules
*/
rulesEngine.fireRules();
// Update suspect order amount threshold via a JMX client.
Scanner scanner = new Scanner(System.in);
System.out.println("Change suspect order amount threshold to a value > 1200 via a JMX client and then press enter");
scanner.nextLine();
System.out.println("**************************************************************");
System.out.println("Re fire rules after updating suspect order amount threshold...");
System.out.println("**************************************************************");
rulesEngine.fireRules();
}
}
```
In the next screenshot, we use VisualVM to change the threshold value:
<img style="width: 100%" src="{{site.url}}/img/jmx-suspectOrderRule.png">
If you change the threshold value to 1400 for example, you will see that the rule _Suspect Order_ will not be applied the second time since the order amount (1200) is no longer greater than the new threshold (1400).
That's all! In this tutorial, we have seen how to create a real business rule with Easy Rules and how to reconfigure it at runtime.

@ -0,0 +1,108 @@
---
layout: docs
title: Hello World
header: Hello World tutorial
prev_section: user-guide/managing-rules
next_section: tutorials/dynamic-configuration
doc: true
---
This tutorial shows how to use Easy Rules on a very simple application.
The program should ask the user if he is a friend of duke and says 'Hello duke's friend!' only if he replies 'yes'.
Based on this requirement, the rule is pretty straightforward :
* The condition is that the user input must be equal to 'yes'
* The action is to say 'Hello duke's friend!' to the user
First, let's create a rule class:
```java
@Rule(name = "Hello World rule",
description = "Say Hello to only duke's friends")
public class HelloWorldRule {
/**
* The user input which represents the data
* that the rule will operate on.
*/
private String input;
@Condition
public boolean checkInput() {
//The rule should be applied only if
//the user's response is yes (duke friend)
return input.equalsIgnoreCase("yes");
}
@Action
public void sayHelloToDukeFriend() throws Exception {
//When rule conditions are satisfied,
//prints 'Hello duke's friend!' to the console
System.out.println("Hello duke's friend!");
}
public void setInput(String input) {
this.input = input;
}
}
```
Then, we have to register an instance of this rule to an Easy Rules engine and launch the program with the following class :
```java
public class HelloWorldSampleLauncher {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Are you a friend of duke?[yes/no]:");
String input = scanner.nextLine();
/**
* Declare the rule
*/
HelloWorldRule helloWorldRule = new HelloWorldRule();
/**
* Set business data to operate on
*/
helloWorldRule.setInput(input.trim());
/**
* Create a rules engine and register the business rule
*/
AnnotatedRulesEngine rulesEngine =
new AnnotatedRulesEngine();
rulesEngine.registerRule(helloWorldRule);
/**
* Fire rules
*/
rulesEngine.fireRules();
}
}
```
To run this tutorial, you can follow these instructions from the root directory of Easy Rules :
{% highlight bash %}
$ mvn install
$ cd easyrules-samples
$ mvn exec:java -P runHelloWorldTutorial
{% endhighlight %}
If you run this tutorial, you would get the following output:
```
Are you a friend of duke? [yes/no]:
yes
10 sep. 2014 13:26:19 io.github.benas.easyrules.core.DefaultRulesEngine fireRules
INFO: Rule 'Hello World rule' triggered.
Hello duke's friend!
10 sep. 2014 13:26:19 io.github.benas.easyrules.core.DefaultRulesEngine fireRules
INFO: Rule 'Hello World rule' performed successfully.
```

@ -0,0 +1,131 @@
---
layout: docs
title: Defining rules
header: Defining rules
prev_section: user-guide/introduction
next_section: user-guide/rules-engine
doc: true
---
The key API in Easy Rules is the `Rule` interface:
```java
public interface Rule {
/**
* This method encapsulates the rule's conditions.
* @return true if the rule should be applied, false else
*/
boolean evaluateConditions();
/**
* This method encapsulates the rule's actions.
* @throws Exception thrown if an exception occurs
* during actions performing
*/
void performActions() throws Exception;
//Getters and setters for rule name,
//description and priority omitted.
}
```
The `evaluateConditions` method encapsulates conditions that must evaluate to _TRUE_ to trigger the rule.
The `performActions` method encapsulates actions that should be performed when rule's conditions are satisfied.
## Defining rules by extending _BasicRule_
Easy Rules provides a simple implementation of the `Rule` interface named `BasicRule`. This class implements most of methods
defined in the `Rule` interface. You can extends this class and override `evaluateConditions` and
`performActions` methods to provide your conditions and actions logic. Here is an example:
```java
public class MyRule extends BasicRule {
private BusinessData myBusinessData; //data to operate on
@Override
public boolean evaluateConditions() {
//my rule conditions
return true;
}
@Override
public void performActions() throws Exception {
//my actions
}
}
```
## Defining rules using annotations
Easy Rules provides the `@Rule` annotation that can turn a POJO into a rule. Here is an example:
```java
@Rule(name = "my rule", description = "my rule description")
public class MyRule {
private BusinessData myBusinessData; //data to operate on
@Condition
public boolean checkConditions() {
//my rule conditions
return true;
}
@Action
public void performActions() throws Exception {
//my actions
}
}
```
You can use `@Condition` and `@Action` annotations to mark methods to execute to check rule conditions and perform rule actions
respectively.
<div class="note info">
<h5>Rules can have multiple actions</h5>
<p>You can annotate multiple methods with the <em>Action</em> annotation. You can also define the execution order of actions with the
<em>order</em> attribute: <em>@Action(order = 1)</em>.</p>
</div>
## Composite rules
Easy Rules allows you to create complex rules from primitive ones. A `CompositeRule` is composed of a set of rules.
This is typically an implementation of the [composite design pattern](http://en.wikipedia.org/wiki/Composite_pattern).
A composite rule is triggered if _all_ conditions of its composing rules are satisfied.
When a composite rule is applied, actions of _all_ composing rules are performed in the natural order of
rules which is rules priorities by default.
To create a composite rule from two primitive rules, you can use the following snippet:
```java
//Create the composite rule from two primitive rules
CompositeRule myCompositeRule =
new CompositeRule("myCompositeRule", "a composite rule");
myCompositeRule.addRule(myRule1);
myCompositeRule.addRule(myRule2);
//Register the composite rule as a regular rule
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.registerRule(myCompositeRule);
```
## Rules priorities
Each rule in Easy Rules has a priority. This represents the default order in which registered rules are fired.
By default, lower values represent higher priorities.
To override this behavior, you should override the `compareTo` method to provide a custom priority strategy.
* If you decided to extend the `BasicRule` class, you can specify rule priority at construction time or by overriding
the `getPriority()` method
* If your rule is a annotated POJO, you should annotate the method that provides priority with `@Priority` annotation.
This method must be public, have no arguments and return an Integer type

@ -0,0 +1,21 @@
---
layout: docs
title: Introduction
header: Introduction
prev_section: about/getting-started
next_section: user-guide/defining-rules
doc: true
---
Most business rules can be represented by the following rule definition:
* _Name_: a unique rule name within a rules namespace
* _Description_: a brief description of the rule
* _Priority_: rule priority regarding to other rules
* _Conditions_: set of conditions that should be satisfied to apply the rule
* _Actions_: set of actions to perform when conditions are satisfied
Easy Rules provides an abstraction for each of these key points that define a business rule.
Next section will show you how to define a rule in Easy Rules either by extending a base class or by annotating your
own domain class.

@ -0,0 +1,28 @@
---
layout: docs
title: Managing rules
header: Managing rules at runtime
prev_section: user-guide/rules-engine
next_section: tutorials/hello-world
doc: true
---
Being able to dynamically reconfigure business rules at runtime in production systems is a recurrent requirement.
Thanks to JMX, Easy Rules can expose rules attributes to be managed via any JMX compliant client.
To make your rule manageable via JMX, you can register it in Easy Rules engine as a JMX managed rule:
```java
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.registerJmxRule(myRule);
```
This will register your rule as a JMX managed bean with the following object name:
`org.easyrules.core.jmx:type=YourRuleClassName,name=YourRuleName`
By default, rule description and priority are exposed as JMX manageable attributes.
If you need to expose more specific attributes, you can extend the `Rule` interface and add getters and setters of your manageable attributes.
An example of using dynamic rule reconfiguration at runtime is provided in the [online shop tutorial]({{site.url}}/tutorials/dynamic-configuration.html).

@ -0,0 +1,75 @@
---
layout: docs
title: Rules engine
header: Rules engine
prev_section: user-guide/defining-rules
next_section: user-guide/managing-rules
doc: true
---
Easy Rules engine handles a registry of rules with unique names. Each instance of Easy Rules engine can be seen as a separate namespace.
Rules are applied according to their natural order.
Easy Rules engine provides the following parameters:
<table>
<thead>
<tr class="active">
<th>Parameter</th>
<th>Type</th>
<th>Required</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>skipOnFirstAppliedRule</td>
<td>boolean</td>
<td>no</td>
<td>false</td>
</tr>
<tr>
<td>rulePriorityThreshold</td>
<td>int</td>
<td>no</td>
<td>Integer.MAX_VALUE</td>
</tr>
</tbody>
</table>
The `skipOnFirstAppliedRule` parameter tells the engine to skip next applicable rules when a rule is applied.
The `rulePriorityThreshold` parameters tells the engine to skip next rules if priority exceeds the defined threshold.
You can specify these parameters at rules engine construction time.
## Create a default rules engine
To create a default Easy Rules engine and register a rule, use the following snippet:
```java
RulesEngine<Rule> rulesEngine = new DefaultRulesEngine();
rulesEngine.registerRule(myRule);
```
You can fire registered rules as follows:
```java
rulesEngine.fireRules();
```
## Create a annotated rules engine
If your rules are annotated POJOs, you have to use the `AnnotatedRulesEngine` to register them:
```java
AnnotatedRulesEngine rulesEngine = new AnnotatedRulesEngine();
rulesEngine.registerRule(myRule);
```
As with default engine, you can fire rules using the following snippet :
```java
rulesEngine.fireRules();
```
Loading…
Cancel
Save