/* * Copyright 2010 The WicketForge-Team * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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 wicketforge.psi.hierarchy; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiCallExpression; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import wicketforge.Constants; import java.util.HashMap; import java.util.List; import java.util.Map; /** */ public class ClassWicketIdHierarchy { private static final Logger LOG = Logger.getInstance("#wicketforge.psi.hierarchy.ClassWicketIdHierarchy"); private Map<String, ClassWicketIdItem> wicketIdPathMap; @NotNull public static ClassWicketIdHierarchy create(@NotNull PsiClass psiClass) { return new ClassWicketIdHierarchy(psiClass); } private ClassWicketIdHierarchy(@NotNull final PsiClass psiClass) { this.wicketIdPathMap = new HashMap<String, ClassWicketIdItem>(); ClassWicketIdItem root = new ClassWicketIdItem("", null); this.wicketIdPathMap.put("", root); ClassWicketIdReferences classWicketIdReferences = ClassWicketIdReferences.build(psiClass); List<PsiCallExpression> addedComponents = classWicketIdReferences.getAdded(psiClass); if (addedComponents != null) { addRecursive(classWicketIdReferences, new StringBuilder(), root, psiClass, addedComponents, 0); } } private void addRecursive(@NotNull ClassWicketIdReferences classWicketIdReferences, @NotNull StringBuilder path, @NotNull ClassWicketIdItem parent, @NotNull PsiElement parentElement, @Nullable List<PsiCallExpression> addedComponents, int depth) { if (depth++ > 50) { LOG.error("Deep addRecursive", path.toString()); return; } if (addedComponents != null) { for (PsiCallExpression callExpression : addedComponents) { // fix issue 95: add the component to itself (no sense) but crash wicketforge if (callExpression.equals(parentElement)) { continue; } ClassWicketIdNewComponentItem newComponentItem = classWicketIdReferences.getNewComponentItem(callExpression); if (newComponentItem != null && !parent.contains(newComponentItem)) { int length = path.length(); try { path.append(Constants.HIERARCHYSEPARATOR).append(newComponentItem.getWicketId()); ClassWicketIdItem child = findOrCreateChild(path, parent, newComponentItem.getWicketId()); child.getNewComponentItems().add(newComponentItem); addRecursive(classWicketIdReferences, path, child, callExpression, classWicketIdReferences.getAdded(callExpression), depth); } finally { path.setLength(length); } } } } // add also components of superclass (if any... ex: MyPage.java -> inner class MyMarkupContainer -> label myMarkupContainer ) PsiClass superClass = null; if (parentElement instanceof PsiClass) { superClass = ((PsiClass) parentElement).getSuperClass(); } else if (parentElement instanceof PsiCallExpression) { PsiCallExpression callExpression = (PsiCallExpression) parentElement; ClassWicketIdNewComponentItem newComponentItem = classWicketIdReferences.getNewComponentItem(callExpression); if (newComponentItem != null) { superClass = newComponentItem.getBaseClassToCreate(); } } if (superClass != null) { List<PsiCallExpression> superAddedComponents = classWicketIdReferences.getAdded(superClass); if (superAddedComponents != null) { addRecursive(classWicketIdReferences, path, parent, superClass, superAddedComponents, depth); } } } @NotNull private ClassWicketIdItem findOrCreateChild(@NotNull StringBuilder path, @NotNull ClassWicketIdItem parent, @NotNull String wicketId) { ClassWicketIdItem child = parent.findChild(wicketId); if (child == null) { child = new ClassWicketIdItem(wicketId, parent); wicketIdPathMap.put(path.toString(), child); } return child; } @NotNull public Map<String, ClassWicketIdItem> getWicketIdPathMap() { return wicketIdPathMap; } }