/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.internal.element; import com.google.dart.engine.element.Element; import com.google.dart.engine.element.ElementLocation; import java.util.ArrayList; /** * Instances of the class {@code ElementLocationImpl} implement an {@link ElementLocation}. * * @coverage dart.engine.element */ public class ElementLocationImpl implements ElementLocation { /** * The path to the element whose location is represented by this object. */ private String[] components; /** * The character used to separate components in the encoded form. */ private static final char SEPARATOR_CHAR = ';'; /** * Initialize a newly created location to represent the given element. * * @param element the element whose location is being represented */ public ElementLocationImpl(Element element) { ArrayList<String> components = new ArrayList<String>(); Element ancestor = element; while (ancestor != null) { components.add(0, ((ElementImpl) ancestor).getIdentifier()); ancestor = ancestor.getEnclosingElement(); } this.components = components.toArray(new String[components.size()]); } /** * Initialize a newly created location from the given encoded form. * * @param encoding the encoded form of a location */ public ElementLocationImpl(String encoding) { this.components = decode(encoding); } /** * Initialize a newly created location from the given components. * * @param components the components of a location */ public ElementLocationImpl(String[] components) { this.components = components; } @Override public boolean equals(Object object) { if (this == object) { return true; } if (!(object instanceof ElementLocationImpl)) { return false; } ElementLocationImpl location = (ElementLocationImpl) object; String[] otherComponents = location.components; int length = components.length; if (otherComponents.length != length) { return false; } for (int i = 0; i < length; i++) { if (!components[i].equals(otherComponents[i])) { return false; } } return true; } @Override public String[] getComponents() { return components; } @Override public String getEncoding() { StringBuilder builder = new StringBuilder(); int length = components.length; for (int i = 0; i < length; i++) { if (i > 0) { builder.append(SEPARATOR_CHAR); } encode(builder, components[i]); } return builder.toString(); } @Override public int hashCode() { int result = 1; for (int i = 0; i < components.length; i++) { String component = components[i]; result = 31 * result + component.hashCode(); } return result; } @Override public String toString() { return getEncoding(); } /** * Decode the encoded form of a location into an array of components. * * @param encoding the encoded form of a location * @return the components that were encoded */ private String[] decode(String encoding) { ArrayList<String> components = new ArrayList<String>(); StringBuilder builder = new StringBuilder(); int index = 0; int length = encoding.length(); while (index < length) { char currentChar = encoding.charAt(index); if (currentChar == SEPARATOR_CHAR) { if (index + 1 < length && encoding.charAt(index + 1) == SEPARATOR_CHAR) { builder.append(SEPARATOR_CHAR); index += 2; } else { components.add(builder.toString()); builder.setLength(0); index++; } } else { builder.append(currentChar); index++; } } components.add(builder.toString()); return components.toArray(new String[components.size()]); } /** * Append an encoded form of the given component to the given builder. * * @param builder the builder to which the encoded component is to be appended * @param component the component to be appended to the builder */ private void encode(StringBuilder builder, String component) { int length = component.length(); for (int i = 0; i < length; i++) { char currentChar = component.charAt(i); if (currentChar == SEPARATOR_CHAR) { builder.append(SEPARATOR_CHAR); } builder.append(currentChar); } } }