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 
17 package com.google.streamhtmlparser.impl;
18 
19 import com.google.common.base.Preconditions;
20 
21 import 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  */
39 class 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    */
InternalState(String name, int id)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    */
InternalState()68   private InternalState() {
69     name = "InternalStateError";
70     id = 0;
71   }
72 
73   /**
74    * @return {@code String} name of that state.
75    */
getName()76   public String getName() {
77     return name;
78   }
79 
80   /**
81    * @return {@code int} id of that state.
82    */
getId()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
toString()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    */
getInstanceHtml(String name)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    */
getInstanceJavascript(String name)113   static InternalState getInstanceJavascript(String name) {
114     int javascriptStateId = javascriptStates.getAndIncrement();
115     return new InternalState(name, javascriptStateId);
116   }
117 }
118