1/*
2 * Copyright (C) 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.streamhtmlparser.impl;
18
19import com.google.common.base.Preconditions;
20
21import java.util.concurrent.atomic.AtomicInteger;
22
23/**
24 * A very simple representation of the parser internal state. The state
25 * contains a small integer identifier (from 1 to 255) to allow for
26 * the implementation of a simple finite state machine. The name is
27 * purely informational.
28 *
29 * <p>In order to eliminate the possibility that different states have
30 * the same identifier, this class manages the idenitifiers themselves.
31 * The HTML and Javascript parser states are managed elsewhere in different
32 * "namespaces" hence will not clash and there is no current need for this
33 * class to disambiguate them further.
34 *
35 * <p>The methods to create new <code>InternalState</code> instances are
36 * package-scope only as they are only needed by <code>HtmlParserImpl</code>
37 * and <code>JavascriptParserImpl</code>.
38 */
39class InternalState {
40
41  // An InternalState to represent an error condition for all parsers.
42  static final InternalState INTERNAL_ERROR_STATE = new InternalState();
43
44  // MAX_ID and FIRST_ID are only used for asserts against developer error.
45  private static final int MAX_ID = 255;
46  private static final int FIRST_ID = 1;
47
48  private static AtomicInteger htmlStates = new AtomicInteger(FIRST_ID);
49  private static AtomicInteger javascriptStates = new AtomicInteger(FIRST_ID);
50  private final String name;
51  private final int id;
52
53  /**
54   * @param name the {@code String} identifier for this state
55   * @param id the integer identiifer for this state, guaranteed to be unique
56   */
57  private InternalState(String name, int id) {
58    Preconditions.checkNotNull(name);
59    Preconditions.checkArgument(id >= FIRST_ID);
60    Preconditions.checkArgument(id <= MAX_ID);
61    this.name = name;
62    this.id = id;
63  }
64
65  /**
66   * Used only for the error state. Bypasses assert checks.
67   */
68  private InternalState() {
69    name = "InternalStateError";
70    id = 0;
71  }
72
73  /**
74   * @return {@code String} name of that state.
75   */
76  public String getName() {
77    return name;
78  }
79
80  /**
81   * @return {@code int} id of that state.
82   */
83  public int getId() {
84    return id;
85  }
86
87  /**
88   * @return {@code String} representation of that object, the format
89   *         may change.
90   */
91  @Override
92  public String toString() {
93    return String.format("InternalState: Name: %s; Id: %d", name, id);
94  }
95
96  /**
97   * Obtain a new {@code InternalState} instance for the HTML parser.
98   *
99   * @param name a unique identifier for this state useful during debugging
100   * @return a new {@code InternalState} object
101   */
102  static InternalState getInstanceHtml(String name) {
103    int htmlStateId = htmlStates.getAndIncrement();
104    return new InternalState(name, htmlStateId);
105  }
106
107  /**
108   * Obtain a new <code>InternalState</code> instance for the Javascript parser.
109   *
110   * @param name A unique identifier for this state useful during debugging
111   * @return a new {@code InternalState} object
112   */
113  static InternalState getInstanceJavascript(String name) {
114    int javascriptStateId = javascriptStates.getAndIncrement();
115    return new InternalState(name, javascriptStateId);
116  }
117}
118