org.netbeans.modules.android.grammars.AndroidGrammar.java Source code

Java tutorial

Introduction

Here is the source code for org.netbeans.modules.android.grammars.AndroidGrammar.java

Source

/*
 * 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 org.netbeans.modules.android.grammars;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.android.core.sdk.DalvikPlatform;
import org.netbeans.modules.xml.api.model.GrammarQuery;
import org.netbeans.modules.xml.api.model.GrammarResult;
import org.netbeans.modules.xml.api.model.HintContext;
import org.openide.util.Enumerations;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Shared code for query implementation user for android XML files.
 *
 * @author Radim Kubacki
 */
abstract class AndroidGrammar implements GrammarQuery {

    private static final Logger LOG = Logger.getLogger(AndroidGrammar.class.getName());

    protected final DalvikPlatform platform;

    protected final StyleableModel model;
    private final ReferenceResolver refResolver;

    public AndroidGrammar(DalvikPlatform platform, StyleableModel model, ReferenceResolver refResolver) {
        this.platform = Preconditions.checkNotNull(platform);
        this.model = Preconditions.checkNotNull(model);
        this.refResolver = Preconditions.checkNotNull(refResolver);
    }

    @VisibleForTesting
    StyleableModel getStyleableModel() {
        return model;
    }

    /**
     * Allow to get names of <b>parsed general entities</b>.
     * @return list of <code>CompletionResult</code>s (ENTITY_REFERENCE_NODEs)
     */
    @Override
    public final Enumeration<GrammarResult> queryEntities(String prefix) {
        List<GrammarResult> list = new ArrayList<GrammarResult>();

        // XXX(radim): add well-know build-in entity names, can we do better?

        if ("lt".startsWith(prefix)) {
            list.add(new SimpleEntityReference("lt"));
        }
        if ("gt".startsWith(prefix)) {
            list.add(new SimpleEntityReference("gt"));
        }
        if ("apos".startsWith(prefix)) {
            list.add(new SimpleEntityReference("apos"));
        }
        if ("quot".startsWith(prefix)) {
            list.add(new SimpleEntityReference("quot"));
        }
        if ("amp".startsWith(prefix)) {
            list.add(new SimpleEntityReference("amp"));
        }

        LOG.log(Level.FINE, "queryEntities({0}) -> {1}", new Object[] { prefix, list });
        return Collections.enumeration(list);
    }

    @Override
    public Enumeration<GrammarResult> queryAttributes(HintContext ctx) {
        LOG.log(Level.FINE, "queryAttributes({0})", ctx.getCurrentPrefix());

        Element ownerElement = null;
        // Support both versions of GrammarQuery contract
        if (ctx.getNodeType() == Node.ATTRIBUTE_NODE) {
            ownerElement = ((Attr) ctx).getOwnerElement();
        } else if (ctx.getNodeType() == Node.ELEMENT_NODE) {
            ownerElement = (Element) ctx;
        }
        if (ownerElement == null) {
            return Enumerations.empty();
        }

        String prefix = ctx.getCurrentPrefix();
        return doQueryAttributes(ownerElement, prefix);
    }

    protected abstract Enumeration<GrammarResult> doQueryAttributes(Element ownerElement, String prefix);

    @Override
    public final Enumeration<GrammarResult> queryNotations(String prefix) {
        LOG.log(Level.FINE, "queryNotatios({0})", prefix);
        return Enumerations.empty();
    }

    // it is not yet implemented
    @Override
    public final boolean isAllowed(Enumeration<GrammarResult> en) {
        return true;
    }

    // customizers section ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override
    public final java.awt.Component getCustomizer(HintContext ctx) {
        return null;
    }

    @Override
    public final boolean hasCustomizer(HintContext ctx) {
        return false;
    }

    @Override
    public final org.openide.nodes.Node.Property[] getProperties(HintContext ctx) {
        return null;
    }

    private static Predicate<String> startsWithPredicate(final String prefix) {
        return new Predicate<String>() {
            @Override
            public boolean apply(String input) {
                return input.startsWith(prefix);
            }

        };
    }

    protected Iterable<String> getChoices(AttributeInfo attr, final String prefix) {
        Iterable<String> values = Collections.emptySet();
        if (Iterables.contains(attr.getFormats(), AttributeInfo.Format.BOOLEAN)) {
            values = Iterables.concat(values, Lists.newArrayList("true", "false"));
        }
        if (Iterables.contains(attr.getFormats(), AttributeInfo.Format.ENUM)) {
            values = Iterables.concat(values, Iterables.filter(attr.getEnumValues(), startsWithPredicate(prefix)));
        }
        if (Iterables.contains(attr.getFormats(), AttributeInfo.Format.DIMENSION)) {
            int i = 0;
            while (i < prefix.length() && Character.isDigit(prefix.charAt(i))) {
                i++;
            }
            if (i > 0) {
                List<String> dimensions = Lists.newArrayList();
                String number = prefix.substring(0, i);
                String unitPrefix = i < prefix.length() ? prefix.substring(i) : "";
                for (String unit : new String[] { "dp", "sp", "pt", "mm", "in", "px" }) {
                    if (unit.startsWith(unitPrefix)) {
                        dimensions.add(number + unit);
                    }
                }
                values = Iterables.concat(values, dimensions);
            }
        }
        if (Iterables.contains(attr.getFormats(), AttributeInfo.Format.REFERENCE)) {
            Iterable<String> offeredValues = Collections.emptyList();
            if (prefix.startsWith("@") && prefix.indexOf('/') > 0) {
                offeredValues = Iterables
                        .transform(Iterables.filter(refResolver.getReferences(), new Predicate<ResourceRef>() {
                            @Override
                            public boolean apply(ResourceRef input) {
                                if (input.toString().startsWith(prefix)) {
                                    return true;
                                }
                                return false;
                            }
                        }), Functions.toStringFunction());
            } else if (prefix.startsWith("@")) {
                final String valuePrefix = prefix.startsWith("@+") ? "@+" : "@";
                offeredValues = Sets.newTreeSet(Iterables
                        .transform(Iterables.filter(refResolver.getReferences(), new Predicate<ResourceRef>() {
                            @Override
                            public boolean apply(ResourceRef input) {
                                if ((valuePrefix + input.resourceType).startsWith(prefix)) {
                                    return true;
                                }
                                return false;
                            }
                        }), new Function<ResourceRef, String>() {
                            @Override
                            public String apply(ResourceRef input) {
                                return valuePrefix + input.resourceType + "/";
                            }
                        }));
            }
            values = Iterables.concat(values, offeredValues);
        }
        return Iterables.filter(values, startsWithPredicate(prefix));
    }
}