1 /******************************************************************************* 2 * Copyright (c) 2000, 2011 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 16 package org.eclipse.jdt.internal.corext.refactoring.typeconstraints; 17 18 import java.util.HashMap; 19 import java.util.Map; 20 21 import org.eclipse.jdt.core.dom.ITypeBinding; 22 23 public class TypeConstraintFactory implements ITypeConstraintFactory { 24 25 private Map<ConstraintVariable, Map<ConstraintVariable, Map<ConstraintOperator, SimpleTypeConstraint>>> fSimpleConstraints= new HashMap<>(); 26 private Map<ConstraintVariable, Map<String, CompositeOrTypeConstraint>> fOrConstraints= new HashMap<>(); 27 28 protected static final boolean PRINT_STATS= false; 29 protected int fNrCreated= 0; 30 protected int fNrFiltered= 0; 31 protected int fNrRetrieved= 0; 32 33 // Only to be called by the createXXXConstraint() methods createSimpleTypeConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator)34 private SimpleTypeConstraint createSimpleTypeConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator) { 35 if (fSimpleConstraints.containsKey(v1)){ 36 Map<ConstraintVariable, Map<ConstraintOperator, SimpleTypeConstraint>> m2= fSimpleConstraints.get(v1); 37 if (m2.containsKey(v2)){ 38 Map<ConstraintOperator, SimpleTypeConstraint> m3= m2.get(v2); 39 if (m3.containsKey(operator)){ 40 if (PRINT_STATS) fNrRetrieved++; 41 if (PRINT_STATS) dumpStats(); 42 return m3.get(operator); 43 } else { 44 return storeConstraint(v1, v2, operator, m3); 45 } 46 } else { 47 Map<ConstraintOperator, SimpleTypeConstraint> m3= new HashMap<>(); 48 m2.put(v2, m3); 49 return storeConstraint(v1, v2, operator, m3); 50 } 51 } else { 52 Map<ConstraintVariable, Map<ConstraintOperator, SimpleTypeConstraint>> m2= new HashMap<>(); 53 fSimpleConstraints.put(v1, m2); 54 Map<ConstraintOperator, SimpleTypeConstraint> m3= new HashMap<>(); 55 m2.put(v2, m3); 56 return storeConstraint(v1, v2, operator, m3); 57 } 58 } 59 storeConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator, Map<ConstraintOperator, SimpleTypeConstraint> m3)60 private SimpleTypeConstraint storeConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator, Map<ConstraintOperator, SimpleTypeConstraint> m3) { 61 SimpleTypeConstraint constraint= new SimpleTypeConstraint(v1, v2, operator); 62 m3.put(operator, constraint); 63 if (PRINT_STATS) fNrCreated++; 64 if (PRINT_STATS) dumpStats(); 65 return constraint; 66 } 67 createConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator)68 public ITypeConstraint[] createConstraint(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator){ 69 if (filter(v1, v2, operator)){ 70 return new ITypeConstraint[0]; 71 } else { 72 return new ITypeConstraint[]{ createSimpleTypeConstraint(v1, v2, operator) }; 73 } 74 } 75 76 @Override createSubtypeConstraint(ConstraintVariable v1, ConstraintVariable v2)77 public ITypeConstraint[] createSubtypeConstraint(ConstraintVariable v1, ConstraintVariable v2){ 78 return createConstraint(v1, v2, ConstraintOperator.createSubTypeOperator()); 79 } 80 81 @Override createStrictSubtypeConstraint(ConstraintVariable v1, ConstraintVariable v2)82 public ITypeConstraint[] createStrictSubtypeConstraint(ConstraintVariable v1, ConstraintVariable v2){ 83 return createConstraint(v1, v2, ConstraintOperator.createStrictSubtypeOperator()); 84 } 85 86 @Override createEqualsConstraint(ConstraintVariable v1, ConstraintVariable v2)87 public ITypeConstraint[] createEqualsConstraint(ConstraintVariable v1, ConstraintVariable v2){ 88 return createConstraint(v1, v2, ConstraintOperator.createEqualsOperator()); 89 } 90 91 @Override createDefinesConstraint(ConstraintVariable v1, ConstraintVariable v2)92 public ITypeConstraint[] createDefinesConstraint(ConstraintVariable v1, ConstraintVariable v2){ 93 return createConstraint(v1, v2, ConstraintOperator.createDefinesOperator()); 94 } 95 96 /** 97 * {@inheritDoc} 98 * Avoid creating constraints involving primitive types and self-constraints. 99 */ 100 @Override filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator)101 public boolean filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator operator) { 102 if ((v1.getBinding() != null && v1.getBinding().isPrimitive() && 103 v2.getBinding() != null && v2.getBinding().isPrimitive()) || 104 v1 == v2) { 105 if (PRINT_STATS) fNrFiltered++; 106 if (PRINT_STATS) dumpStats(); 107 return true; 108 } 109 return false; 110 } 111 112 @Override createCompositeOrTypeConstraint(ITypeConstraint[] constraints)113 public CompositeOrTypeConstraint createCompositeOrTypeConstraint(ITypeConstraint[] constraints){ 114 ConstraintVariable left= ((SimpleTypeConstraint)constraints[0]).getLeft(); 115 String bounds= ""; //$NON-NLS-1$ 116 for (ITypeConstraint constraint : constraints) { 117 ConstraintVariable right= ((SimpleTypeConstraint) constraint).getRight(); 118 ITypeBinding binding= right.getBinding(); 119 String typeName= binding.getQualifiedName(); 120 bounds= bounds + typeName +","; //$NON-NLS-1$ 121 } 122 123 if (fOrConstraints.containsKey(left)){ 124 Map<String, CompositeOrTypeConstraint> m2= fOrConstraints.get(left); 125 if (m2.containsKey(bounds)){ 126 if (PRINT_STATS) fNrRetrieved++; 127 if (PRINT_STATS) dumpStats(); 128 return m2.get(bounds); 129 } else { 130 CompositeOrTypeConstraint constraint= new CompositeOrTypeConstraint(constraints); 131 m2.put(bounds, constraint); 132 if (PRINT_STATS) dumpStats(); 133 if (PRINT_STATS) fNrCreated++; 134 return constraint; 135 } 136 } else { 137 Map<String, CompositeOrTypeConstraint> m2= new HashMap<>(); 138 fOrConstraints.put(left, m2); 139 CompositeOrTypeConstraint constraint= new CompositeOrTypeConstraint(constraints); 140 m2.put(bounds, constraint); 141 if (PRINT_STATS) dumpStats(); 142 if (PRINT_STATS) fNrCreated++; 143 return constraint; 144 } 145 } 146 dumpStats()147 protected void dumpStats() { 148 System.out.println("Constraints: " + fNrCreated + " created, " + fNrRetrieved + " retrieved, " + fNrFiltered + " filtered"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 149 } 150 151 } 152