001/* 002 * Copyright c 2018 Rusi Popov, MDA Tools.net All rights reserved. 003 * 004 * This program and the accompanying materials are made available under the terms of the 005 * Eclipse Public License v2.0 which accompanies this distribution, and is available at 006 * http://www.eclipse.org/legal/epl-v20.html 007 */ 008package net.mdatools.modelant.core.name; 009 010import java.util.ArrayList; 011import java.util.List; 012import java.util.Map; 013 014import javax.jmi.reflect.InvalidNameException; 015import javax.jmi.reflect.JmiException; 016import javax.jmi.reflect.RefBaseObject; 017import javax.jmi.reflect.RefClass; 018import javax.jmi.reflect.RefObject; 019import javax.jmi.reflect.RefPackage; 020import javax.jmi.reflect.RefStruct; 021 022import net.mdatools.modelant.core.api.Operation; 023import net.mdatools.modelant.core.api.model.ConstructOperation; 024import net.mdatools.modelant.core.api.model.ConstructProcedure; 025import net.mdatools.modelant.core.api.model.NameMapping; 026import net.mdatools.modelant.core.api.name.Name; 027import net.mdatools.modelant.core.api.name.PackageName; 028import net.mdatools.modelant.core.api.name.StructName; 029 030/** 031 * @author Rusi Popov (popovr@mdatools.net) 032 */ 033public class StructNameImpl extends NameImpl<Name<?>> implements StructName { 034 public StructNameImpl(String packageName) { 035 super(packageName); 036 } 037 038 public StructNameImpl(Name<?> parent, String name) { 039 super(parent, name); 040 } 041 042 public StructNameImpl(RefPackage extent, RefStruct struct) { 043 this(constructOwnerClassName(struct.refTypeName(), extent), 044 getStructName(struct)); 045 } 046 047 /** 048 * @param struct not null 049 * @return the name of the Struct's class from its qualified name 050 */ 051 private static String getStructName(RefStruct struct) { 052 String result; 053 List<String> names; 054 055 names = struct.refTypeName(); 056 result = names.get(names.size()-1); 057 058 return result; 059 } 060 061 /** 062 * @param qualifiedName not null, not empty qualified name of the Enum Class 063 * @param targetExtent not null 064 * @return the class name of that Enum 065 */ 066 private static Name<?> constructOwnerClassName(List<String> qualifiedName, RefPackage targetExtent) { 067 Name<?> result; 068 String name; 069 RefBaseObject namespace; 070 071 namespace = targetExtent; 072 result = null; 073 for (int i=0; i<qualifiedName.size()-1; i++) { 074 name = qualifiedName.get( i ); 075 076 if ( namespace instanceof RefPackage ) { // the current name is a name of a package or class, packageName is a name of a package so far 077 try { 078 namespace = ((RefPackage) namespace).refPackage( name ); 079 result = new PackageNameImpl((PackageName) result, name); 080 081 } catch (InvalidNameException ex) { // name is not a package, it could be only a class 082 namespace = ((RefPackage) namespace).refClass( name ); 083 result = new ClassNameImpl((PackageName) result, name); 084 } 085 } else { // namespace is a Class owning at most an enumeration 086 throw new IllegalArgumentException("Resolving "+qualifiedName 087 +" struct name, reached "+PRINT_MODEL_ELEMENT.execute( namespace ) 088 +" which cannot contain nested "+name); 089 } 090 } 091 return result; 092 } 093 094 /** 095 * @see net.mdatools.modelant.core.name.NameImpl#constructName(net.mdatools.modelant.core.api.name.Name, java.lang.String) 096 */ 097 public Name<Name<?>> constructName(Name<?> parent, String name) { 098 return new StructNameImpl(parent, name); 099 } 100 101 /** 102 * @see net.mdatools.modelant.core.api.name.Name#constructTransfromation() 103 */ 104 public ConstructProcedure<?> constructTransfromation() { 105 throw new IllegalStateException("This method should not be called by design"); 106 } 107 108 /** 109 * The Structs are instantiated through the model package in contrast to the classes, 110 * and there is no 111 * so locate the package in the target model that contains the target struct type and 112 * instantiate that struct. 113 * @param rootPackage not null extent 114 * @param fieldValues TODO 115 * @return non-null structure instance 116 * @throws JmiException when the struct does not exist 117 */ 118 private RefStruct construct(RefPackage targetExtent, List<?> fieldValues) throws JmiException { 119 RefStruct result; 120 Name<?> structClassNamespace; 121 PackageName structClassNamespaceNamespace; 122 RefPackage structClassNamespacePackage; 123 RefPackage structClassPackage; 124 RefClass structClassClass; 125 126 if ( getOwner() == null ) { 127 throw new InvalidNameException( toString(), "Expected a parent class or package name provided"); 128 } 129 130 structClassNamespace = getOwner(); 131 structClassNamespaceNamespace = (PackageName) structClassNamespace.getOwner(); 132 133 if ( structClassNamespaceNamespace != null ) { 134 structClassNamespacePackage = structClassNamespaceNamespace.getMetaPackage( targetExtent ); 135 } else { 136 structClassNamespacePackage = targetExtent; 137 } 138 139 // in enumClassNamespaceNamespace, enumClassNamespace could be a class or package 140 // try both options, which one will work 141 try { 142 structClassPackage = structClassNamespacePackage.refPackage( structClassNamespace.getName() ); 143 result = structClassPackage.refCreateStruct(getName(), fieldValues ); 144 145 } catch (InvalidNameException ex) { 146 structClassClass = structClassNamespacePackage.refClass( structClassNamespace.getName() ); 147 result = structClassClass.refCreateStruct(getName(), fieldValues ); 148 } 149 return result; 150 } 151 152 153 /** 154 * @see net.mdatools.modelant.core.api.name.StructName#constructCopyOperation() 155 */ 156 public ConstructOperation<RefStruct> constructCopyOperation() { 157 return new ConstructOperation<RefStruct>() { 158 public Operation<RefStruct> construct(RefPackage targetExtent, 159 Map<RefObject, RefObject> objectsMap, 160 NameMapping valueMapping) { 161 return new Operation<RefStruct>() { 162 public RefStruct execute(RefStruct struct) throws RuntimeException, IllegalArgumentException { 163 List<Object> values; 164 165 values = new ArrayList<>(); 166 for (String name : (List<String>) struct.refFieldNames()) { 167 values.add( struct.refGetValue( name ) ); 168 } 169 return StructNameImpl.this.construct( targetExtent, values ); 170 } 171 }; 172 } 173 }; 174 } 175}