or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

appenders.mdconfiguration.mdencoders-layouts.mdfilters-evaluators.mdindex.mdmodel-framework.mdnetwork-logging.mdpatterns.mdrolling-policies.mdutilities.md

model-framework.mddocs/

0

# Model Framework

1

2

Configuration model system that provides hierarchical representation of logback components with processing, state tracking, serialization support, and integration with the Joran configuration framework. The Model framework serves as the bridge between XML configuration and component instantiation.

3

4

## Capabilities

5

6

### Core Model Architecture

7

8

#### Model Base Class

9

10

The foundational class representing configuration components in a hierarchical structure.

11

12

```java { .api }

13

/**

14

* Base class for all configuration models in the logback framework.

15

* Provides hierarchical structure, processing state, and serialization support.

16

*/

17

public class Model implements Serializable {

18

/**

19

* Get the line number where this model was defined in configuration.

20

* @return line number in source configuration

21

*/

22

public int getLineNumber();

23

24

/**

25

* Set the line number for this model.

26

* @param lineNumber line number in source configuration

27

*/

28

public void setLineNumber(int lineNumber);

29

30

/**

31

* Get the parent model in the hierarchy.

32

* @return parent model or null if this is root

33

*/

34

public Model getParent();

35

36

/**

37

* Set the parent model.

38

* @param parent parent model

39

*/

40

public void setParent(Model parent);

41

42

/**

43

* Add a child model to this model.

44

* @param child child model to add

45

*/

46

public void addSubModel(Model child);

47

48

/**

49

* Get all child models.

50

* @return list of child models

51

*/

52

public List<Model> getSubModels();

53

54

/**

55

* Get processing state for this model.

56

* @return true if model has been processed

57

*/

58

public boolean isProcessed();

59

60

/**

61

* Mark this model as processed.

62

* @param processed processing state

63

*/

64

public void setProcessed(boolean processed);

65

66

/**

67

* Get the tag name associated with this model.

68

* @return XML tag name

69

*/

70

public String getTag();

71

72

/**

73

* Set the tag name for this model.

74

* @param tag XML tag name

75

*/

76

public void setTag(String tag);

77

78

/**

79

* Get the body text content of this model.

80

* @return body text or null

81

*/

82

public String getBodyText();

83

84

/**

85

* Set the body text content.

86

* @param bodyText text content

87

*/

88

public void setBodyText(String bodyText);

89

90

/**

91

* Check if this model has been marked.

92

* Used for processing control and cycle detection.

93

* @return true if marked

94

*/

95

public boolean isMarked();

96

97

/**

98

* Mark this model for processing control.

99

* @param marked marking state

100

*/

101

public void setMarked(boolean marked);

102

}

103

```

104

105

### Component Model Hierarchy

106

107

#### ComponentModel

108

109

Base class for models representing configurable components.

110

111

```java { .api }

112

/**

113

* Model for configurable components with class name and property support.

114

*/

115

public class ComponentModel extends Model {

116

/**

117

* Get the component class name.

118

* @return fully qualified class name

119

*/

120

public String getClassName();

121

122

/**

123

* Set the component class name.

124

* @param className fully qualified class name

125

*/

126

public void setClassName(String className);

127

128

/**

129

* Get the component class object.

130

* @return Class object or null

131

*/

132

public Class<?> getClazz();

133

134

/**

135

* Set the component class object.

136

* @param clazz Class object

137

*/

138

public void setClazz(Class<?> clazz);

139

}

140

```

141

142

#### NamedComponentModel

143

144

Model for components that have names (like appenders, filters).

145

146

```java { .api }

147

/**

148

* Model for named components like appenders and filters.

149

*/

150

public class NamedComponentModel extends ComponentModel implements INamedModel {

151

/**

152

* Get the component name.

153

* @return component name

154

*/

155

public String getName();

156

157

/**

158

* Set the component name.

159

* @param name component name

160

*/

161

public void setName(String name);

162

}

163

```

164

165

#### INamedModel Interface

166

167

Interface for models that have names.

168

169

```java { .api }

170

/**

171

* Interface for models that can be identified by name.

172

*/

173

public interface INamedModel {

174

/**

175

* Get the model name.

176

* @return model name

177

*/

178

String getName();

179

180

/**

181

* Set the model name.

182

* @param name model name

183

*/

184

void setName(String name);

185

}

186

```

187

188

### Configuration Models

189

190

#### AppenderModel

191

192

Model representing appender configuration.

193

194

```java { .api }

195

/**

196

* Model for appender configuration with encoder and filter support.

197

*/

198

public class AppenderModel extends NamedComponentModel {

199

/**

200

* Get the encoder model.

201

* @return encoder model or null

202

*/

203

public EncoderModel getEncoder();

204

205

/**

206

* Set the encoder model.

207

* @param encoder encoder model

208

*/

209

public void setEncoder(EncoderModel encoder);

210

211

/**

212

* Get all filter models.

213

* @return list of filter models

214

*/

215

public List<FilterModel> getFilterModels();

216

217

/**

218

* Add a filter model.

219

* @param filterModel filter model to add

220

*/

221

public void addFilterModel(FilterModel filterModel);

222

}

223

```

224

225

#### PropertyModel

226

227

Model for property definitions and references.

228

229

```java { .api }

230

/**

231

* Model for property definitions with name, value, and scope.

232

*/

233

public class PropertyModel extends Model {

234

/**

235

* Get the property name.

236

* @return property name

237

*/

238

public String getName();

239

240

/**

241

* Set the property name.

242

* @param name property name

243

*/

244

public void setName(String name);

245

246

/**

247

* Get the property value.

248

* @return property value

249

*/

250

public String getValue();

251

252

/**

253

* Set the property value.

254

* @param value property value

255

*/

256

public void setValue(String value);

257

258

/**

259

* Get the property scope.

260

* @return property scope (context, system, local)

261

*/

262

public String getScope();

263

264

/**

265

* Set the property scope.

266

* @param scope property scope

267

*/

268

public void setScope(String scope);

269

270

/**

271

* Get the source for property value.

272

* @return source reference (file, resource, url)

273

*/

274

public String getSource();

275

276

/**

277

* Set the source for property value.

278

* @param source source reference

279

*/

280

public void setSource(String source);

281

}

282

```

283

284

#### ConditionalModel

285

286

Model for conditional configuration logic.

287

288

```java { .api }

289

/**

290

* Model for conditional configuration based on properties or expressions.

291

*/

292

public class ConditionalModel extends Model {

293

/**

294

* Get the condition expression.

295

* @return condition expression

296

*/

297

public String getCondition();

298

299

/**

300

* Set the condition expression.

301

* @param condition condition to evaluate

302

*/

303

public void setCondition(String condition);

304

305

/**

306

* Get the then models (executed if condition is true).

307

* @return list of then models

308

*/

309

public List<Model> getThenModels();

310

311

/**

312

* Add a model to the then branch.

313

* @param model model to add

314

*/

315

public void addThenModel(Model model);

316

317

/**

318

* Get the else models (executed if condition is false).

319

* @return list of else models

320

*/

321

public List<Model> getElseModels();

322

323

/**

324

* Add a model to the else branch.

325

* @param model model to add

326

*/

327

public void addElseModel(Model model);

328

}

329

```

330

331

### Model Processing Framework

332

333

#### ModelHandlerBase

334

335

Base class for model handlers that process specific model types.

336

337

```java { .api }

338

/**

339

* Base class for handlers that process specific model types.

340

* Provides context access and common processing utilities.

341

*/

342

public abstract class ModelHandlerBase extends ContextAwareBase {

343

protected ModelInterpretationContext mic;

344

345

/**

346

* Check if this handler can handle the given model.

347

* @param model model to check

348

* @return true if this handler can process the model

349

*/

350

public abstract boolean isSuitableForModel(Model model);

351

352

/**

353

* Handle the model processing.

354

* @param mic model interpretation context

355

* @param model model to process

356

* @throws ModelHandlerException if processing fails

357

*/

358

public abstract void handle(ModelInterpretationContext mic, Model model)

359

throws ModelHandlerException;

360

361

/**

362

* Post-handle processing after all children are processed.

363

* @param mic model interpretation context

364

* @param model model being processed

365

* @throws ModelHandlerException if post-processing fails

366

*/

367

public void postHandle(ModelInterpretationContext mic, Model model)

368

throws ModelHandlerException;

369

}

370

```

371

372

#### ModelInterpretationContext

373

374

Context for model processing providing access to objects, properties, and processing state.

375

376

```java { .api }

377

/**

378

* Context for model interpretation providing access to processing state.

379

*/

380

public class ModelInterpretationContext extends ContextAwareBase {

381

/**

382

* Get an object by key.

383

* @param key object key

384

* @return stored object or null

385

*/

386

public Object getObject(String key);

387

388

/**

389

* Store an object by key.

390

* @param key object key

391

* @param value object to store

392

*/

393

public void putObject(String key, Object value);

394

395

/**

396

* Push an object onto the processing stack.

397

* @param obj object to push

398

*/

399

public void pushObject(Object obj);

400

401

/**

402

* Pop an object from the processing stack.

403

* @return popped object

404

*/

405

public Object popObject();

406

407

/**

408

* Peek at the top object on the stack.

409

* @return top object without removing it

410

*/

411

public Object peekObject();

412

413

/**

414

* Check if the stack is empty.

415

* @return true if stack is empty

416

*/

417

public boolean isObjectStackEmpty();

418

419

/**

420

* Get property value with variable substitution.

421

* @param key property key

422

* @return property value with substitutions applied

423

*/

424

public String getProperty(String key);

425

426

/**

427

* Substitute variables in the given value.

428

* @param value value with potential variables

429

* @return value with variables substituted

430

*/

431

public String subst(String value);

432

433

/**

434

* Get the dependency analyzer for tracking component dependencies.

435

* @return dependency analyzer

436

*/

437

public DependencyAnalyzer getDependencyAnalyzer();

438

}

439

```

440

441

#### ModelHandlerException

442

443

Exception thrown during model processing.

444

445

```java { .api }

446

/**

447

* Exception thrown when model processing fails.

448

*/

449

public class ModelHandlerException extends Exception {

450

/**

451

* Create exception with message.

452

* @param msg error message

453

*/

454

public ModelHandlerException(String msg);

455

456

/**

457

* Create exception with message and cause.

458

* @param msg error message

459

* @param cause underlying cause

460

*/

461

public ModelHandlerException(String msg, Throwable cause);

462

}

463

```

464

465

#### DefaultProcessor

466

467

Main processor that orchestrates model processing through registered handlers.

468

469

```java { .api }

470

/**

471

* Default processor that handles model processing through registered handlers.

472

*/

473

public class DefaultProcessor extends ContextAwareBase {

474

/**

475

* Add a model handler.

476

* @param modelHandler handler to add

477

*/

478

public void addHandler(ModelHandlerBase modelHandler);

479

480

/**

481

* Process a model and its children.

482

* @param mic model interpretation context

483

* @param model model to process

484

* @throws ModelHandlerException if processing fails

485

*/

486

public void process(ModelInterpretationContext mic, Model model)

487

throws ModelHandlerException;

488

489

/**

490

* Find a suitable handler for the given model.

491

* @param model model to find handler for

492

* @return suitable handler or null

493

*/

494

protected ModelHandlerBase getSuitableModelHandler(Model model);

495

}

496

```

497

498

### Integration with Joran

499

500

#### BaseModelAction

501

502

Base action class that bridges SAX parsing and model creation.

503

504

```java { .api }

505

/**

506

* Base action for creating models from SAX events.

507

*/

508

public abstract class BaseModelAction extends Action {

509

/**

510

* Create a model instance for the current element.

511

* @param ic interpretation context

512

* @param localName element local name

513

* @param attributes element attributes

514

* @return created model instance

515

*/

516

protected abstract Model buildCurrentModel(InterpretationContext ic,

517

String localName, Attributes attributes);

518

519

/**

520

* Build model from SAX start element.

521

* @param ic interpretation context

522

* @param localName element local name

523

* @param attributes element attributes

524

*/

525

@Override

526

public void begin(InterpretationContext ic, String localName,

527

Attributes attributes) throws ActionException;

528

529

/**

530

* Set body text on the model.

531

* @param ic interpretation context

532

* @param body element body text

533

*/

534

@Override

535

public void body(InterpretationContext ic, String body)

536

throws ActionException;

537

538

/**

539

* Finalize model creation.

540

* @param ic interpretation context

541

* @param localName element local name

542

*/

543

@Override

544

public void end(InterpretationContext ic, String localName)

545

throws ActionException;

546

}

547

```

548

549

### Utility Classes

550

551

#### ModelUtil

552

553

Utility methods for model processing and manipulation.

554

555

```java { .api }

556

/**

557

* Utility methods for model processing.

558

*/

559

public class ModelUtil {

560

/**

561

* Deep clone a model hierarchy.

562

* @param model model to clone

563

* @return cloned model

564

*/

565

public static Model deepClone(Model model);

566

567

/**

568

* Find models of a specific type in the hierarchy.

569

* @param root root model to search from

570

* @param modelClass class of models to find

571

* @return list of matching models

572

*/

573

public static <T extends Model> List<T> findModelsOfType(Model root,

574

Class<T> modelClass);

575

576

/**

577

* Substitute variables in all string properties of a model.

578

* @param mic model interpretation context

579

* @param model model to process

580

*/

581

public static void substituteVariables(ModelInterpretationContext mic,

582

Model model);

583

584

/**

585

* Reset processing state for a model hierarchy.

586

* @param model root model to reset

587

*/

588

public static void resetProcessingState(Model model);

589

}

590

```

591

592

## Usage Examples

593

594

### Creating a Custom Model

595

596

```java

597

import ch.qos.logback.core.model.ComponentModel;

598

import ch.qos.logback.core.model.INamedModel;

599

600

public class CustomFilterModel extends ComponentModel implements INamedModel {

601

private String name;

602

private String pattern;

603

private boolean caseSensitive = true;

604

605

@Override

606

public String getName() {

607

return name;

608

}

609

610

@Override

611

public void setName(String name) {

612

this.name = name;

613

}

614

615

public String getPattern() {

616

return pattern;

617

}

618

619

public void setPattern(String pattern) {

620

this.pattern = pattern;

621

}

622

623

public boolean isCaseSensitive() {

624

return caseSensitive;

625

}

626

627

public void setCaseSensitive(boolean caseSensitive) {

628

this.caseSensitive = caseSensitive;

629

}

630

}

631

```

632

633

### Creating a Custom Model Handler

634

635

```java

636

import ch.qos.logback.core.model.processor.ModelHandlerBase;

637

import ch.qos.logback.core.model.processor.ModelInterpretationContext;

638

import ch.qos.logback.core.model.processor.ModelHandlerException;

639

640

public class CustomFilterModelHandler extends ModelHandlerBase {

641

642

@Override

643

public boolean isSuitableForModel(Model model) {

644

return model instanceof CustomFilterModel;

645

}

646

647

@Override

648

public void handle(ModelInterpretationContext mic, Model model)

649

throws ModelHandlerException {

650

CustomFilterModel cfm = (CustomFilterModel) model;

651

652

// Create the actual filter instance

653

CustomFilter filter = new CustomFilter();

654

filter.setContext(context);

655

filter.setName(cfm.getName());

656

filter.setPattern(cfm.getPattern());

657

filter.setCaseSensitive(cfm.isCaseSensitive());

658

659

// Validate configuration

660

if (cfm.getPattern() == null) {

661

addError("Pattern is required for CustomFilter");

662

return;

663

}

664

665

// Store in context for reference by other components

666

if (cfm.getName() != null) {

667

mic.putObject(cfm.getName(), filter);

668

}

669

670

// Add to parent component if applicable

671

Object parent = mic.peekObject();

672

if (parent instanceof FilterAttachable) {

673

((FilterAttachable<?>) parent).addFilter(filter);

674

}

675

676

filter.start();

677

}

678

}

679

```

680

681

### Using the Default Processor

682

683

```java

684

import ch.qos.logback.core.model.processor.DefaultProcessor;

685

import ch.qos.logback.core.model.processor.ModelInterpretationContext;

686

687

// Create processor and register handlers

688

DefaultProcessor processor = new DefaultProcessor();

689

processor.setContext(context);

690

691

// Add standard handlers

692

processor.addHandler(new AppenderModelHandler());

693

processor.addHandler(new FilterModelHandler());

694

processor.addHandler(new CustomFilterModelHandler());

695

696

// Create interpretation context

697

ModelInterpretationContext mic = new ModelInterpretationContext(context);

698

699

// Process model hierarchy

700

try {

701

processor.process(mic, rootModel);

702

} catch (ModelHandlerException e) {

703

addError("Failed to process model", e);

704

}

705

```

706

707

### Model-based Configuration Action

708

709

```java

710

import ch.qos.logback.core.joran.action.BaseModelAction;

711

import ch.qos.logback.core.joran.spi.InterpretationContext;

712

713

public class CustomFilterAction extends BaseModelAction {

714

715

@Override

716

protected Model buildCurrentModel(InterpretationContext ic,

717

String localName, Attributes attributes) {

718

CustomFilterModel model = new CustomFilterModel();

719

model.setTag(localName);

720

721

// Set properties from attributes

722

String name = attributes.getValue("name");

723

if (name != null) {

724

model.setName(name);

725

}

726

727

String className = attributes.getValue("class");

728

if (className != null) {

729

model.setClassName(className);

730

}

731

732

String pattern = attributes.getValue("pattern");

733

if (pattern != null) {

734

model.setPattern(pattern);

735

}

736

737

String caseSensitive = attributes.getValue("caseSensitive");

738

if (caseSensitive != null) {

739

model.setCaseSensitive(Boolean.parseBoolean(caseSensitive));

740

}

741

742

return model;

743

}

744

}

745

```

746

747

## Model Processing Phases

748

749

The Model framework processes configuration in distinct phases:

750

751

1. **Model Creation**: SAX events are converted to model objects through actions

752

2. **Model Assembly**: Models are arranged in hierarchical structure

753

3. **Model Processing**: Handlers process models to create actual component instances

754

4. **Component Configuration**: Created components are configured and started

755

5. **Dependency Resolution**: Component dependencies are resolved and injected

756

757

This separation enables sophisticated configuration processing, validation, and component lifecycle management while maintaining clean separation between parsing and instantiation concerns.

758

759

## Integration Patterns

760

761

The Model framework integrates with other logback-core components:

762

763

- **Joran Configuration**: Actions create models from XML elements

764

- **Component Factory**: Handlers instantiate and configure components

765

- **Context Management**: Models store component references in context

766

- **Property Substitution**: Variable substitution occurs during model processing

767

- **Conditional Logic**: Models support conditional configuration sections

768

- **Error Handling**: Processing errors are reported through context status system