or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-interface.mdcollections-utilities.mdcore-runtime.mdindex.mdjson-processing.mdmeta-programming.mdscript-execution.mdsql-database.mdtemplate-processing.mdxml-processing.md

collections-utilities.mddocs/

0

# Collections and Utilities

1

2

Enhanced collection operations, builder patterns, configuration management, and utility classes that extend Java's standard library with Groovy-specific enhancements.

3

4

## Capabilities

5

6

### Dynamic Objects

7

8

Create and manipulate objects dynamically at runtime.

9

10

```groovy { .api }

11

/**

12

* Dynamic object that allows adding properties and methods at runtime

13

*/

14

class Expando extends GroovyObjectSupport {

15

/** Create empty Expando */

16

Expando()

17

18

/** Create Expando with initial properties */

19

Expando(Map properties)

20

21

/** Get property value dynamically */

22

Object getProperty(String name)

23

24

/** Set property value dynamically */

25

void setProperty(String name, Object value)

26

}

27

```

28

29

**Usage Examples:**

30

31

```groovy

32

// Create dynamic object

33

def person = new Expando()

34

person.name = "Alice"

35

person.age = 30

36

person.greet = { "Hello, I'm ${name}" }

37

38

println person.name // "Alice"

39

println person.greet() // "Hello, I'm Alice"

40

41

// Create with initial properties

42

def car = new Expando([

43

make: "Toyota",

44

model: "Camry",

45

year: 2020,

46

start: { "Starting ${make} ${model}" }

47

])

48

49

println car.start() // "Starting Toyota Camry"

50

51

// Add methods dynamically

52

person.celebrate = { years ->

53

age += years

54

return "Now I'm ${age} years old!"

55

}

56

57

println person.celebrate(1) // "Now I'm 31 years old!"

58

```

59

60

### Builder Support

61

62

Base classes for implementing various builder patterns.

63

64

```groovy { .api }

65

/**

66

* Base class for implementing builder patterns

67

*/

68

abstract class BuilderSupport {

69

/** Create node with name only */

70

protected abstract Object createNode(Object name)

71

72

/** Create node with name and value */

73

protected abstract Object createNode(Object name, Object value)

74

75

/** Create node with name and attributes */

76

protected abstract Object createNode(Object name, Map attributes)

77

78

/** Create node with name, attributes, and value */

79

protected abstract Object createNode(Object name, Map attributes, Object value)

80

81

/** Set parent-child relationship */

82

protected void setParent(Object parent, Object child)

83

84

/** Get current node */

85

protected Object getCurrent()

86

87

/** Set current node */

88

protected void setCurrent(Object current)

89

}

90

91

/**

92

* Builder implementation using factory pattern

93

*/

94

class FactoryBuilderSupport extends BuilderSupport {

95

/** Register factory for node type */

96

void registerFactory(String name, Factory factory)

97

98

/** Register factory with alias */

99

void registerFactory(String name, String groupName, Factory factory)

100

101

/** Register bean factory */

102

void registerBeanFactory(String name, Class beanClass)

103

}

104

```

105

106

**Usage Examples:**

107

108

```groovy

109

// Custom builder implementation

110

class TreeBuilder extends BuilderSupport {

111

private Stack nodeStack = new Stack()

112

113

protected Object createNode(Object name) {

114

return createNode(name, null, null)

115

}

116

117

protected Object createNode(Object name, Object value) {

118

return createNode(name, null, value)

119

}

120

121

protected Object createNode(Object name, Map attributes) {

122

return createNode(name, attributes, null)

123

}

124

125

protected Object createNode(Object name, Map attributes, Object value) {

126

def node = [name: name, attributes: attributes ?: [:], value: value, children: []]

127

128

if (!nodeStack.empty()) {

129

nodeStack.peek().children << node

130

}

131

132

return node

133

}

134

135

protected void setParent(Object parent, Object child) {

136

// Handled in createNode

137

}

138

}

139

140

// Using the custom builder

141

def builder = new TreeBuilder()

142

def tree = builder.root {

143

branch(type: 'main') {

144

leaf('Leaf 1')

145

leaf('Leaf 2', color: 'green')

146

}

147

branch(type: 'secondary') {

148

leaf('Leaf 3')

149

}

150

}

151

```

152

153

### Node Processing

154

155

Tree structure representation and manipulation for XML-like data.

156

157

```groovy { .api }

158

/**

159

* Represents a node in a tree structure (used by XML processing)

160

*/

161

class Node {

162

/** Create node with name */

163

Node(Object name)

164

165

/** Create node with name and value */

166

Node(Object name, Object value)

167

168

/** Create node with name and attributes */

169

Node(Object name, Map attributes)

170

171

/** Create node with parent, name, and value */

172

Node(Node parent, Object name, Object value)

173

174

/** Get node name */

175

Object name()

176

177

/** Get node value */

178

Object value()

179

180

/** Set node value */

181

void setValue(Object value)

182

183

/** Get node attributes */

184

Map attributes()

185

186

/** Get child nodes */

187

List children()

188

189

/** Get parent node */

190

Node parent()

191

192

/** Append child node with name */

193

Node appendNode(Object name)

194

195

/** Append child node with name and value */

196

Node appendNode(Object name, Object value)

197

198

/** Append child node with name and attributes */

199

Node appendNode(Object name, Map attributes)

200

201

/** Remove child node */

202

boolean remove(Node child)

203

204

/** Get attribute value */

205

Object attribute(Object key)

206

207

/** Get text content */

208

String text()

209

210

/** Find all nodes matching closure */

211

List findAll(Closure closure)

212

213

/** Find first node matching closure */

214

Node find(Closure closure)

215

}

216

217

/**

218

* List of Node objects with additional query capabilities

219

*/

220

class NodeList extends ArrayList<Node> {

221

/** Get nodes by name */

222

NodeList getAt(String name)

223

224

/** Get text content of all nodes */

225

String text()

226

227

/** Find all nodes matching closure */

228

NodeList findAll(Closure closure)

229

230

/** Get attribute values */

231

List getAttribute(String name)

232

}

233

```

234

235

### Configuration Management

236

237

Hierarchical configuration objects with nested property support.

238

239

```groovy { .api }

240

/**

241

* Configuration object supporting hierarchical properties

242

*/

243

class ConfigObject implements Map<String, Object> {

244

/** Create empty ConfigObject */

245

ConfigObject()

246

247

/** Check if config is empty */

248

boolean isEmpty()

249

250

/** Get property using dot notation */

251

Object getProperty(String name)

252

253

/** Set property using dot notation */

254

void setProperty(String name, Object value)

255

256

/** Merge with another ConfigObject */

257

ConfigObject merge(ConfigObject other)

258

259

/** Convert to Properties */

260

Properties toProperties()

261

262

/** Convert to Properties with prefix */

263

Properties toProperties(String prefix)

264

265

/** Flatten to Map */

266

Map flatten()

267

268

/** Flatten with custom separator */

269

Map flatten(String separator)

270

}

271

```

272

273

**Usage Examples:**

274

275

```groovy

276

// Create configuration

277

def config = new ConfigObject()

278

config.database.url = "jdbc:mysql://localhost:3306/mydb"

279

config.database.username = "user"

280

config.database.password = "pass"

281

config.server.port = 8080

282

config.server.host = "localhost"

283

284

// Access nested properties

285

println config.database.url // "jdbc:mysql://localhost:3306/mydb"

286

println config.server.port // 8080

287

288

// Map-style access

289

println config['database']['username'] // "user"

290

291

// Convert to Properties

292

def props = config.toProperties()

293

props.each { key, value ->

294

println "$key = $value"

295

}

296

297

// Merge configurations

298

def defaultConfig = new ConfigObject()

299

defaultConfig.server.timeout = 30

300

defaultConfig.server.retries = 3

301

302

def finalConfig = defaultConfig.merge(config)

303

println finalConfig.server.timeout // 30

304

println finalConfig.server.port // 8080

305

```

306

307

### Observable Collections

308

309

Collections that fire events when modified.

310

311

```groovy { .api }

312

/**

313

* List implementation that fires events on changes

314

*/

315

class ObservableList<E> extends ArrayList<E> {

316

/** Add property change listener */

317

void addPropertyChangeListener(PropertyChangeListener listener)

318

319

/** Remove property change listener */

320

void removePropertyChangeListener(PropertyChangeListener listener)

321

322

/** Add property change listener for specific property */

323

void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)

324

325

/** Remove property change listener for specific property */

326

void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)

327

328

/** Get all property change listeners */

329

PropertyChangeListener[] getPropertyChangeListeners()

330

331

/** Fire property change event */

332

protected void firePropertyChange(String propertyName, Object oldValue, Object newValue)

333

}

334

335

/**

336

* Map implementation that fires events on changes

337

*/

338

class ObservableMap<K, V> extends HashMap<K, V> {

339

/** Add property change listener */

340

void addPropertyChangeListener(PropertyChangeListener listener)

341

342

/** Remove property change listener */

343

void removePropertyChangeListener(PropertyChangeListener listener)

344

345

/** Add property change listener for specific property */

346

void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)

347

348

/** Get all property change listeners */

349

PropertyChangeListener[] getPropertyChangeListeners()

350

}

351

352

/**

353

* Set implementation that fires events on changes

354

*/

355

class ObservableSet<E> extends HashSet<E> {

356

/** Add property change listener */

357

void addPropertyChangeListener(PropertyChangeListener listener)

358

359

/** Remove property change listener */

360

void removePropertyChangeListener(PropertyChangeListener listener)

361

362

/** Get all property change listeners */

363

PropertyChangeListener[] getPropertyChangeListeners()

364

}

365

```

366

367

**Usage Examples:**

368

369

```groovy

370

import java.beans.PropertyChangeListener

371

372

// Observable list

373

def list = new ObservableList()

374

list.addPropertyChangeListener { event ->

375

println "List changed: ${event.propertyName} from ${event.oldValue} to ${event.newValue}"

376

}

377

378

list.add("item1") // Fires event

379

list.add("item2") // Fires event

380

list.remove("item1") // Fires event

381

382

// Observable map

383

def map = new ObservableMap()

384

map.addPropertyChangeListener("key1") { event ->

385

println "Key1 changed from ${event.oldValue} to ${event.newValue}"

386

}

387

388

map.put("key1", "value1") // Fires event for key1

389

map.put("key2", "value2") // No event (no listener for key2)

390

map.put("key1", "newvalue") // Fires event for key1

391

```

392

393

### Utility Classes

394

395

Various utility classes for common operations.

396

397

```groovy { .api }

398

/**

399

* PrintWriter that automatically handles indentation

400

*/

401

class IndentPrinter extends PrintWriter {

402

/** Create with Writer and indent string */

403

IndentPrinter(Writer writer, String indent)

404

405

/** Create with Writer, default indent */

406

IndentPrinter(Writer writer)

407

408

/** Increment indent level */

409

void incrementIndent()

410

411

/** Decrement indent level */

412

void decrementIndent()

413

414

/** Print current indentation */

415

void printIndent()

416

417

/** Set auto-indent mode */

418

void setAutoIndent(boolean autoIndent)

419

420

/** Get current indent level */

421

int getIndentLevel()

422

423

/** Set indent level */

424

void setIndentLevel(int indentLevel)

425

}

426

427

/**

428

* Comparator implementation using closures

429

*/

430

class ClosureComparator<T> implements Comparator<T> {

431

/** Create with comparison closure */

432

ClosureComparator(Closure closure)

433

434

/** Compare two objects using closure */

435

int compare(T o1, T o2)

436

}

437

438

/**

439

* Utility for working with Groovy collections

440

*/

441

class GroovyCollections {

442

/** Get combinations of collections */

443

static <T> List<List<T>> combinations(Collection<Collection<T>> collections)

444

445

/** Transpose lists (matrix transpose) */

446

static List transpose(List lists)

447

448

/** Get subsequences of a list */

449

static <T> List<List<T>> subsequences(List<T> items)

450

451

/** Permutations of a collection */

452

static <T> List<List<T>> combinations(List<T> items, int length)

453

}

454

```

455

456

**Usage Examples:**

457

458

```groovy

459

// IndentPrinter

460

def writer = new StringWriter()

461

def printer = new IndentPrinter(writer, " ")

462

463

printer.println("Level 0")

464

printer.incrementIndent()

465

printer.println("Level 1")

466

printer.incrementIndent()

467

printer.println("Level 2")

468

printer.decrementIndent()

469

printer.println("Back to Level 1")

470

471

println writer.toString()

472

473

// ClosureComparator

474

def people = [

475

[name: "Alice", age: 30],

476

[name: "Bob", age: 25],

477

[name: "Charlie", age: 35]

478

]

479

480

// Sort by age

481

def ageComparator = new ClosureComparator { a, b -> a.age <=> b.age }

482

people.sort(ageComparator)

483

484

// Sort by name length

485

def nameComparator = new ClosureComparator { a, b -> a.name.length() <=> b.name.length() }

486

people.sort(nameComparator)

487

488

// GroovyCollections

489

def colors = ["red", "blue"]

490

def sizes = ["small", "large"]

491

def materials = ["cotton", "silk"]

492

493

def combinations = GroovyCollections.combinations([colors, sizes, materials])

494

combinations.each { combo ->

495

println combo.join(" ")

496

}

497

// Output: red small cotton, red small silk, red large cotton, etc.

498

499

def matrix = [[1, 2, 3], [4, 5, 6]]

500

def transposed = GroovyCollections.transpose(matrix)

501

println transposed // [[1, 4], [2, 5], [3, 6]]

502

```