/******************************************************************************* * Copyright (c) 2011, 2015 Willink Transformations and others. * 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 * * Contributors: * E.D.Willink - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.pivot.internal.library.executor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; import org.eclipse.emf.ecore.EObject; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.CollectionType; import org.eclipse.ocl.pivot.CompleteInheritance; import org.eclipse.ocl.pivot.InheritanceFragment; import org.eclipse.ocl.pivot.ids.TypeId; import org.eclipse.ocl.pivot.internal.elements.AbstractExecutorClass; import org.eclipse.ocl.pivot.types.AbstractFragment; import org.eclipse.ocl.pivot.utilities.ClassUtil; /** * A ReflectiveType defines a Type using a compact representation suitable for efficient * execution. The representation is derived reflectively from a less efficient representation. */ public abstract class ReflectiveInheritance extends AbstractExecutorClass { protected static int computeFlags(org.eclipse.ocl.pivot.@NonNull Class asClass) { int flags = 0; if (asClass instanceof CollectionType) { CollectionType collectionType = (CollectionType)asClass; if (collectionType.isOrdered()) { flags |= ORDERED; } if (collectionType.isUnique()) { flags |= UNIQUE; } } TypeId typeId = asClass.getTypeId(); if (typeId == TypeId.OCL_ANY){ flags |= OCL_ANY; } else if (typeId == TypeId.OCL_VOID){ flags |= OCL_VOID; } else if (typeId == TypeId.OCL_INVALID){ flags |= OCL_INVALID; } if (asClass.isIsAbstract()) { flags |= ABSTRACT; } return flags; } /** * Depth ordered inheritance fragments. OclAny at depth 0, OclSelf at depth size-1. */ private @NonNull InheritanceFragment @Nullable [] fragments = null; /** * The index in fragments at which inheritance fragments at a given depth start. * depthIndexes[0] is always zero since OclAny is always at depth 0. * depthIndexes[depthIndexes.length-2] is always depthIndexes.length-1 since OclSelf is always at depth depthIndexes.length-2. * depthIndexes[depthIndexes.length-1] is always depthIndexes.length to provide an easy end stop. */ private int @Nullable [] indexes = null; /** * The Inheritances of sub-types that have been installed, and which must be * uninstalled in the event of an inheritance change for this Inheritance. */ private Set<ReflectiveInheritance> knownSubInheritances = null; public ReflectiveInheritance(@NonNull String name, int flags, ExecutorTypeParameter... typeParameters) { super(name, flags); } public void addSubInheritance(@NonNull ReflectiveInheritance subInheritance) { if (knownSubInheritances == null) { knownSubInheritances = new HashSet<ReflectiveInheritance>(); } knownSubInheritances.add(subInheritance); } protected abstract @NonNull AbstractFragment createFragment(@NonNull CompleteInheritance baseInheritance); @Override public @NonNull EObject createInstance() { throw new UnsupportedOperationException(); } @Override public @Nullable Object createInstance( @NonNull String value) { throw new UnsupportedOperationException(); } /** * Add this Inheritance and all un-installed super-Inheritances to inheritances, returning true if this * inheritance was already installed. */ public boolean gatherUninstalledInheritances(@NonNull List<ReflectiveInheritance> inheritances) { boolean gotOne = false; if (!inheritances.contains(this)) { inheritances.add(this); if (fragments == null) { for (CompleteInheritance superInheritance : getInitialSuperInheritances()) { if (superInheritance instanceof ReflectiveInheritance) { if (((ReflectiveInheritance)superInheritance).gatherUninstalledInheritances(inheritances)) { gotOne = true; // Transitively installed } } else { gotOne = true; // Statically installed } } } else { gotOne = true; // Locally installed } } return gotOne; } @Override public final @NonNull FragmentIterable getAllProperSuperFragments() { if (fragments == null) { initialize(); } @NonNull InheritanceFragment[] fragments2 = ClassUtil.nonNullState(fragments); return new FragmentIterable(fragments2, 0, fragments2.length-1); } @Override public final @NonNull FragmentIterable getAllSuperFragments() { if (fragments == null) { initialize(); } return new FragmentIterable(ClassUtil.nonNullState(fragments)); } @Override public final int getDepth() { if (indexes == null) { initialize(); } int @Nullable [] indexes2 = indexes; assert indexes2 != null; return indexes2.length-2; } @Override public InheritanceFragment getFragment(int fragmentNumber) { if ((fragments == null) && isOclAny()) { installOclAny(); } assert fragments != null; return fragments[fragmentNumber]; } @Override public @NonNull Iterable<@NonNull InheritanceFragment> getFragments() { @NonNull InheritanceFragment[] fragments2 = fragments; if (fragments2 == null) { initialize(); fragments2 = fragments; assert fragments2 != null; } return new FragmentIterable(fragments2); } @Override public int getIndex(int fragmentNumber) { int @Nullable [] indexes2 = indexes; assert indexes2 != null; return indexes2[fragmentNumber]; } @Override public int getIndexes(){ int @Nullable [] indexes2 = indexes; assert indexes2 != null; return indexes2.length; } /** * Return the immediate superinheritances without reference to the fragments. */ protected abstract @NonNull Iterable<@NonNull ? extends CompleteInheritance> getInitialSuperInheritances(); @Override public @NonNull InheritanceFragment getSelfFragment() { if (indexes == null) { initialize(); } @NonNull InheritanceFragment @Nullable [] fragments2 = fragments; assert fragments2 != null; InheritanceFragment fragment = getFragment(fragments2.length-1); if (fragment == null) { throw new IllegalStateException("No self fragment"); //$NON-NLS-1$ } return fragment; } @Override public final @NonNull FragmentIterable getSuperFragments(int depth) { int @Nullable [] indexes2 = indexes; assert indexes2 != null; return new FragmentIterable(ClassUtil.nonNullState(fragments), indexes2[depth], indexes2[depth+1]); } protected synchronized void initialize() { List<ReflectiveInheritance> uninstalledInheritances = new ArrayList<ReflectiveInheritance>(); // Detect missing OclAny inheritance // - any installed superclass must inherit from OclAny so ok. // - an all-uninstalled superclass list must include OclAny to be ok. if (!gatherUninstalledInheritances(uninstalledInheritances)) { // boolean containsOclAny = false; // for (DomainInheritance anInheritance : uninstalledInheritances) { // if (anInheritance.isOclAny()) { // containsOclAny = true; // break; // } // } // if (!containsOclAny) { // FIXME may be an rather than the OclAny - need a way to find the partial types. /* List<ReflectiveType> uninstalledInheritances2 = new ArrayList<ReflectiveType>(); gatherUninstalledInheritances(uninstalledInheritances2); assert uninstalledInheritances.contains(oclAnyInheritance); */ // } } // int oldPendingCount = uninstalledInheritances.size(); @SuppressWarnings("unused") List<ReflectiveInheritance> debugOldUninstalledInheritances = new ArrayList<ReflectiveInheritance>(uninstalledInheritances); while (true) { Boolean gotOne = false; for (ListIterator<ReflectiveInheritance> it = uninstalledInheritances.listIterator(); it.hasNext(); ) { ReflectiveInheritance uninstalledInheritance = it.next(); if (uninstalledInheritance.isInstallable()) { uninstalledInheritance.install(); it.remove(); gotOne = true; } } if (uninstalledInheritances.isEmpty()) { break; } // int newPendingCount = uninstalledInheritances.size(); if (!gotOne) { List<ReflectiveInheritance> debugNewUninstalledInheritances = new ArrayList<ReflectiveInheritance>(); gatherUninstalledInheritances(debugNewUninstalledInheritances); StringBuilder s = new StringBuilder(); s.append("Inheritance loop for "); //$NON-NLS-1$ for (ListIterator<ReflectiveInheritance> it = uninstalledInheritances.listIterator(); it.hasNext(); ) { ReflectiveInheritance uninstalledInheritance = it.next(); if (!uninstalledInheritance.isInstallable()) { s.append("\n "); //$NON-NLS-1$ s.append(uninstalledInheritance); } } throw new IllegalStateException(s.toString()); } // oldPendingCount = newPendingCount; } } /** * Install this Inheritance establishing its superClass tables and registering * it to be notified of any changes. * * @return true if installed, false if some superClass uninstallable */ public boolean install() { if (fragments != null) { return true; } // System.out.println("Install " + this); if (isOclAny()) { installOclAny(); } else { List<List<CompleteInheritance>> all = new ArrayList<List<CompleteInheritance>>(); for (CompleteInheritance superInheritance : getInitialSuperInheritances()) { // installIn(superInheritance, this, all); int j = 0; for (int i = 0; i < superInheritance.getIndexes()-1; i++) { List<CompleteInheritance> some = (i < all.size()) ? all.get(i) : null; if (some == null) { some = new ArrayList<CompleteInheritance>(); all.add(some); } int jMax = superInheritance.getIndex(i+1); for (; j < jMax; j++) { InheritanceFragment fragment = superInheritance.getFragment(j); CompleteInheritance baseInheritance = fragment.getBaseInheritance(); if (!some.contains(baseInheritance)) { some.add(baseInheritance); if (baseInheritance instanceof ReflectiveInheritance) { ((ReflectiveInheritance)baseInheritance).addSubInheritance(this); } } } } } int superDepths = all.size(); int superInheritances = 0; for (List<CompleteInheritance> some : all) { superInheritances += some.size(); } assert superDepths > 0; @NonNull InheritanceFragment @NonNull [] fragments2 = fragments = new @NonNull InheritanceFragment[superInheritances+1]; // +1 for OclSelf int @NonNull [] indexes2 = indexes = new int[superDepths+2]; // +1 for OclSelf, +1 for tail pointer int j = 0; indexes2[0] = 0; for (int i = 0; i < superDepths; i++) { for (CompleteInheritance some : all.get(i)) { if (some != null) { fragments2[j++] = createFragment(some); } } indexes2[i+1] = j; } indexes2[superDepths++] = j; fragments2[j++] = createFragment(this); indexes2[superDepths++] = j; } return true; } /** * Install the root OclAny Inheritance. */ protected final void installOclAny() { assert fragments == null; fragments = new @NonNull InheritanceFragment[] { createFragment(this) }; indexes = new int[] { 0, 1 }; } /** * Return true if this is installed or able to be installed. Returns false if some superclass * must be installed first. */ public boolean isInstallable() { if (isOclAny()) { return true; } if (fragments != null) { // System.out.println("isInstallable true (already) " + this); return true; } // DomainInheritance oclAnyInheritance = getOclAnyInheritance(); for (CompleteInheritance superInheritance : getInitialSuperInheritances()) { if ((superInheritance instanceof ReflectiveInheritance) && !((ReflectiveInheritance)superInheritance).isInstalled()) { // System.out.println("isInstallable false " + this); return false; } } // System.out.println("isInstallable true " + this); return true; } /** * Return true if this is installed. */ public boolean isInstalled() { return fragments != null; } public void removeSubInheritance(@NonNull ReflectiveInheritance subInheritance) { if (knownSubInheritances != null) { knownSubInheritances.remove(subInheritance); } } public void uninstall() { @NonNull InheritanceFragment @Nullable [] fragments2 = fragments; @SuppressWarnings("null")boolean isNonNull = fragments2 != null; // FIXME needed for JDT 4.5, not needed for JDT 4.6M4 if (isNonNull && (fragments2 != null)) { // System.out.println("Uninstall " + this); for (InheritanceFragment fragment : fragments2) { CompleteInheritance baseInheritance = fragment.getBaseInheritance(); if (baseInheritance instanceof ReflectiveInheritance) { ((ReflectiveInheritance)baseInheritance).removeSubInheritance(this); } } fragments = null; indexes = null; if (knownSubInheritances != null) { Set<ReflectiveInheritance> previouslyKnownSubInheritances = knownSubInheritances; knownSubInheritances = null; for (ReflectiveInheritance subInheritance : previouslyKnownSubInheritances) { subInheritance.uninstall(); } } } } }