001/* 002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others 003 * 004 * This program and the accompanying materials are made available under the 005 * terms of the Eclipse Public License 2.0 which is available at 006 * http://www.eclipse.org/legal/epl-2.0. 007 * 008 * SPDX-License-Identifier: EPL-2.0 009 */ 010 011package gololang.ir; 012 013import java.util.LinkedList; 014import java.util.List; 015 016import static java.util.Collections.unmodifiableList; 017 018/** 019 * A {@code case} node. 020 * <p> This node describe tree such as: 021 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 022 * case { 023 * when condition_1 { 024 * action_1 025 * } 026 * when condition_2 { 027 * action_2 028 * } 029 * otherwise { 030 * default_action 031 * } 032 * } 033 * </code></pre> 034 */ 035public final class CaseStatement extends GoloStatement<CaseStatement> implements Alternatives<Block> { 036 037 private Block otherwise; 038 private final LinkedList<WhenClause<Block>> clauses = new LinkedList<>(); 039 040 private CaseStatement() { 041 super(); 042 } 043 044 /** 045 * Creates an empty case switch. 046 */ 047 public static CaseStatement cases() { 048 return new CaseStatement(); 049 } 050 051 protected CaseStatement self() { return this; } 052 053 /** 054 * {@inheritDoc} 055 */ 056 @Override 057 public CaseStatement when(Object cond) { 058 if (cond instanceof WhenClause) { 059 @SuppressWarnings("unchecked") 060 WhenClause<Block> clause = (WhenClause<Block>) cond; 061 this.clauses.add(makeParentOf(clause)); 062 } else { 063 this.clauses.add(makeParentOf(new WhenClause<Block>(ExpressionStatement.of(cond), null))); 064 } 065 return this; 066 } 067 068 /** 069 * {@inheritDoc} 070 * 071 * @param action a {@link gololang.ir.Block} containing the statements to execute. 072 */ 073 @Override 074 public CaseStatement then(Object action) { 075 this.clauses.getLast().then(Block.of(action)); 076 return this; 077 } 078 079 /** 080 * {@inheritDoc} 081 * 082 * @param action a {@link gololang.ir.Block} containing the statements to execute. 083 */ 084 @Override 085 public CaseStatement otherwise(Object action) { 086 this.otherwise = makeParentOf(Block.of(action)); 087 return this; 088 } 089 090 public List<WhenClause<Block>> getClauses() { 091 return unmodifiableList(this.clauses); 092 } 093 094 public Block getOtherwise() { 095 return this.otherwise; 096 } 097 098 /** 099 * {@inheritDoc} 100 */ 101 @Override 102 public void accept(GoloIrVisitor visitor) { 103 visitor.visitCaseStatement(this); 104 } 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override 110 public List<GoloElement<?>> children() { 111 LinkedList<GoloElement<?>> children = new LinkedList<>(clauses); 112 children.add(otherwise); 113 return children; 114 } 115 116 /** 117 * {@inheritDoc} 118 */ 119 @Override 120 public void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 121 if (!(newElement instanceof Block || newElement instanceof WhenClause)) { 122 throw cantConvert("Block or WhenClause", newElement); 123 } 124 if (otherwise.equals(original)) { 125 otherwise(newElement); 126 return; 127 } 128 if (clauses.contains(original)) { 129 @SuppressWarnings("unchecked") 130 WhenClause<Block> when = (WhenClause<Block>) newElement; 131 clauses.set(clauses.indexOf(original), makeParentOf(when)); 132 return; 133 } 134 throw doesNotContain(original); 135 } 136}