Skip to content

Commit

Permalink
Merge pull request #11 from zweidenker/code-and-library-documentation
Browse files Browse the repository at this point in the history
Code and library documentation
  • Loading branch information
bocasti authored Jan 30, 2020
2 parents 635e6a3 + fae608b commit 150cd08
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 13 deletions.
10 changes: 5 additions & 5 deletions Cinic-Core.package/Cinic.class/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ I'm a Configuration holding access to static and dynamic configuration elements.
Loading
=======

config := Configuration readFileNamed: 'config.json'.
config := Cinic readFileNamed: 'config.json'.
config apply.

Global use:
Expand All @@ -15,7 +15,7 @@ A configuration can be made globally available by issuing

Code can then access

Confguration default
Cinic default

Script usage
============
Expand All @@ -35,9 +35,9 @@ In-Image usage
Components can be annotated using pragmas

myConfiguration
<configurationStep>
^ ConfigurationStep new
group: #server;
<cinicStep>
^ CinicStep new
section: #server;
action: [ :config | MyServer port: config port ].
In order to apply the configuration to the image you need to evaluate
Expand Down
2 changes: 1 addition & 1 deletion Cinic-Core.package/Cinic.class/properties.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"commentStamp" : "NorbertHartl 4/23/2019 16:56",
"commentStamp" : "cdelaunay 1/28/2020 16:24",
"super" : "Object",
"category" : "Cinic-Core",
"classinstvars" : [
Expand Down
5 changes: 4 additions & 1 deletion Cinic-Core.package/CinicSection.class/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
I'm a ConfigurationSection. I hold one level of properties and I can be nested. I'm reflecting a hierarchical configuration format like JSON where every JSON object maps to an instance of my class. I'm a subclass to dictionary therefor
I'm a Configuration Section.
I hold one level of properties and I can be nested.
I'm reflecting a hierarchical configuration format like JSON where every JSON object maps to an instance of my class.
I'm a subclass to dictionary therefor
2 changes: 1 addition & 1 deletion Cinic-Core.package/CinicSection.class/properties.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"commentStamp" : "NorbertHartl 4/23/2019 16:57",
"commentStamp" : "cdelaunay 1/28/2020 14:32",
"super" : "OrderedDictionary",
"category" : "Cinic-Core",
"classinstvars" : [ ],
Expand Down
4 changes: 3 additions & 1 deletion Cinic-Core.package/CinicStep.class/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
I'm a ConfguratinStep. I reify a single action that needs to be executed in order to configure an image. I'm collect by the root configuration to prepare a list of configuration actions
I'm a Configuration Step.
I reify a single action that needs to be executed in order to configure an image.
I'm collected by the root configuration to prepare a list of configuration actions
2 changes: 1 addition & 1 deletion Cinic-Core.package/CinicStep.class/properties.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"commentStamp" : "NorbertHartl 4/23/2019 16:59",
"commentStamp" : "cdelaunay 1/28/2020 14:37",
"super" : "Object",
"category" : "Cinic-Core",
"classinstvars" : [ ],
Expand Down
3 changes: 2 additions & 1 deletion Cinic-Core.package/CurrentCinic.class/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
I'm a dynamic variable to acquire configuration objects in code. I'm used in all nesting actions when sections are used.
I'm a dynamic variable to acquire configuration objects in code.
I'm used in all nesting actions when sections are used.
2 changes: 1 addition & 1 deletion Cinic-Core.package/CurrentCinic.class/properties.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"commentStamp" : "NorbertHartl 4/23/2019 16:58",
"commentStamp" : "cdelaunay 1/28/2020 14:39",
"super" : "DynamicVariable",
"category" : "Cinic-Core",
"classinstvars" : [ ],
Expand Down
166 changes: 165 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,167 @@
# pharo-configuration

[![Build Status](https://travis-ci.org/zweidenker/Configurator.svg?branch=master)](https://travis-ci.org/zweidenker/Configurator)

# Installation:

Cinic is a [Pharo](https://pharo.org/) library that aims to help managing external configuration files.
It can be loaded into a pharo image with:

```smalltalk
Metacello new
repository: 'https://github.com/zweidenker/Cinic:0.2’;
baseline: 'Cinic';
load
```


While the model of Cinic is format-agnostic,
the current implemented parser expects a configuration to comes in the form of a JSON file.
The parser could later be extended to other formats if needed.


Here is a contents example of such a configuration file:

```
{
“section1” :
{
“property1” : “value1”
} ,
“section2” :
{
“section21” :
{
“property2” : “value2”
{
}
}
```

# Loading configuration files:

A configuration file can be loaded by executing:

```smalltalk
config := Cinic readFileNamed: 'config.json'.
```

The resulting Cinic object will be the entry point for traversing the imported configuration.

# Model:

Cinic models configuration as a tree of Sections.
The root Section represents the root of the configuration file.
Sections can be nested without limitations.

Regarding the implementation, a Section object is nothing more than a specialised Dictionary object.
Its keys are property or section names,
Its values are property values or Section objects.

# Scripting actions:

In order to act upon a configuration, Cinic provides some scripting facilities.
After loading the above configuration example, one could excecute:

```smalltalk
#section1 sectionIn: config do: [ :aSection |
Transcript show: aSection property1
].
#section2 sectionIn: config do: [ :aSection |
#section21 sectionIn: aSection do: [:aNestedSection |
Transcript show: aSection property2
]
].
```

Note that property names can be turned into messages send to a Section object.
Cinic will automatically "translate" such unknown messages, and made them return the associated property value.

When iterating over inner sections of a configuration, Cinic will store the current section in a dynamic variable.
The above script can then be simplified as:

```smalltalk
#section2 sectionIn: config do: [ :aSection |
#section21 sectionDo: [:aNestedSection |
Transcript show: aSection property2
]
].
```

# Implementing actions:

An alternative to scripting configuration actions is to implement them as method.
This may be useful if you want to share a common action behaviour between multiple kind of configurations.
This can be done by using Steps.

## Steps definition

A Step knows about a Section path and an action block.
The action block is expected to be executed with an associated Section object as argument:

```smalltalk
CinicStep new
section: #section1;
action: [ :aSection1 | Transcript show: aSection1 property1 ].
```

A Step is intended to be returned by methods providing a `<cinicStep>` pragma:

```smalltalk
section21SetUp
<cinicStep>
^ CinicStep new
section: #section21;
action: [ :aSection21 | Transcript show: aSection property2 ].
```

## Steps execution

After loading a configuration, one can execute the Steps associated to this configuration by executing .

```smalltalk
config := Cinic readFileNamed: 'config.json'.
config apply.
```

When applying a configuration, Cinic will gather all methods in the pharo image with pragma `<cinicStep>`.
It will select the steps matching a section path in the configuration, and execute them.

The steps will be executed in the same order than the file sections order.


## Steps section path

The above example shows the case of a "standalone" section: #section21.
As soon as a configuration file includes a section with name #section21, the Step will be executed.
But a Step could also target a more precise section path:

```smalltalk
section1SetUp
<cinicStep>
^ CinicStep new
sectionPath: #(section2 section21);
action: [ :aSection21 | Transcript show: aSection property1 ].
```

In this case, the Step would be executed only if the configuration file provide a section with name #section2,
followed by a section with name #section21.
The block would be evaluated with the #section21 associated object.

# Global use:

After being loaded, a configuration can also be made globally available in the Pharo image with:

```smalltalk
config beDefault
```

Code can then access

```smalltalk
Cinic default
```





0 comments on commit 150cd08

Please sign in to comment.