Skip to content

Commit

Permalink
Working on documenation
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-lischke committed Jan 15, 2024
1 parent 51e301d commit 28a0b67
Show file tree
Hide file tree
Showing 22 changed files with 62 additions and 598 deletions.
177 changes: 0 additions & 177 deletions doc/3to4.md

This file was deleted.

106 changes: 54 additions & 52 deletions doc/adaptors.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
# Model adaptors
# Model Adaptors

StringTemplate lets you access the properties of injected attributes, but only if they follow the JavaBeans naming pattern ("getters") or are publicly visible fields.
This works well if you control the attribute class definitions, but falls apart for some models.
Some models, though, don't follow the getter method naming convention and so template expressions cannot access properties.
To get around this, we need a model adaptor that makes external models look like the kind StringTemplate needs.
If object `o` is of type `T`, we register a model adaptor object, `a`, for `T` that converts property references on `o`.
Given `<o.foo>`, StringTemplate will ask `a` to get the value of property `foo`.
As with renderers, `a` is a suitable adaptor if "`o` is instance of `a`'s associated type".
For the statically typed language ports, here are the interfaces:
StringTemplate lets you access the properties of injected attributes, but only if they follow a specific naming pattern (`hasXXX`, `getXXX`, `isXXX`) or are publicly visible fields. This works well if you control the attribute class definitions, but falls apart for some models.

```java
public interface ModelAdaptor<T> {
Object getProperty(Interpreter interpreter, ST self, T model, Object property, String propertyName)
throws STNoSuchPropertyException;
Some models, though, don't follow the getter method naming convention and so template expressions cannot access properties. To get around this, we need a model adaptor that makes external models look like the kind StringTemplate needs. If object `o` is of type `T`, we register a model adaptor object, `a`, for `T` that converts property references on `o`. Given `<o.foo>`, StringTemplate will ask `a` to get the value of property `foo`. As with renderers, `a` is a suitable adaptor if "`o` is instance of `a`'s associated type".

This is the adaptor interfaces:

```typescript
export interface ModelAdaptor<T> {
getProperty(interp: IInterpreter, self: IST, model: T, property: unknown, propertyName: string): unknown;
}
```

Expand All @@ -22,33 +18,35 @@ public interface ModelAdaptor<T> {

## Example 1

```java
```typescript
class UserAdaptor implements ModelAdaptor<User> {
public Object getProperty(Interpreter interpreter, ST self, User model, Object property, String propertyName)
throws STNoSuchPropertyException
{
if ( propertyName.equals("id") ) return model.id;
if ( propertyName.equals("name") ) return model.theName();
throw new STNoSuchPropertyException(null, "User."+propertyName);
public getProperty(interpreter: IInterpreter, self: IST, model: User, property: unknown, propertyName: string): unknown {
if (propertyName === "id") {
return model.id;
}
if (propertyName === "name") {
return model.theName();
}
throw new STNoSuchPropertyException(null, "User." + propertyName);
}
}

public static class User {
private int id; // ST can't see; it's private
private String name;
public User(int id, String name) { this.id = id; this.name = name; }
public String theName() { return name; } // doesn't follow naming conventions
class User {
private id: number; // ST can't see; it's private
private name: string;
public constructor(id: number, name: string) { this.id = id; this.name = name; }
public theName(): string { return name; } // doesn't follow naming conventions
}
```

```java
String template = "foo(x) ::= \"<x.id>: <x.name>\"\n";
STGroup g = new STGroupString(template);
g.registerModelAdaptor(User.class, new UserAdaptor());
ST st = g.getInstanceOf("foo");
st.add("x", new User(100, "parrt"));
String expecting = "100: parrt";
String result = st.render();
```typescript
const template = "foo(x) ::= \"<x.id>: <x.name>\"\n";
const g = new STGroupString(template);
g.registerModelAdaptor(User, new UserAdaptor());
const st = g.getInstanceOf("foo");
st?.add("x", new User(100, "parrt"));
const expecting = "100: parrt";
const result = st?.render();
```

|Inheriting from `ObjectModelAdaptor`|
Expand All @@ -57,33 +55,37 @@ String result = st.render();

## Example 2

```java
```typescript
class UserAdaptor extends ObjectModelAdaptor<User> {
public Object getProperty(Interpreter interpreter, ST self, User model, Object property, String propertyName)
throws STNoSuchPropertyException
{
public getProperty(interpreter: IInterpreter, self: IST, model: User, property: unknown, propertyName: string): unknown {
// intercept handling of "name" property and capitalize first character
if ( propertyName.equals("name") ) return model.name.substring(0,1).toUpperCase()+model.name.substring(1);
if (propertyName === "name") {
return model.name[0].toUpperCase() + model.name.substring(1);
}

// respond to "description" property by composing desired result
if ( propertyName.equals("description") ) return "User object with id:" + model.id;
if (propertyName === "description") {
return "User object with id:" + model.id;
}

// let "id" be handled by ObjectModelAdaptor
return super.getProperty(interpreter,self,model,property,propertyName);
return super.getProperty(interpreter, self, model, property, propertyName);
}
}

public static class User {
public int id; // ST can see this and we'll let ObjectModelAdaptor handle it
public String name; // ST can see this, but we'll override to capitalize
public User(int id, String name) { this.id = id; this.name = name; }
class User {
public id: number; // ST can see this and we'll let ObjectModelAdaptor handle it
public name: string; // ST can see this, but we'll override to capitalize
public constructor(id: number, name: string) { this.id = id; this.name = name; }
}
```

```java
String template = "foo(x) ::= \"<x.id>: <x.name> (<x.description>)\"\n";
STGroup g = new STGroupString(template);
g.registerModelAdaptor(User.class, new UserAdaptor());
ST st = g.getInstanceOf("foo");
st.add("x", new User(100, "parrt"));
String expecting = "100: Parrt (User object with id:100)";
String result = st.render();
```typescript
const template = "foo(x) ::= \"<x.id>: <x.name> (<x.description>)\"\n";
const g = new STGroupString(template);
g.registerModelAdaptor(User, new UserAdaptor());
const st = g.getInstanceOf("foo");
st?.add("x", new User(100, "parrt"));
const expecting = "100: Parrt (User object with id:100)";
const result = st?.render();
```
14 changes: 0 additions & 14 deletions doc/faq/index.md

This file was deleted.

Binary file removed doc/images/AST.png
Binary file not shown.
Binary file removed doc/images/attrstack.gif
Binary file not shown.
Binary file removed doc/images/bytecode.png
Binary file not shown.
Binary file removed doc/images/outputclick.gif
Binary file not shown.
Binary file removed doc/images/startup.gif
Binary file not shown.
Binary file removed doc/images/trace.png
Binary file not shown.
Loading

0 comments on commit 28a0b67

Please sign in to comment.