001/**
002 * Copyright 2004-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.student.jpa.mojo;
017
018import java.util.HashSet;
019import java.util.List;
020import java.util.Set;
021
022import org.kuali.student.contract.model.MessageStructure;
023import org.kuali.student.contract.model.ServiceContractModel;
024import org.kuali.student.contract.model.ServiceMethod;
025import org.kuali.student.contract.model.ServiceMethodParameter;
026import org.kuali.student.contract.model.ServiceMethodReturnValue;
027import org.kuali.student.contract.model.XmlType;
028import org.kuali.student.contract.model.util.ModelFinder;
029import org.kuali.student.contract.model.validation.DictionaryValidationException;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033/**
034 *
035 * @author nwright
036 */
037public class JpaImplWriterForOneService {
038
039    private static final Logger log = LoggerFactory.getLogger(JpaImplWriterForOneService.class);
040    
041    protected ServiceContractModel model;
042    protected ModelFinder finder;
043    protected String directory;
044    protected String rootPackage;
045    protected String servKey;
046    protected boolean isR1;
047
048    public JpaImplWriterForOneService(ServiceContractModel model,
049            String directory,
050            String rootPackage,
051            String servKey,
052            boolean isR1) {
053        this.model = model;
054        this.finder = new ModelFinder(model);
055        this.directory = directory;
056        this.rootPackage = rootPackage;
057        this.servKey = servKey;
058        this.isR1 = isR1;
059    }
060
061    /**
062     * Write out the entire file
063     * @param out
064     */
065    public void write() {
066        List<ServiceMethod> methods = finder.getServiceMethodsInService(servKey);
067        if (methods.size() == 0) {
068            log.warn("No methods defined for servKey: {}", servKey);
069            return;
070        }
071
072        // the main servKey
073        log.info("Generating jpa impls for {}", servKey);
074        new JpaImplServiceWriter(model, directory, rootPackage, servKey, methods, isR1).write();
075        
076//        for (XmlType xmlType : getXmlTypesUsedJustByService()) {
077//            new JpaEntityWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1).write();
078//        }
079
080    }
081
082    private Set<XmlType> getXmlTypesUsedJustByService() {
083        Set<XmlType> set = new HashSet();
084        for (XmlType type : model.getXmlTypes()) {
085            if (type.getService().equalsIgnoreCase(servKey)) {
086                if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
087                    set.add(type);
088                }
089            }
090        }
091        return set;
092    }
093
094    private Set<XmlType> getXmlTypesUsedByService(List<ServiceMethod> methods) {
095        Set<XmlType> set = new HashSet();
096        for (ServiceMethod method : methods) {
097            if (method.getReturnValue() != null) {
098                ServiceMethodReturnValue ret = method.getReturnValue();
099                XmlType xmlType = finder.findXmlType(stripListFromType(ret.getType()));
100                if (xmlType == null) {
101                    throw new DictionaryValidationException("Method " + method.getService()
102                            + "." + method.getName()
103                            + "returns an unknown type, "
104                            + ret.getType());
105                }
106                addTypeAndAllSubTypes(set, xmlType);
107            }
108            for (ServiceMethodParameter param : method.getParameters()) {
109                XmlType xmlType = finder.findXmlType(stripListFromType(param.getType()));
110                if (xmlType == null) {
111                    throw new DictionaryValidationException("Parameter "
112                            + method.getService() + "."
113                            + method.getName() + "."
114                            + param.getName()
115                            + "has an unknown type, "
116                            + param.getType());
117                }
118                addTypeAndAllSubTypes(set, xmlType);
119            }
120        }
121        return set;
122    }
123
124    private void addTypeAndAllSubTypes(Set<XmlType> set, XmlType xmlType) {
125        if (xmlType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
126            if (set.add(xmlType)) {
127                addXmlTypesUsedByMessageStructure(set, xmlType);
128            }
129        }
130    }
131
132    private String stripListFromType(String type) {
133        if (type.endsWith("List")) {
134            type = type.substring(0, type.length() - "List".length());
135        }
136        return type;
137    }
138
139    private void addXmlTypesUsedByMessageStructure(Set<XmlType> set,
140            XmlType xmlType) {
141        ModelFinder finder = new ModelFinder(model);
142        for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
143            XmlType subType = finder.findXmlType(stripListFromType(ms.getType()));
144            if (subType == null) {
145                throw new DictionaryValidationException("MessageStructure field "
146                        + ms.getId()
147                        + " has an unknown type, "
148                        + ms.getType());
149            }
150            addTypeAndAllSubTypes(set, subType);
151        }
152    }
153}