001package ball.game.crossword;
002/*-
003 * ##########################################################################
004 * Game Applications and Utilities
005 * $Id: Cell.java 5285 2020-02-05 04:23:21Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-game/trunk/src/main/java/ball/game/crossword/Cell.java $
007 * %%
008 * Copyright (C) 2010 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import java.util.List;
024import java.util.stream.Collectors;
025
026import static java.lang.Character.isDigit;
027import static java.lang.Character.isLetter;
028import static java.lang.Character.isLowerCase;
029import static java.lang.Character.toLowerCase;
030import static java.lang.Character.toUpperCase;
031
032/**
033 * Crossword {@link Puzzle} {@link Cell}.
034 *
035 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
036 * @version $Revision: 5285 $
037 */
038public class Cell implements Cloneable {
039    private static final Block BLOCK = new Block();
040
041    private final Boolean special;
042    private Character solution = null;
043
044    private Cell(boolean special) { this.special = special; }
045
046    private Cell(boolean special, Character solution) {
047        this(special);
048
049        setSolution(solution);
050    }
051
052    public boolean isBlock() { return false; }
053
054    public boolean isSpecial() { return special; }
055
056    public boolean isSolved() { return solution != null; }
057
058    public Character getSolution() { return solution; }
059    public void setSolution(Character solution) { this.solution = solution; }
060
061    @Override
062    public Cell clone() throws CloneNotSupportedException {
063        return (Cell) super.clone();
064    }
065
066    @Override
067    public String toString() {
068        char representation = '.';
069
070        if (isSolved()) {
071            representation = getSolution();
072
073            if (isSpecial()) {
074                representation = toLowerCase(representation);
075            } else {
076                representation = toUpperCase(representation);
077            }
078        }
079
080        return String.valueOf(representation);
081    }
082
083    /**
084     * Factory method to produce a {@link Cell}.
085     *
086     * @param   character       The {@code char} representing the
087     *                          {@link Cell}.
088     *
089     * @return  The new {@link Cell}.
090     */
091    public static Cell getInstance(char character) {
092        Cell cell = null;
093
094        switch (character) {
095        case '.':
096            cell = new Cell(false);
097            break;
098
099        case '#':
100            cell = BLOCK;
101            break;
102
103        default:
104            if (isLetter(character)) {
105                cell =
106                    new Cell(isLowerCase(character), toUpperCase(character));
107            } else if (isDigit(character)) {
108                cell = new Cell(false, character);
109            } else {
110                throw new IllegalArgumentException(String.valueOf(character));
111            }
112            break;
113        }
114
115        return cell;
116    }
117
118    public static List<Cell> getRowFrom(String line) {
119        return (line.chars()
120                .mapToObj(c -> getInstance((char) c))
121                .collect(Collectors.toList()));
122    }
123
124    private static class Block extends Cell {
125        private Block() { super(false); }
126
127        @Override
128        public boolean isBlock() { return true; }
129
130        @Override
131        public boolean isSolved() { return true; }
132
133        @Override
134        public void setSolution(Character solution) {
135            throw new IllegalStateException();
136        }
137
138        @Override
139        public String toString() { return "#"; }
140    }
141}