/*
* Copyright 2016 ArcBees Inc.
*
* 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.gwtplatform.mvp.processors.bundle;
import java.util.Collection;
import java.util.Collections;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleAnnotationValueVisitor7;
import com.google.common.base.CaseFormat;
import com.gwtplatform.mvp.client.annotations.ProxyCodeSplitBundle.NoOpProviderBundle;
import com.gwtplatform.processors.tools.domain.HasImports;
import com.gwtplatform.processors.tools.domain.Type;
import com.gwtplatform.processors.tools.logger.Logger;
import com.gwtplatform.processors.tools.utils.Utils;
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.MoreTypes.asTypeElement;
public class BundleDetails implements HasImports {
private static final String BUNDLE_NAME = "GeneratedBundle";
private final Logger logger;
private final Utils utils;
private final Type targetType;
private final TypeElement proxyElement;
private final AnnotationMirror codeSplitBundleMirror;
private boolean initialized;
private boolean valid = true;
private String bundleName;
private Type bundleType;
private int id;
public BundleDetails(
Logger logger,
Utils utils,
Type targetType,
TypeElement proxyElement,
AnnotationMirror codeSplitBundleMirror) {
this.logger = logger;
this.utils = utils;
this.targetType = targetType;
this.proxyElement = proxyElement;
this.codeSplitBundleMirror = codeSplitBundleMirror;
}
public boolean isManualBundle() {
initialize();
return valid && bundleName.isEmpty();
}
public boolean isValid() {
initialize();
return valid;
}
public Type getTargetType() {
return targetType;
}
public String getBundleName() {
return bundleName;
}
public int getId() {
initialize();
return id;
}
public Type getBundleType() {
initialize();
return bundleType;
}
private void initialize() {
if (initialized) {
return;
}
initialized = true;
bundleName = extractBundleValue();
bundleType = extractBundleClass();
id = extractBundleId();
validateBundleConfiguration();
if (valid && !bundleName.isEmpty()) {
bundleType = new Type(
utils.getSourceFilter().getApplicationPackage(),
BUNDLE_NAME + "$$" + bundleName);
}
}
private String extractBundleValue() {
return getAnnotationValue(codeSplitBundleMirror, "value")
.accept(new SimpleAnnotationValueVisitor7<String, Void>("") {
@Override
public String visitString(String value, Void v) {
return sanitizeBundleName(value);
}
}, null);
}
private String sanitizeBundleName(String name) {
String sanitized = name.trim().replaceAll("[^\\w\\d]", "_");
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, sanitized);
}
private int extractBundleId() {
return getAnnotationValue(codeSplitBundleMirror, "id")
.accept(new SimpleAnnotationValueVisitor7<Integer, Void>(-1) {
@Override
public Integer visitInt(int id, Void v) {
return id;
}
}, null);
}
private Type extractBundleClass() {
return getAnnotationValue(codeSplitBundleMirror, "bundleClass")
.accept(new SimpleAnnotationValueVisitor7<Type, Void>() {
@Override
public Type visitType(TypeMirror bundleClass, Void v) {
boolean isNotSpecified = asTypeElement(bundleClass).getQualifiedName()
.contentEquals(NoOpProviderBundle.class.getCanonicalName());
return isNotSpecified ? null : new Type(bundleClass);
}
}, null);
}
private void validateBundleConfiguration() {
if (!bundleName.isEmpty() && (id > -1 || bundleType != null)) {
logger.mandatoryWarning()
.context(proxyElement, codeSplitBundleMirror)
.log("@ProxyCodeSplitBundle used with both a bundle name and a bundle class. "
+ "Only one or the other can be used at once. "
+ "Defaulting to @ProxyStandard.");
valid = false;
} else if (bundleName.isEmpty() && id < 0 && bundleType == null) {
logger.mandatoryWarning()
.context(proxyElement, codeSplitBundleMirror)
.log("@ProxyCodeSplitBundle used with no configurations. "
+ "Either specify a bundle name or a Bundle Class with an ID. "
+ "Defaulting to @ProxyStandard.");
valid = false;
} else if ((id < 0 && bundleType != null) || (id > -1 && bundleType == null)) {
logger.mandatoryWarning()
.context(proxyElement, codeSplitBundleMirror)
.log("@ProxyCodeSplitBundle used with an invalid Bundle Class configuration. "
+ "Both a Bundle Class and an ID must be specified. "
+ "Defaulting to @ProxyStandard.");
valid = false;
} else {
valid = true;
}
}
@Override
public Collection<String> getImports() {
initialize();
if (isValid() && isManualBundle()) {
return bundleType.getImports();
}
return Collections.emptyList();
}
}