| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * 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 com.intellij.patterns; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.util.PairProcessor; |
| import com.intellij.util.ProcessingContext; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Modifier; |
| import java.util.Collection; |
| |
| /** |
| * @author peter |
| */ |
| public abstract class PatternCondition<T> { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.patterns.PatternCondition"); |
| @NonNls private static final String PARAMETER_FIELD_PREFIX = "val$"; |
| private final String myDebugMethodName; |
| |
| public PatternCondition(@Nullable @NonNls String debugMethodName) { |
| myDebugMethodName = debugMethodName; |
| } |
| |
| public String getDebugMethodName() { |
| return myDebugMethodName; |
| } |
| |
| private static void appendValue(final StringBuilder builder, final String indent, final Object obj) { |
| if (obj instanceof ElementPattern) { |
| ((ElementPattern)obj).getCondition().append(builder, indent + " "); |
| } else if (obj instanceof Object[]) { |
| appendArray(builder, indent, (Object[])obj); |
| } else if (obj instanceof Collection) { |
| appendArray(builder, indent, ((Collection) obj).toArray()); |
| } |
| else if (obj instanceof String) { |
| builder.append('\"').append(obj).append('\"'); |
| } |
| else { |
| builder.append(obj); |
| } |
| } |
| |
| protected static void appendArray(final StringBuilder builder, final String indent, final Object[] objects) { |
| builder.append("["); |
| boolean first = true; |
| for (final Object o : objects) { |
| if (!first) { |
| builder.append(", "); |
| } |
| first = false; |
| appendValue(builder, indent, o); |
| } |
| builder.append("]"); |
| } |
| |
| public abstract boolean accepts(@NotNull T t, final ProcessingContext context); |
| |
| @NonNls |
| public String toString() { |
| final StringBuilder builder = new StringBuilder(); |
| append(builder, ""); |
| return builder.toString(); |
| } |
| |
| public void append(StringBuilder builder, String indent) { |
| builder.append(myDebugMethodName); |
| builder.append("("); |
| appendParams(builder, indent); |
| builder.append(")"); |
| } |
| |
| private void appendParams(final StringBuilder builder, final String indent) { |
| processParameters(new PairProcessor<String, Object>() { |
| int count; |
| String prevName; |
| int prevOffset; |
| |
| @Override |
| public boolean process(String name, Object value) { |
| count ++; |
| if (count == 2) builder.insert(prevOffset, prevName +"="); |
| if (count > 1) builder.append(", "); |
| prevOffset = builder.length(); |
| if (count > 1) builder.append(name).append("="); |
| appendValue(builder, indent, value); |
| prevName = name; |
| return true; |
| } |
| }); |
| } |
| |
| // this code eats CPU, for debug purposes ONLY |
| public boolean processParameters(final PairProcessor<String, Object> processor) { |
| for (Class aClass = getClass(); aClass != null; aClass = aClass.getSuperclass()) { |
| for (final Field field : aClass.getDeclaredFields()) { |
| if (!Modifier.isStatic(field.getModifiers()) && |
| (((field.getModifiers() & 0x1000 /*Modifer.SYNTHETIC*/) == 0 && !aClass.equals(PatternCondition.class)) |
| || field.getName().startsWith(PARAMETER_FIELD_PREFIX))) { |
| final String name = field.getName(); |
| final String fixedName = name.startsWith(PARAMETER_FIELD_PREFIX) ? |
| name.substring(PARAMETER_FIELD_PREFIX.length()) : name; |
| final Object value = getFieldValue(field); |
| if (!processor.process(fixedName, value)) return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| private Object getFieldValue(Field field) { |
| final boolean accessible = field.isAccessible(); |
| try { |
| field.setAccessible(true); |
| return field.get(this); |
| } |
| catch (IllegalAccessException e) { |
| LOG.error(e); |
| } |
| finally { |
| field.setAccessible(accessible); |
| } |
| return null; |
| } |
| |
| } |