use of ceylon.language.Entry in project ceylon by eclipse.
the class PartialImpl method initializeObject.
protected <Id> void initializeObject(TypeDescriptor $reified$Id, DeserializationContextImpl<Id> context, Serializable instance) {
NativeMap<ReachableReference, Id> state = (NativeMap<ReachableReference, Id>) getState();
// TODO If it were a map of java.lang.String we'd avoid pointless extra boxing
java.util.Collection<ReachableReference> reachables = instance.$references$();
int numLate = 0;
for (ReachableReference r : reachables) {
if (r instanceof Member && ((Member) r).getAttribute().getLate()) {
numLate++;
} else if (r instanceof Outer) {
numLate++;
}
}
if (state.getSize() < reachables.size() - numLate) {
HashSet<ReachableReference> missingNames = new HashSet<ReachableReference>();
java.util.Iterator<ReachableReference> it = reachables.iterator();
while (it.hasNext()) {
missingNames.add(it.next());
}
ceylon.language.Iterator<? extends ReachableReference> it2 = state.getKeys().iterator();
Object next;
while (((next = it2.next()) instanceof ReachableReference)) {
missingNames.remove(next);
}
throw insufficiantState(missingNames);
}
for (ReachableReference reference : reachables) {
if (reference instanceof Member) {
Member member = (Member) reference;
if (member.getAttribute().getLate() && !state.contains(member) || state.get(member) == uninitializedLateValue_.get_()) {
continue;
}
TypeDescriptor.Class classTypeDescriptor = getClassTypeDescriptor();
Entry<TypeDescriptor.Class, String> cacheKey = new Entry<TypeDescriptor.Class, String>(TypeDescriptor.klass(TypeDescriptor.Class.class), String.$TypeDescriptor$, classTypeDescriptor, String.instance(member.getAttribute().getQualifiedName()));
Type memberType = (Type) context.getMemberTypeCache().get(cacheKey);
if (memberType == null) {
Type pt = Metamodel.getModuleManager().getCachedType(classTypeDescriptor);
while (!pt.getDeclaration().getQualifiedNameString().equals(((ClassDeclaration) member.getAttribute().getContainer()).getQualifiedName())) {
pt = pt.getExtendedType();
}
FunctionOrValue attributeDeclaration = (FunctionOrValue) ((TypeDeclaration) pt.getDeclaration()).getMember(member.getAttribute().getName(), null, false);
TypedReference attributeType = pt.getTypedMember(attributeDeclaration, Collections.<Type>emptyList(), true);
memberType = attributeType.getType();
context.getMemberTypeCache().put(cacheKey, memberType);
}
Object referredInstance = getReferredInstance(context, state, member);
if (referredInstance instanceof Tuple) {
// Because tuples are special wrt reified types...
Id referredId = state.get(member);
Object r = context.leakInstance(referredId);
if (r instanceof PartialImpl) {
((PartialImpl) r).initialize($reified$Id, context);
}
}
Type instanceType = Metamodel.getModuleManager().getCachedType(Metamodel.getTypeDescriptor(referredInstance));
if (!instanceType.isSubtypeOf(memberType)) {
throw notAssignable(member, memberType, instanceType);
}
instance.$set$(member, referredInstance);
// the JVM will check the assignability, but we need to
// check assignability at the ceylon level, so we need to know
// / type of the attribute an the type that we're assigning.
// XXX this check is really expensive!
// we should cache the attribute type on the context
// when can we avoid this check.
// XXX we can cache MethodHandle setters on the context!
} else if (reference instanceof Outer) {
// instantiating member classes
continue;
} else {
throw new AssertionError("unexpected ReachableReference " + reference);
}
}
}
Aggregations