/**
* Copyright 2011-2014 Asakusa Framework 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 com.asakusafw.compiler.repository;
import java.text.MessageFormat;
import com.asakusafw.compiler.common.JavaName;
import com.asakusafw.compiler.common.Precondition;
import com.asakusafw.compiler.flow.DataClass;
import com.asakusafw.runtime.value.ValueOption;
import com.asakusafw.utils.java.model.syntax.Expression;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
import com.asakusafw.utils.java.model.syntax.Statement;
import com.asakusafw.utils.java.model.syntax.Type;
import com.asakusafw.utils.java.model.util.ExpressionBuilder;
import com.asakusafw.utils.java.model.util.Models;
import com.asakusafw.utils.java.model.util.TypeBuilder;
/**
* {@link ValueOption}を元にした{@code DataClass.Property}の実装。
*/
public class ValueOptionProperty implements DataClass.Property {
private ModelFactory factory;
private String name;
private Class<? extends ValueOption<?>> optionClass;
/**
* インスタンスを生成する。
* @param factory ファクトリーオブジェクト
* @param name プロパティの名前
* @param optionClass プロパティのJavaでの型
* @throws IllegalArgumentException 引数に{@code null}が指定された場合
*/
public ValueOptionProperty(
ModelFactory factory,
String name,
Class<? extends ValueOption<?>> optionClass) {
Precondition.checkMustNotBeNull(factory, "factory"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(name, "name"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(optionClass, "optionClass"); //$NON-NLS-1$
this.factory = factory;
this.name = name;
this.optionClass = optionClass;
}
@Override
public String getName() {
return name;
}
@Override
public java.lang.reflect.Type getType() {
return optionClass;
}
@Override
public Expression createNewInstance(Type target) {
return new TypeBuilder(factory, target)
.newObject()
.toExpression();
}
@Override
public boolean canNull() {
return true;
}
@Override
public Expression createIsNull(Expression object) {
JavaName javaName = JavaName.of(name);
javaName.addFirst("get");
javaName.addLast("option");
return new ExpressionBuilder(factory, object)
.method(javaName.toMemberName())
.method("isNull")
.toExpression();
}
@Override
public Expression createGetter(Expression object) {
JavaName javaName = JavaName.of(name);
javaName.addFirst("get");
javaName.addLast("option");
return new ExpressionBuilder(factory, object)
.method(javaName.toMemberName())
.toExpression();
}
@Override
public Statement assign(Expression target, Expression source) {
return new ExpressionBuilder(factory, target)
.method("copyFrom", source)
.toStatement();
}
@Override
public Statement createGetter(Expression object, Expression target) {
return assign(target, createGetter(object));
}
@Override
public Statement createSetter(Expression object, Expression value) {
JavaName javaName = JavaName.of(name);
javaName.addFirst("set");
javaName.addLast("option");
return new ExpressionBuilder(factory, object)
.method(javaName.toMemberName(), value)
.toStatement();
}
@Override
public Statement createWriter(Expression object, Expression dataOutput) {
Precondition.checkMustNotBeNull(object, "object"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(dataOutput, "dataOutput"); //$NON-NLS-1$
return new ExpressionBuilder(factory, object)
.method("write", dataOutput)
.toStatement();
}
@Override
public Statement createReader(Expression object, Expression dataInput) {
Precondition.checkMustNotBeNull(object, "object"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(dataInput, "dataInput"); //$NON-NLS-1$
return new ExpressionBuilder(factory, object)
.method("readFields", dataInput)
.toStatement();
}
@Override
public Expression createHashCode(Expression source) {
Precondition.checkMustNotBeNull(source, "source"); //$NON-NLS-1$
return new ExpressionBuilder(factory, source)
.method("hashCode")
.toExpression();
}
@Override
public Expression createBytesSize(
Expression bytes,
Expression start,
Expression length) {
Precondition.checkMustNotBeNull(bytes, "bytes"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(start, "start"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(length, "length"); //$NON-NLS-1$
Type type = factory.newNamedType(Models.toName(factory, optionClass.getName()));
return new TypeBuilder(factory, type)
.method("getBytesLength", bytes, start, length)
.toExpression();
}
@Override
public Expression createBytesDiff(
Expression bytes1, Expression start1, Expression length1,
Expression bytes2, Expression start2, Expression length2) {
Precondition.checkMustNotBeNull(bytes1, "bytes1"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(start1, "start1"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(length1, "length1"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(bytes2, "bytes2"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(start2, "start2"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(length2, "length2"); //$NON-NLS-1$
Type type = factory.newNamedType(Models.toName(factory, optionClass.getName()));
return new TypeBuilder(factory, type)
.method("compareBytes",
bytes1, start1, length1,
bytes2, start2, length2)
.toExpression();
}
@Override
public Expression createValueDiff(Expression value1, Expression value2) {
Precondition.checkMustNotBeNull(value1, "value1"); //$NON-NLS-1$
Precondition.checkMustNotBeNull(value2, "value2"); //$NON-NLS-1$
return new ExpressionBuilder(factory, value1)
.method("compareTo", value2)
.toExpression();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + name.hashCode();
result = prime * result + optionClass.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ValueOptionProperty other = (ValueOptionProperty) obj;
if (name.equals(other.name) == false) {
return false;
}
if (optionClass.equals(other.optionClass) == false) {
return false;
}
return true;
}
@Override
public String toString() {
return MessageFormat.format(
"{0}({1}:{2})",
getClass().getSimpleName(),
getName(),
getType());
}
}