blob: 83f6879b595ad834f46f9c8fc4fc1ad953dfb9c9 [file] [log] [blame]
/*
* Copyright (c) 2011 Google Inc.
*
* All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
* Public License v1.0 which accompanies this distribution, and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.google.eclipse.protobuf.model.util;
import static java.util.Collections.unmodifiableList;
import static org.eclipse.xtext.util.Strings.isEmpty;
import java.util.List;
import com.google.eclipse.protobuf.naming.NameResolver;
import com.google.eclipse.protobuf.protobuf.AbstractCustomOption;
import com.google.eclipse.protobuf.protobuf.AbstractOption;
import com.google.eclipse.protobuf.protobuf.DefaultValueFieldOption;
import com.google.eclipse.protobuf.protobuf.FieldOption;
import com.google.eclipse.protobuf.protobuf.Group;
import com.google.eclipse.protobuf.protobuf.IndexedElement;
import com.google.eclipse.protobuf.protobuf.MessageField;
import com.google.eclipse.protobuf.protobuf.NativeFieldOption;
import com.google.eclipse.protobuf.protobuf.NativeOption;
import com.google.eclipse.protobuf.protobuf.Option;
import com.google.eclipse.protobuf.protobuf.OptionField;
import com.google.eclipse.protobuf.protobuf.OptionSource;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* Utility methods related to <code>{@link Option}</code>s.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@Singleton public class Options {
@Inject private ModelObjects modelObjects;
@Inject private NameResolver nameResolver;
@Inject private OptionFields optionFields;
public boolean isNative(AbstractOption option) {
return option instanceof NativeOption || option instanceof NativeFieldOption;
}
@SuppressWarnings("unchecked")
public List<OptionField> fieldsOf(AbstractCustomOption option) {
List<OptionField> fields = modelObjects.valueOfFeature(option, "fields", List.class);
return unmodifiableList(fields);
}
/**
* Indicates whether the given option is the "default value" one.
* @param option the given option to check.
* @return {@code true} if the given option is the "default value" one, {@code false} otherwise.
*/
public boolean isDefaultValueOption(FieldOption option) {
return option instanceof DefaultValueFieldOption && option.eContainer() instanceof MessageField;
}
/**
* Returns the <code>{@link IndexedElement}</code> the given custom option is referring to. This method will check
* first the source of the last field of the given option (if any.) If the option does not have any fields, this
* method will return the root source of the option.
* <p>
* Example #1
*
* <pre>
* option(myOption) = true;
* </pre>
*
* this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
* </p>
* <p>
* Example #2
*
* <pre>
* option(myOption).foo = true;
* </pre>
*
* this method will return the <code>{@link IndexedElement}</code> "foo" is pointing to.
* </p>
* @param option the given custom option.
* @return the {@code IndexedElement} the given custom option is referring to, or {@code null} if it cannot be
* found.
*/
public IndexedElement sourceOf(AbstractCustomOption option) {
IndexedElement e = sourceOfLastFieldIn(option);
if (e == null) {
e = rootSourceOf((AbstractOption) option);
}
return e;
}
/**
* Returns the last field of the given custom option. In the following example
*
* <pre>
* option(myOption).foo = true;
* </pre>
*
* this method will return the field that "foo" is pointing to.
* @param option the given custom option.
* @return the last field of the given custom option is referring to, or {@code null} if one cannot be found.
*/
@SuppressWarnings("unchecked")
public IndexedElement sourceOfLastFieldIn(AbstractCustomOption option) {
List<OptionField> fields = modelObjects.valueOfFeature(option, "fields", List.class);
if (fields == null || fields.isEmpty()) {
return null;
}
OptionField last = fields.get(fields.size() - 1);
return optionFields.sourceOf(last);
}
/**
* Returns the <code>{@link IndexedElement}</code> the given option is referring to. In the following example
*
* <pre>
* option(myOption).foo = true;
* </pre>
*
* this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
* @param option the given option.
* @return the {@code Property} the given option is referring to, or {@code null} if it cannot be found.
*/
public IndexedElement rootSourceOf(AbstractOption option) {
OptionSource source = modelObjects.valueOfFeature(option, "source", OptionSource.class);
return source == null ? null : source.getTarget();
}
/**
* Returns the name of the given <code>{@link IndexedElement}</code> that is being used as a source of an option. If
* the given element is a <code>{@link Group}</code>, this method will return its name in lower case.
* @param optionSource the given {@code IndexedElement} that is being used as a source of an option.
* @return the name of the given {@code IndexedElement}.
*/
public String nameForOption(IndexedElement optionSource) {
String name = nameResolver.nameOf(optionSource);
if (optionSource instanceof Group && !isEmpty(name)) {
name = name.toLowerCase();
}
return name;
}
/**
* Returns the name of the given option.
* @param option the given option.
* @return the name of the given option.
*/
public String nameOf(FieldOption option) {
IndexedElement e = rootSourceOf(option);
if (e instanceof MessageField) {
return ((MessageField) e).getName();
}
return null;
}
}