1/*
2 * Copyright (C) 2015 The Android Open Source Project
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 */
16package com.google.currysrc.api.process.ast;
17
18import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
19import org.eclipse.jdt.core.dom.BodyDeclaration;
20import org.eclipse.jdt.core.dom.CompilationUnit;
21import org.eclipse.jdt.core.dom.FieldDeclaration;
22import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
23
24import java.util.ArrayList;
25import java.util.List;
26
27/**
28 * Locates the {@link org.eclipse.jdt.core.dom.BodyDeclaration} associated with an field
29 * declaration.
30 */
31public final class FieldLocator implements BodyDeclarationLocator {
32
33  static final String LOCATOR_TYPE_NAME = "field";
34
35  private final TypeLocator typeLocator;
36
37  private final String fieldName;
38
39  public FieldLocator(String packageName, String typeName, String fieldName) {
40    this(new TypeLocator(packageName, typeName), fieldName);
41  }
42
43  public FieldLocator(TypeLocator typeLocator, String fieldName) {
44    this.typeLocator = typeLocator;
45    this.fieldName = fieldName;
46  }
47
48  @Override public TypeLocator getTypeLocator() {
49    return typeLocator;
50  }
51
52  @Override
53  public boolean matches(BodyDeclaration node) {
54    if (node instanceof FieldDeclaration) {
55      FieldDeclaration fieldDeclaration = (FieldDeclaration) node;
56      for (VariableDeclarationFragment variableDeclarationFragment
57          : (List<VariableDeclarationFragment>) fieldDeclaration.fragments()) {
58        String nodeFieldName = variableDeclarationFragment.getName().getFullyQualifiedName();
59        if (nodeFieldName.equals(fieldName)) {
60          BodyDeclaration parentNode = (BodyDeclaration) node.getParent();
61          return typeLocator.matches(parentNode);
62        }
63      }
64    }
65    return false;
66  }
67
68  @Override
69  public FieldDeclaration find(CompilationUnit cu) {
70    AbstractTypeDeclaration typeDeclaration = typeLocator.find(cu);
71    if (typeDeclaration == null) {
72      return null;
73    }
74    for (BodyDeclaration bodyDeclaration
75        : (List<BodyDeclaration>) typeDeclaration.bodyDeclarations()) {
76      if (bodyDeclaration instanceof FieldDeclaration) {
77        FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclaration;
78        for (VariableDeclarationFragment variableDeclarationFragment
79            : (List<VariableDeclarationFragment>) fieldDeclaration.fragments()) {
80          String nodeFieldName = variableDeclarationFragment.getName().getFullyQualifiedName();
81          if (nodeFieldName.equals(fieldName)) {
82            return fieldDeclaration;
83          }
84        }
85      }
86    }
87    return null;
88  }
89
90  @Override public String getStringFormType() {
91    return LOCATOR_TYPE_NAME;
92  }
93
94  @Override public String getStringFormTarget() {
95    return typeLocator.getStringFormTarget() + "#" + fieldName;
96  }
97
98  /**
99   * Returns the names of the fields declared in the supplied {@code fieldDeclarationNode}.
100   */
101  public static List<String> getFieldNames(FieldDeclaration fieldDeclarationNode) {
102    List<VariableDeclarationFragment> fieldDeclarations = fieldDeclarationNode.fragments();
103    List<String> fieldNames = new ArrayList<>(fieldDeclarations.size());
104    for (VariableDeclarationFragment fieldDeclaration : fieldDeclarations) {
105      fieldNames.add(fieldDeclaration.getName().getIdentifier());
106    }
107    return fieldNames;
108  }
109
110  @Override
111  public String toString() {
112    return "FieldLocator{" +
113        "typeLocator=" + typeLocator +
114        ", fieldName='" + fieldName + '\'' +
115        '}';
116  }
117}
118