/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.contexts;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.whole.lang.commands.BooleanChangeCommand;
import org.whole.lang.commands.ByteChangeCommand;
import org.whole.lang.commands.CharChangeCommand;
import org.whole.lang.commands.DoubleChangeCommand;
import org.whole.lang.commands.FloatChangeCommand;
import org.whole.lang.commands.ICommand;
import org.whole.lang.commands.IntChangeCommand;
import org.whole.lang.commands.LongChangeCommand;
import org.whole.lang.commands.ShortChangeCommand;
import org.whole.lang.commands.StringChangeCommand;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.InternalIEntity;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.util.EntityUtils;
/**
* @author Riccardo Solmi
*/
public class IntensionalEntityContext extends AbstractEntityContext {
public IntensionalEntityContext(IEntity root) {
super(root);
}
protected IEntity entityContext(IEntity root) {
return new IntensionalEntityContext(root);
}
public boolean wIsEmpty() {
int size = wSize();
return size == 0 || (size == 1 && EntityUtils.isResolver(wGet(0)));
}
public int wSize() {
int size = entity.wSize();
ICommand cmd = wGetLastCommand();
while (contextTime < cmd.getExecutionTime()) {
switch (cmd.getKind()) {
case ADD:
size--;
break;
case REMOVE:
size++;
break;
}
cmd = cmd.getPrevCommand();
}
return size;
}
public int wIndexOf(IEntity value) {
ICommand cmd = ((InternalIEntity) value).wGetBindingCommand();
if (contextTime < cmd.getExecutionTime())
return -1;
return cmd.getSourceIndex();
}
protected IEntity wGetIEntity(int index) {
if (contextTime >= wGetLastCommand().getExecutionTime())
return entity.wGet(index);
else {
List<IEntity> children = wIndexedFeatures(entity, contextTime);
return children.get(index);
}
}
public boolean wContains(FeatureDescriptor feature) {
return entity.wContains(feature);
}
public boolean wRemove(FeatureDescriptor feature) {
return entity.wRemove(feature);
}
public IEntity wGet(FeatureDescriptor feature) {
return entityContext(wGetVersion(getEntityInScope(feature).wGet(feature), contextTime));
}
public void wSet(FeatureDescriptor feature, IEntityContext value) {
getEntityInScope(feature).wSet(feature, (IEntity) ((IntensionalEntityContext) value).entity);
}
protected IEntity getEntityInScope(FeatureDescriptor feature) {
IEntity e = entity;
do {
if (e.wContains(feature))
return e;
e = e.wGetParent();
} while (!EntityUtils.isNull(e));
throw new IllegalArgumentException("Feature is not in scope");
}
protected final ICommand wGetValueVersion(int contextTime) {
return wGetLastCommand().getCommand(contextTime);
}
public boolean wBooleanValue() {
return ((BooleanChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public byte wByteValue() {
return ((ByteChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public char wCharValue() {
return ((CharChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public double wDoubleValue() {
return ((DoubleChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public float wFloatValue() {
return ((FloatChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public int wIntValue() {
return ((IntChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public long wLongValue() {
return ((LongChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public short wShortValue() {
return ((ShortChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public String wStringValue() {
return ((StringChangeCommand) wGetValueVersion(contextTime)).newValue;
}
public Object wGetValue() {
return wGetValueVersion(contextTime).getNewObject();
}
public void wSetValue(boolean value) {
entity.wSetValue(value);
}
public void wSetValue(byte value) {
entity.wSetValue(value);
}
public void wSetValue(char value) {
entity.wSetValue(value);
}
public void wSetValue(double value) {
entity.wSetValue(value);
}
public void wSetValue(float value) {
entity.wSetValue(value);
}
public void wSetValue(int value) {
entity.wSetValue(value);
}
public void wSetValue(long value) {
entity.wSetValue(value);
}
public void wSetValue(short value) {
entity.wSetValue(value);
}
public void wSetValue(String value) {
entity.wSetValue(value);
}
public void wSetValue(Object value) {
entity.wSetValue(value);
}
private Map<IEntity, List<IEntity>> childrenCache = new WeakHashMap<IEntity, List<IEntity>>();
protected final IEntity wGetVersion(IEntity e, int contextTime) {
ICommand cmd = ((InternalIEntity) e).wGetBindingCommand();
if (cmd.getKind().isComposite()) {
List<IEntity> children = wIndexedFeatures(cmd.getSource(), contextTime);
return children.get(cmd.getSourceIndex());
} else
return cmd.getCommand(contextTime).getNewEntity();
}
protected final IEntity wGetPrevVersion(IEntity e) {
ICommand cmd = ((InternalIEntity) e).wGetBindingCommand();
if (cmd.getKind().isComposite()) {
IEntity source = cmd.getSource();
List<IEntity> children = wIndexedFeatures(source, ((InternalIEntity) source).wGetLastCommand().getPrevCommand().getExecutionTime());
return children.get(cmd.getSourceIndex());
} else
return cmd.getPrevCommand().getNewEntity();
}
@Deprecated
public final List<IEntity> wIndexedFeatures(IEntity e, int contextTime) {
List<IEntity> result = childrenCache.get(e);
if (result != null && this.contextTime == contextTime)
return result;
result = new ArrayList<IEntity>(e.wFeatures());
ICommand cmd = ((InternalIEntity) e).wGetLastCommand();
while (contextTime < cmd.getExecutionTime()) {
switch (cmd.getKind()) {
case ADD:
result.remove(cmd.getSourceIndex());
break;
case REMOVE:
result.add(cmd.getSourceIndex(), cmd.getOldEntity());
break;
case CHANGE:
result.set(cmd.getSourceIndex(), cmd.getOldEntity());
break;
}
cmd = cmd.getPrevCommand();
}
if (this.contextTime == contextTime)
childrenCache.put(e, result);
return result;
}
}